Загрузка данных


import tkinter as tk
from PIL import Image, ImageTk
import os

def open_window(title):
    """Универсальная заглушка для открытия новых интерфейсов."""
    # Проверяем, существует ли главное окно app и полностью ли оно инициализировано
    if not app or not hasattr(app, 'winfo_exists') or not app.winfo_exists():
        return

    win = tk.Toplevel(app)
    win.title(title)
    
    x = app.winfo_x() + 50
    y = app.winfo_y() + 50
    win.geometry(f"+{x}+{y}")
    
    win.transient(app)
    win.grab_set()
    
    lbl = tk.Label(win, text=f"Здесь будет интерфейс:\n{title}", font=("Arial", 14), pady=20)
    lbl.pack()
    
    ok_btn = tk.Button(win, text="Закрыть", command=win.destroy, width=10)
    ok_btn.pack(pady=10)

class MainInterface(tk.Tk):
    def __init__(self):
        super().__init__()
        
        self.title("ДОЗОР -- Heri-Hodie-Cras")
        self.geometry("458x360") 
        self.resizable(False, False)
        
        bg_color = "#EEEEEE"
        self.configure(bg=bg_color)

        main_frame = tk.Frame(self, bg=bg_color)
        main_frame.pack(padx=1, pady=1, fill='both', expand=True)

        button_width = 20
        button_height = 2
        button_font = ("Arial", 12, "bold")

        for i in range(7): 
            main_frame.grid_rowconfigure(i, weight=0)
        
        main_frame.grid_columnconfigure(0, minsize=210, weight=0) 
        main_frame.grid_columnconfigure(1, minsize=235, weight=0) 

        self.active_popup = None
        
        left_texts = [
            ["Администратор", [("Пользователи", "users"), ("Базы данных", "db")]],
            ["Менеджер базы", [("Менеджер группы", "group"), ("Менеджер показателей", "metrics")]],
            ["Эксперты", [("Создание файлов", "create_files"), ("Агрегирование файлов", "aggregate")]],
            ["Проект", [("Создать", "new"), ("Редактировать", "edit"), ("В архив", "archive")]],
            ["Прогнозирование", []]
        ]

        # --- ЛЕВАЯ ПАНЕЛЬ ---
        for row_index, item in enumerate(left_texts):
            btn_text = item[0]
            
            btn = tk.Button(
                main_frame, 
                text=btn_text, 
                font=button_font, 
                width=button_width, 
                height=button_height,
                anchor="w",
                command=lambda r=row_index, name=btn_text: self.show_dropdown(name, r)
            )
            btn.grid(row=row_index, column=0, padx=5, pady=5, sticky="ew")

        # --- ПРАВАЯ ПАНЕЛЬ ---
        right_box = tk.Frame(main_frame, bg=bg_color, width=235, height=300)
        right_box.grid(row=0, column=1, rowspan=6, pady=5, sticky="nsew", padx=(0, 5)) 
        right_box.grid_propagate(False) 
        right_box.columnconfigure(0, weight=1)

        picture_frame = tk.Frame(right_box, bg="#d9ead3", highlightbackground="gray", highlightthickness=1, width=225, height=160)
        picture_frame.place(relx=0.5, y=5, anchor="n") 
        picture_frame.grid_propagate(False)

        current_dir = os.path.dirname(os.path.abspath(__file__))
        image_path = os.path.join(current_dir, "images", "Сова1.png")

        try:
            original_img = Image.open(image_path)
            target_w, target_h = 215, 130 
            
            img_ratio = original_img.width / original_img.height
            box_ratio = target_w / target_h
            if img_ratio > box_ratio:
                new_w, new_h = target_w, int(target_w / img_ratio)
            else:
                new_w, new_h = int(target_h * img_ratio), target_h
                
            resized_img = original_img.resize((new_w, new_h), resample=Image.LANCZOS)
            self.tk_image = ImageTk.PhotoImage(resized_img)
            
            label = tk.Label(picture_frame, image=self.tk_image, bg="#d9ead3", borderwidth=0)
            label.image = self.tk_image
            label.place(relx=0.5, rely=0.5, anchor='center', width=new_w, height=new_h)

        except Exception as e:
            print(f"[FATAL IMAGE ERROR]: {e}") 
            canvas = tk.Canvas(picture_frame, width=225, height=160, bg="red", highlightthickness=0)
            canvas.create_text(112, 80, text="IMG\nFAIL", fill="white")
            canvas.place(x=0, y=0, relwidth=1, relheight=1)

        spacer = tk.Frame(right_box, bg=bg_color, height=1) 
        spacer.grid(row=0, column=0, pady=(170, 10), sticky="ew") 

        # --- ФИКС: ДОБАВЛЕН НЕВИДИМЫЙ РАЗДЕЛИТЕЛЬ ---
        # Этот Frame заберет на себя те самые 2-3 пикселя сдвига,
        # создав жесткий отступ сверху для кнопок.
        upper_padding = tk.Frame(right_box, bg=bg_color, height=3) 
        upper_padding.grid(row=1, column=0) 

        btn6 = tk.Button(right_box, text="Руководство", font=button_font, width=button_width, height=button_height)
        btn6.grid(row=2, column=0, ipadx=10, pady=(0, 5), sticky="ew") 

        btn7 = tk.Button(right_box, text="О программе", font=button_font, width=button_width, height=button_height)
        btn7.grid(row=3, column=0, ipadx=10, pady=(5, 15), sticky="ew")

        # --- ПОДВАЛ ---
        footer_frame = tk.Frame(main_frame, bg="#0078D7")
        footer_frame.grid(row=6, column=0, columnspan=2, sticky="ew", pady=(10, 0))

        footer_label = tk.Label(
            footer_frame,
            text="Copyright © Минск, НИИ, 2027 год",
            fg="#FF8C00",
            bg="#0078D7",
            font=("Arial", 12, "bold")
        )
        footer_label.pack(expand=True, ipady=4)

        # Закрытие при клике мимо
        self.bind("<Button-1>", self.close_popup_global)

    def show_dropdown(self, menu_name, base_row):
        """Показывает всплывающее окно под кнопкой."""
        
        if self.active_popup is not None:
            self.active_popup.destroy()

        data = None
        lookup = {
            "Администратор": [("Пользователи", "users"), ("Базы данных", "db")],
            "Менеджер базы": [("Менеджер группы", "group"), ("Менеджер показателей", "metrics")],
            "Эксперты": [("Создание файлов", "create_files"), ("Агрегирование файлов", "aggregate")],
            "Проект": [("Создать", "new"), ("Редактировать", "edit"), ("В архив", "archive")]
        }
        data = lookup.get(menu_name, [])

        if not data:
            return

        # Координаты относительно экрана
        x = self.winfo_rootx() + 5
        y = self.winfo_rooty() + (base_row * 35) + 50

        popup = tk.Toplevel(self)
        popup.overrideredirect(True)
        popup.geometry(f"+{x}+{y}")
        
        popup_frame = tk.Frame(popup, bg="#F9F9F9", bd=1, relief="solid")
        popup_frame.pack()

        for sub_text, _ in data:
            # ВАЖНО: Сначала уничтожаем popup, а потом вызываем функцию!
            sub_btn = tk.Button(
                popup_frame, 
                text=sub_text, 
                font=("Arial", 11), 
                width=20, 
                height=1,
                anchor="w",
                bd=0,
                relief="flat",
                cursor="hand2",
                command=lambda t=sub_text, w=popup: (w.destroy(), open_window(t))
            )
            sub_btn.pack(fill="x", ipadx=5, ipady=3)

            sep = tk.Frame(popup_frame, bg="#E0E0E0", height=1)
            sep.pack(fill="x")

        self.active_popup = popup

    def on_submenu_select(self, title, popup_widget):
        """Этот метод больше не нужен, логика перенесена прямо в Button"""
        pass

    def close_popup_global(self, event):
        """Закрытие меню, если кликнули по пустому месту."""
        if self.active_popup is not None:
            widget = event.widget
            while widget:
                if widget == self.active_popup:
                    return
                widget = widget.master
            
            self.active_popup.destroy()
            self.active_popup = None

# Глобальная переменная
app = None

if __name__ == "__main__":
    app = MainInterface()
    app.mainloop()