Enable borderless fullscreen window with custom controls

This commit is contained in:
lm 2025-10-17 14:05:10 +02:00
parent 2077d574c3
commit 662f6b4df3
2 changed files with 90 additions and 20 deletions

View File

@ -21,11 +21,7 @@ class ICRSApp(
def __init__(self, root: tk.Tk): def __init__(self, root: tk.Tk):
self.root = root self.root = root
self.root.title("ICRS — Interactive Color Range Analyzer") self.root.title("ICRS — Interactive Color Range Analyzer")
try: self._setup_window()
self.root.state("zoomed")
except Exception:
pass
self.root.configure(bg="#f2f2f7")
# Theme and styling # Theme and styling
self.init_theme() self.init_theme()
@ -64,6 +60,13 @@ class ICRSApp(
self._init_copy_menu() self._init_copy_menu()
self.bring_to_front() self.bring_to_front()
def _setup_window(self) -> None:
self.root.overrideredirect(True)
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()
self.root.geometry(f"{screen_width}x{screen_height}+0+0")
self.root.configure(bg="#f2f2f7")
def start_app() -> None: def start_app() -> None:
"""Entry point used by the CLI script.""" """Entry point used by the CLI script."""

View File

@ -11,8 +11,10 @@ class UIBuilderMixin:
"""Constructs the Tkinter UI and common widgets.""" """Constructs the Tkinter UI and common widgets."""
def setup_ui(self) -> None: def setup_ui(self) -> None:
self._create_titlebar()
toolbar = ttk.Frame(self.root) toolbar = ttk.Frame(self.root)
toolbar.pack(fill=tk.X, padx=12, pady=8) toolbar.pack(fill=tk.X, padx=12, pady=0)
buttons = [ buttons = [
("📂 Bild laden", self.load_image), ("📂 Bild laden", self.load_image),
("📁 Ordner laden", self.load_folder), ("📁 Ordner laden", self.load_folder),
@ -71,11 +73,13 @@ class UIBuilderMixin:
left_column = ttk.Frame(main) left_column = ttk.Frame(main)
left_column.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 6)) left_column.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 6))
left_column.grid_columnconfigure(1, weight=1)
left_column.grid_rowconfigure(0, weight=1)
self._create_navigation_button(left_column, "", self.show_previous_image) self._create_navigation_button(left_column, "", self.show_previous_image, column=0)
self.canvas_orig = tk.Canvas(left_column, bg="#1e1e1e", highlightthickness=0, relief="flat") self.canvas_orig = tk.Canvas(left_column, bg="#1e1e1e", highlightthickness=0, relief="flat")
self.canvas_orig.pack(fill=tk.BOTH, expand=True) self.canvas_orig.grid(row=0, column=1, sticky="nsew")
self.canvas_orig.bind("<Button-1>", self.on_canvas_click) self.canvas_orig.bind("<Button-1>", self.on_canvas_click)
self.canvas_orig.bind("<ButtonPress-3>", self._exclude_start) self.canvas_orig.bind("<ButtonPress-3>", self._exclude_start)
self.canvas_orig.bind("<B3-Motion>", self._exclude_drag) self.canvas_orig.bind("<B3-Motion>", self._exclude_drag)
@ -83,10 +87,13 @@ class UIBuilderMixin:
right_column = ttk.Frame(main) right_column = ttk.Frame(main)
right_column.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(6, 0)) right_column.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(6, 0))
right_column.grid_columnconfigure(0, weight=1)
right_column.grid_rowconfigure(0, weight=1)
self.canvas_overlay = tk.Canvas(right_column, bg="#1e1e1e", highlightthickness=0, relief="flat") self.canvas_overlay = tk.Canvas(right_column, bg="#1e1e1e", highlightthickness=0, relief="flat")
self.canvas_overlay.pack(fill=tk.BOTH, expand=True) self.canvas_overlay.grid(row=0, column=0, sticky="nsew")
self._create_navigation_button(right_column, "", self.show_next_image) self._create_navigation_button(right_column, "", self.show_next_image, column=1)
info_frame = ttk.Frame(self.root) info_frame = ttk.Frame(self.root)
info_frame.pack(fill=tk.X, padx=12, pady=(0, 12)) info_frame.pack(fill=tk.X, padx=12, pady=(0, 12))
@ -113,6 +120,7 @@ class UIBuilderMixin:
self._attach_copy_menu(self.ratio_label) self._attach_copy_menu(self.ratio_label)
self.root.bind("<Escape>", self.disable_pick_mode) self.root.bind("<Escape>", self.disable_pick_mode)
self.root.bind("<ButtonPress-1>", self._maybe_focus_window)
def add_slider_with_value(self, parent, text, var, minimum, maximum, column=0): def add_slider_with_value(self, parent, text, var, minimum, maximum, column=0):
cell = ttk.Frame(parent) cell = ttk.Frame(parent)
@ -317,24 +325,83 @@ class UIBuilderMixin:
] ]
return canvas.create_polygon(points, smooth=True, splinesteps=24, **kwargs) return canvas.create_polygon(points, smooth=True, splinesteps=24, **kwargs)
def _create_navigation_button(self, container, symbol: str, command) -> None: def _create_navigation_button(self, container, symbol: str, command, *, column: int) -> None:
wrapper = ttk.Frame(container) bg = self.root.cget("bg") if hasattr(self.root, "cget") else "#f2f2f7"
wrapper.pack(fill=tk.Y) container.grid_rowconfigure(0, weight=1)
btn = tk.Button( btn = tk.Button(
wrapper, container,
text=symbol, text=symbol,
command=command, command=command,
font=("Segoe UI", 18, "bold"), font=("Segoe UI", 26, "bold"),
relief="flat", relief="flat",
borderwidth=0, borderwidth=0,
background="#00000000", background=bg,
activebackground="#00000000", activebackground=bg,
highlightthickness=0, highlightthickness=0,
cursor="hand2", cursor="hand2",
width=2,
) )
btn.pack(side=tk.TOP, pady=12) btn.grid(row=0, column=column, sticky="ns", padx=6)
wrapper.pack_propagate(False)
def _create_titlebar(self) -> None:
bar_bg = "#1f1f1f"
title_bar = tk.Frame(self.root, bg=bar_bg, relief="flat", height=34)
title_bar.pack(fill=tk.X, side=tk.TOP)
title_bar.pack_propagate(False)
title_label = tk.Label(
title_bar,
text="ICRS — Interactive Color Range Analyzer",
bg=bar_bg,
fg="#f5f5f5",
font=("Segoe UI", 11, "bold"),
anchor="w",
)
title_label.pack(side=tk.LEFT, padx=12)
close_btn = tk.Button(
title_bar,
text="",
command=self._close_app,
bg=bar_bg,
fg="#f5f5f5",
activebackground="#ff3b30",
activeforeground="#ffffff",
borderwidth=0,
highlightthickness=0,
relief="flat",
font=("Segoe UI", 10, "bold"),
cursor="hand2",
width=3,
)
close_btn.pack(side=tk.RIGHT, padx=8, pady=4)
for widget in (title_bar, title_label):
widget.bind("<ButtonPress-1>", self._start_window_drag)
widget.bind("<B1-Motion>", self._perform_window_drag)
def _close_app(self) -> None:
try:
self.root.destroy()
except Exception:
pass
def _start_window_drag(self, event) -> None:
self._drag_offset = (event.x_root - self.root.winfo_rootx(), event.y_root - self.root.winfo_rooty())
def _perform_window_drag(self, event) -> None:
offset = getattr(self, "_drag_offset", None)
if offset is None:
return
x = event.x_root - offset[0]
y = event.y_root - offset[1]
self.root.geometry(f"+{x}+{y}")
def _maybe_focus_window(self, _event) -> None:
try:
self.root.focus_set()
except Exception:
pass
def _toolbar_palette(self) -> dict[str, str]: def _toolbar_palette(self) -> dict[str, str]:
is_dark = getattr(self, "theme", "light") == "dark" is_dark = getattr(self, "theme", "light") == "dark"