Setup the GUI layout
(self)
| 50 | self.load_config_direct(config_path) |
| 51 | |
| 52 | def setup_ui(self): |
| 53 | """Setup the GUI layout""" |
| 54 | # Menu bar |
| 55 | menubar = tk.Menu(self.root) |
| 56 | self.root.config(menu=menubar) |
| 57 | |
| 58 | file_menu = tk.Menu(menubar, tearoff=0) |
| 59 | menubar.add_cascade(label="File", menu=file_menu) |
| 60 | file_menu.add_command(label="Load Config", command=self.load_config) |
| 61 | file_menu.add_command(label="Save Points", command=self.save_points) |
| 62 | file_menu.add_separator() |
| 63 | file_menu.add_command(label="Exit", command=self.root.quit) |
| 64 | |
| 65 | # Top toolbar |
| 66 | toolbar = ttk.Frame(self.root) |
| 67 | toolbar.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5) |
| 68 | |
| 69 | ttk.Label(toolbar, text="Config:").pack(side=tk.LEFT) |
| 70 | self.config_label = ttk.Label(toolbar, text="None", foreground="gray") |
| 71 | self.config_label.pack(side=tk.LEFT, padx=5) |
| 72 | |
| 73 | ttk.Button(toolbar, text="Load Config", command=self.load_config).pack(side=tk.LEFT, padx=5) |
| 74 | ttk.Button(toolbar, text="Save All Points", command=self.save_points).pack(side=tk.LEFT, padx=5) |
| 75 | |
| 76 | # Video info |
| 77 | info_frame = ttk.Frame(self.root) |
| 78 | info_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5) |
| 79 | |
| 80 | self.video_label = ttk.Label(info_frame, text="Video: None", font=("Arial", 10, "bold")) |
| 81 | self.video_label.pack(side=tk.LEFT, padx=5) |
| 82 | |
| 83 | self.instruction_label = ttk.Label(info_frame, text="", foreground="blue") |
| 84 | self.instruction_label.pack(side=tk.LEFT, padx=10) |
| 85 | |
| 86 | # Frame navigation controls - COMPACT (Ctrl+←/→ shortcuts) |
| 87 | frame_nav = ttk.LabelFrame(self.root, text="Frame Navigation") |
| 88 | frame_nav.pack(side=tk.TOP, fill=tk.X, padx=5, pady=2) |
| 89 | |
| 90 | btn_frame = ttk.Frame(frame_nav) |
| 91 | btn_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=2) |
| 92 | |
| 93 | # Compact buttons |
| 94 | ttk.Button(btn_frame, text="<<", command=self.first_frame, width=3).pack(side=tk.LEFT, padx=1) |
| 95 | ttk.Button(btn_frame, text="<10", command=lambda: self.prev_frame(10), width=3).pack(side=tk.LEFT, padx=1) |
| 96 | ttk.Button(btn_frame, text="<", command=lambda: self.prev_frame(1), width=3).pack(side=tk.LEFT, padx=1) |
| 97 | |
| 98 | self.frame_label = ttk.Label(btn_frame, text="F: 0/0", font=("Arial", 9)) |
| 99 | self.frame_label.pack(side=tk.LEFT, padx=8) |
| 100 | |
| 101 | ttk.Button(btn_frame, text=">", command=lambda: self.next_frame(1), width=3).pack(side=tk.LEFT, padx=1) |
| 102 | ttk.Button(btn_frame, text="10>", command=lambda: self.next_frame(10), width=3).pack(side=tk.LEFT, padx=1) |
| 103 | ttk.Button(btn_frame, text=">>", command=self.last_frame, width=3).pack(side=tk.LEFT, padx=1) |
| 104 | |
| 105 | # Slider inline |
| 106 | self.frame_slider = ttk.Scale(btn_frame, from_=0, to=100, orient=tk.HORIZONTAL, command=self.on_slider_change, length=250) |
| 107 | self.frame_slider.pack(side=tk.LEFT, padx=5) |
| 108 | |
| 109 | # Frames with points inline |
no test coverage detected