🍵️

2021-11-19

Lightweight, Simple, and Cross-Platform GUI Programming?

I've probably complained about this in a hundred places a thousand times by now, but things happen and evolve (allegedly) and perhaps a solution is nigh in sight.

I generally hate GUI programming. It always turns into a convoluted mess of components in components in components with triggers and events and everything. And then enter all problems with resizing windows. If a tool is 1,000 lines of code the GUI for it is probably going to be 10,000. The only sane tool I've found is actually to make a webapp. But I'm not interesting in making an Electron app, because that makes every tiny little program hilariously bloated by design.

What I'm looking for is something that's easy and relatively fast to develop with, and is lightweight and snappy to use. Preferably cross-platform, but Linux only works fine too.

The latest I've looked at is tkinter in python. It's not insane, and it builds functional interfaces. It's not overly verbose either. I built a GUI with it that had a row of three buttons and a text field, and a tabbed window underneath. It was less than 50 lines of code. Possibly the best I've found so far.

Tkinter's weakness is the number of components that need to be defined and added to each other, and keeping track of what the layout within each component is. This is the code for the interface itself:

root = Tk()
root.title("TESTWINDOW")
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)

mainframe = ttk.Frame(root, padding="0 10")
mainframe.grid(column=0, row=0, sticky=(N, S, E, W))

ttk.Button(mainframe, text='ONE').grid(column=0, row=0, sticky=(N, W))
ttk.Button(mainframe, text='TWO').grid(column=1, row=0, sticky=(N, W))
ttk.Button(mainframe, text='THREE').grid(column=2, row=0, sticky=(N, W))
ttk.Entry(mainframe, width=200).grid(column=3, row=0, sticky=(E, W), padx=5)

mainframe.columnconfigure(0, weight=0)
mainframe.columnconfigure(1, weight=0)
mainframe.columnconfigure(2, weight=0)
mainframe.columnconfigure(3, weight=5)
mainframe.rowconfigure(0, weight=0)

#
# Set up tabbed window
#
tabwindow = ttk.Notebook(mainframe)
tabwindow.grid(column=0, row=1, sticky=(N, S, E, W), padx=5, pady=5, columnspan=4)
mainframe.rowconfigure(1, weight=1)
tab1 = ttk.Frame(tabwindow, height=500)
tab1.columnconfigure(0, weight=1)
tab1.rowconfigure(0, weight=1)
tabwindow.add(tab1, text='TAB ONE')

It's been a few months since I wrote that and coming back to it now is utterly confusing. Columnconfigure, rowconfigure, grid placement. God forbid that I decide to add a component at the start of the top row. I'd have to increment the column position for all of the following items. There's a bunch of stickiness and weight in there too, which I recall have to do with how components resize in relation to each other.

This is a tree structure, but unlike XML or HTML it doesn't look like a tree structure. Items aren't defined in and of themselves either; they're only defined with weight and position relative to each other.

There's a whole lot to keep track of and hard to change once it's been set in place.

So here comes my recurring question:

Can you recommend me a better GUI programming tool that fulfills my requirements? I know Qt has some sort of XML-like markup these days, but is it easier to develop in and lighter or faster than tkinter?

-- CC0 Björn Wärmedal