import threading import tkinter as tk from tkinter import Menu from tkinter import ttk from app.ConfigMgr import ConfigMgr from app.chat_server.Server import Server from app.widgets import ClockLabel from app.widgets.ChatTab import ChatTab from app.widgets.MusicDownloadTab import MusicDownloadTab from app.widgets.MusicPlayerTab import MusicPlayerTab from app.widgets.TicTacToeTab import TicTacToeTab from app.widgets.TodoTab import TodoTab from app.widgets.UsageLabels import CPULabel, RAMLabel, BatteryLabel, NetworkLabel from app.widgets.WeatherTab import WeatherTab from app.widgets.WebScrapingTab import WebScrapingTab stop_event = threading.Event() def on_closing(): # Kill all threads that are linked to the stop_event # This ensures that execution is thread-safe stop_event.set() # Close the main window root.quit() root.destroy() def on_config_changed(): chat_frame.change_server_url(config_manager.config["Chat"]["server"]) chat_frame.change_sender_name(config_manager.config["Chat"]["name"]) weather_tab.changeCity(config_manager.config["Weather"]["city"]) # Create the main window root = tk.Tk() root.title("Responsive Window") root.geometry("1150x700") config_manager = ConfigMgr(root, config_changed_listener=on_config_changed) server = Server(host="localhost", port=2020, stop_event=stop_event) # Configure the main window to be responsive root.columnconfigure(0, weight=0) root.columnconfigure(1, weight=1) root.columnconfigure(2, weight=0) root.rowconfigure(0, weight=1) root.rowconfigure(1, weight=0) # Create the top menu menu_bar = Menu(root) file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="New") file_menu.add_command(label="Open") file_menu.add_separator() file_menu.add_command(label="Config", command=config_manager.display_config_window) file_menu.add_command(label="Exit", command=on_closing) edit_menu = Menu(menu_bar, tearoff=0) edit_menu.add_command(label="Copy") edit_menu.add_command(label="Paste") menu_bar.add_cascade(label="File", menu=file_menu) menu_bar.add_cascade(label="Edit", menu=edit_menu) root.config(menu=menu_bar) # Create the side and central frames frame_left = tk.Frame(root, bg="lightblue", width=300) frame_center = tk.Frame(root, bg="white") frame_right = tk.Frame(root, bg="lightgreen", width=300) # Place the side and central frames frame_left.grid(row=0, column=0, sticky="ns") frame_center.grid(row=0, column=1, sticky="nsew") frame_right.grid(row=0, column=2, sticky="ns") # Configure the fixed sizes of the side frames frame_left.grid_propagate(False) frame_right.grid_propagate(False) # Configure the left frame to have three rows frame_left.rowconfigure(0, weight=1) frame_left.rowconfigure(1, weight=0) frame_left.rowconfigure(2, weight=0) # Add weather tab to the left frame, occupying 1/3 of the height weather_tab = WeatherTab(frame_left, stop_event=stop_event, city=config_manager.config["Weather"]["city"], refresh_rate=300) weather_tab.grid(row=0, column=0, sticky="nsew") # Adjust the remaining rows to occupy the rest of the space frame_left.rowconfigure(1, weight=2) frame_left.rowconfigure(2, weight=2) # Divide the central frame into two parts (top variable and bottom fixed) frame_center.rowconfigure(0, weight=1) frame_center.rowconfigure(1, weight=0) frame_center.columnconfigure(0, weight=1) # Create subframes within the central frame frame_top = tk.Frame(frame_center, bg="lightyellow") frame_bottom = tk.Frame(frame_center, bg="lightgray", height=100) # Place the subframes within the central frame frame_top.grid(row=0, column=0, sticky="nsew") frame_bottom.grid(row=1, column=0, sticky="ew") # Fix the size of the bottom part frame_bottom.grid_propagate(False) # Create the status bar status_bar = tk.Label(root, text="Status bar", bg="lightgray", anchor="w") status_bar.grid(row=1, column=0, columnspan=3, sticky="ew") # Notebook for widgets style = ttk.Style() style.configure("CustomNotebook.TNotebook.Tab", font=("Arial", 12, "bold")) notebook = ttk.Notebook(frame_top, style="CustomNotebook.TNotebook") notebook.pack(fill="both", expand=True) # Add the tabs to the notebook music_download_tab = MusicDownloadTab(notebook, stop_event=stop_event) music_download_tab.pack(fill="both", expand=True) notebook.add(music_download_tab, text="Music Download") # Add the TodoTab to the notebook todo_tab = TodoTab(notebook, stop_event=stop_event) todo_tab.pack(fill="both", expand=True) notebook.add(todo_tab, text="Todo List") # Add the TodoTab to the notebook tic_tac_toe_tab = TicTacToeTab(notebook, stop_event=stop_event) tic_tac_toe_tab.pack(fill="both", expand=True) notebook.add(tic_tac_toe_tab, text="Tic Tac Toe") # Add the TodoTab to the notebook web_scraping_tab = WebScrapingTab(notebook, stop_event=stop_event) web_scraping_tab.pack(fill="both", expand=True) notebook.add(web_scraping_tab, text="Web Scraping") # Create the chat and music player frames within the right frame frame_chat = tk.Frame(frame_right, bg="lightgreen") frame_music_player = tk.Frame(frame_right) # Place the chat and music player frames within the right frame frame_chat.grid(row=0, column=0, sticky="nsew") frame_music_player.grid(row=1, column=0, sticky="nsew") # Configure the right frame to be responsive frame_right.rowconfigure(0, weight=3) frame_right.rowconfigure(1, weight=1) frame_right.columnconfigure(0, weight=1) # Create and place the chat frame and music player tab chat_frame = ChatTab(frame_chat, chat_server_url=config_manager.config["Chat"]["server"], sender_name=config_manager.config["Chat"]["name"], stop_event=stop_event, width=200, bg="lightgreen", refresh_rate=1) chat_frame.pack(fill="both", expand=True) music_player = MusicPlayerTab(frame_music_player, stop_event=stop_event, refresh_rate=5) music_player.pack(fill="both", expand=True) label_cpu = CPULabel(status_bar, bg="lightgreen", font=("Helvetica", 10), relief="groove", anchor="center", width=10, stop_event=stop_event, refresh_rate=1) label_ram = RAMLabel(status_bar, bg="lightcoral", font=("Helvetica", 10), relief="groove", anchor="center", width=10, stop_event=stop_event, refresh_rate=3) label_battery = BatteryLabel(status_bar, bg="lightblue", font=("Helvetica", 10), relief="groove", anchor="center", width=20, stop_event=stop_event, refresh_rate=10) label_net = NetworkLabel(status_bar, text="Network", bg="lightpink", font=("Helvetica", 10), relief="groove", anchor="center", width=20, stop_event=stop_event, refresh_rate=5) label_time = ClockLabel(status_bar, font=("Helvetica", 12), bd=1, fg="darkblue", relief="sunken", anchor="center", width=20, stop_event=stop_event, refresh_rate=0.5) label_cpu.pack(side="left", fill="both", expand=True) label_ram.pack(side="left", fill="both", expand=True) label_battery.pack(side="left", fill="both", expand=True) label_net.pack(side="left", fill="both", expand=True) label_time.pack(side="right", fill="both", expand=True) root.protocol("WM_DELETE_WINDOW", on_closing) # Run the application root.mainloop()