Open MartinThoma opened 9 months ago
Looking at https://www.pythonguis.com/faq/which-python-gui-library/, it seems that PyQt6 or PySide6.
https://www.pythonguis.com/faq/pyqt6-vs-pyside6/ : I would need to use GPL if I use PyQt6.
https://stackoverflow.com/questions/6888750/pyqt-or-pyside-which-one-to-use
Pyside6 seems a bit more pythonic
PyInstaller supports PyQt
Other interesting frontends:
We could have a base class:
from abc import ABC, abstractmethod
class Frontend(ABC):
def __init__(self, cfg):
self.cfg = cfg
self.width = None
self.height = None
self.x = None
self.y = None
def set_geometry(self, width: int, height: int, x=0, y=0) -> None:
self.width = width
self.height = height
self.x = x
self.y = y
def set_title(self, title: str) -> None:
self.title = title
def bind(self, event, callback) -> None:
self.root.bind(event, callback)
@abstractmethod
def run(self):
pass
and classes implementing it:
from tkinter import Tk, Label
import tkinter as tk
from tkinter import messagebox, ttk
from tkinter.simpledialog import askstring
from flitz.frontends.base import Frontend
from flitz.config import Config
from pathlib import Path
class TkinterFrontend(Frontend):
def __init__(self, cfg: Config):
self.cfg = cfg
self.root = Tk()
self.set_geometry(width=self.cfg.window.width, height=self.cfg.window.height)
self.root.configure(background=self.cfg.background_color)
self.root.rowconfigure(0, weight=0, minsize=45)
self.root.rowconfigure(1, weight=1)
self.root.columnconfigure(0, weight=0, minsize=80, uniform="group1")
self.root.columnconfigure(1, weight=85, uniform="group1")
self.root.columnconfigure(2, weight=5, uniform="group1")
self.style = ttk.Style()
self.style.theme_use("clam") # necessary to get the selection highlight
self.style.configure(
"Treeview.Heading",
font=(self.cfg.font, self.cfg.font_size),
)
self.style.map(
"Treeview",
foreground=[
("selected", self.cfg.selection.text_color),
(None, self.cfg.text_color),
],
background=[
# Adding `(None, self.cfg.background_color)` here makes the
# selection not work anymore
("selected", self.cfg.selection.background_color),
],
fieldbackground=self.cfg.background_color,
)
# Set window icon (you need to provide a suitable icon file)
icon_path = str(Path(__file__).resolve().parent / "../icon.gif")
img = tk.Image("photo", file=icon_path)
self.root.tk.call("wm", "iconphoto", self.root._w, img) # type: ignore[attr-defined]
def set_geometry(self, width, height, x=0, y=0):
self.width = width
self.height = height
self.x = x
self.y = y
self.root.geometry(f"{self.width}x{self.height}")
def set_title(self, title: str) -> None:
self.title = title
self.root.title(self.title)
def bind(self, event, callback) -> None:
pass
def run(self):
label = Label(self.root, text="Tkinter GUI")
label.pack()
self.root.mainloop()
The problem is how to set the layout. The tk.Frame
/ pack concept of tkinter likely doesn't translate properly to other GUI frameworks
The next issue is that some front-end elements have direct connections to the application state which again should trigger other front-end components to change:
I've introduced a on_current_path_change
to trigger all changes, but that currently is in the main application. I could pass a reference to the main application to the frontend... I'm not sure if that is a good idea.
Instead, I could introduce a "controller".
I'm uncertain if this makes sense, but maximum flexibility would be to have the option to implement alternative frontends.
Requirements