GUI toolkits

Published by mithat on Wednesday, 3 March 2010

Some thoughts on what I want in a GUI toolkit. Ideally, I want a kit that has:

  1. A decent GUI builder.
  2. Bindings for several languages that are usable by the GUI builder (and esp. something other than C/C++).
  3. Cross-platform capability.
  4. Integration with an IDE to make codebase maintenance a single-point affair.
  5. A libre license that doesn’t limit use in proprietary s/w.

Candidates include:

  • wxWidgets
  • GTK
  • Qt
  • Lazarus

I am not considering Java and Mono based solutions at the present time even though for completeness I should.

wxWidgets

GUI builders for wxWidgets include wxFormBuilder, wxGlade, and XRCed. BoaConstructor is a Python IDE with a wxWidgets GUI builder built-in. Stani’s Python Editor is a Python IDE with wxGlade and XRCed built-in. Before you get comfy with any of these, you need to know a bit about how wxWidgets work (sizers and constants mostly).

wxWidgets is well-supported on all major operating systems. It is natively C++, but there are bindings for tons of languages including Python and Perl. Someone once told me that wxWidgets is not thread-safe but Qt is. This needs some investigation to 1. determine if this is (still) true and 2. get a grip on when this might be a problem.

There are a couple approaches to working with non-C++ languages: 1) have the GUI builder generate code in whatever language you want or 2) produce XRC files and write the code to import the layout specs. XRC seems like a cool idea (you can use one XRC as a basis for implementation in many languages), but I don’t think it maps controller events to handlers—which is possibly a bit of a pain.

GUI builders for wxWidgets

wxGlade

Produces code for C++, Python, Perl, LISP (!), and XRC. Is fairly WYSIWYG and has a preview mode (^P while the form designer is in focus) that shows you exactly WYG. It only supports about 33 widgets, i.e., the basic GUI stuff. Generates code that you must then edit through other means. This introduces a level of foo that may be inconvenient or problematic (requires more work to say for sure).

The Python code generation (the only one tested so far) seems to check for event handlers. If an event handler already has code written for it, that code is not touched. If the handler does not exist, then a template handler is inserted into the code. It looks as though if you eliminate a control in wxGlade, you must manually remove the event handlers from the generated code.

Overall: Takes some getting used to, but once you re used to it, it seem pretty usable. No support for non-GUI widgets though (timers, etc.), which must be hand-coded.

XRCed

Outputs XRC. UI building is graphical, but not WYSIWYG—not even crudely. However, it has a “test” mode (i.e., a WYG preview) that’s not too bad. Number of available widgets is about the same as wxGlade, but tuning them/changing properties/etc. is confounding for several of them (e.g., adding text to a status bar).

wxFormBuilder

Generates C++. It also produces XRC that you can copy/paste into your own text editor and save. Newest version supposedly makes Python as well, but the version in the Ubunbtu Karmic repos doesn’t. Introduces an additional layer of code between GUI and app: the app writer must subclass the stuff generated by wxFormBuilder to use in the app.

Decent WYSIWYG-ish form viewer, but there is no “test” mode that I’ve been able to find to show you exactly WYG. Also, it has the same confounding aspects as XRCed, e.g., status bars and notebooks: How do you add content? Appears to offer a few more widgets than wxGlade.

BoaConstructor

The name makes you want to use it, but hasn’t been updated since 2007-07-05 and that makes you want to avoid it. It’s a Python-only IDE with a wxWidgets GUI builder built-in. The UI of the GUI builder isn’t exactly intuitive (!), so I will withhold more comments until I get a better handle on this.

A note on XRC

I think it would be cool if there were a tool that generated handler stubs from the XRC file—or maybe something simpler that only generates a list of widgets and their most common events. Or something.

Comments and caveats

Overall, wxWidgets is swell, but all the available GUI builders have issues. The least problematic is probably wxGlade, which in fact may be totally fine if you don’t mind hand-coding non-GUI widgets.

There is a bit of a problem with Windows apps using wxWidgets esp. if you are using something other than C++. The user must do three different installs to get things working: 1) install e.g. Python/Perl/whatever, 2) install wxWidgets, and 3) install your app. You could ship Python “executable binaries” or whatever they call the code+interpreter package and then possibly locally link to only the bits of wxWidgets that are needed, but the Python “executable binaries” will be pretty large—mostly due to the size of the interpreter.

GTK

GUI builders for GTK include Glade. That’s it. GTK is totally *nix-centric. While GTK apps are not uncommon in Windows (OS X is TODO), they always look (and behave) like GTK apps. However, GTK apps on Linux look really nice (as you might expect). GTK is old (mature?) and not very OOP, but it seems to be well-supported and is the defacto standard in Linux. There’s also and app called autoglade to help you integrate Glade files into bash and such.

I have yet to spend any time with Glade. However, I think it too may benefit from an “auto-generate stubs” think. When you’ve got a gazillion widgets on a form, it’s hard not to miss one.

Comments and caveats

The biggest issue with GTK is cross-platform support. While supporting non-*nix platforms is possible, it’s not without problems. In particular, Windows packages must come with a GTK package as well—or with instructions directing the user to install and configure one. And they will not look nor behave as native. Also, if you are using something other than C/C++, you will have the same installation issues with Python or whatever that you would with wxWidgets.

Qt

Cross-platform support is good and there are many language bindings. There is an official GUI builder that outputs code for C++ and Java. Translation to other languages is possible using e.g. pyuic. Qt is the native toolkit in KDE and there is also support for Symbian; I suspect Maemo/MeeGoo support is following. Lots of people developing with Qt seem to be rabid in their support for the toolkit. I know of at least one who is not (you know who you are).

In the past a big issue with Qt was their dual GPL/Commercial licensing model. But since they have gone LGPL, there really isn’t any licensing issue.

I have yet to spend any significant time with Qt or QtCreator.

Comments and caveats

To me, Qt apps never look or feel right on any platform except for KDE—for which I have no awesome love.

Lazarus

“Write once, compile anywhere” cross-platform Delphi clone. Draws controls using whatever is native to the underlying OS/DE, and I can confirm that the results are acceptable in GTK Linux. Licensing is great (but watch for GPL-only third-party extensions). The UI is pretty usable, although I don’t love the floating windows interface (ala the Gimp). But if you put everything into its own desktop it becomes ok. I also don’t like the SynEdit-based editor, but it’s far less than horrible.

Lazarus produces compiled code (no runtimes, VMs, etc. needed), but you need to manually strip out the debug symbols to shrink the binaries to “release” size. While Pascal does not support Unicode, Lazarus does—however it looks like this might require some hoop jumping.

Comments and caveats

Lazarus’ biggest limitation is that you must code in FreePascal. It’s not a bad language, but it’s the only language that Lazarus supports. Menus in the actual Lazarus IDE are a bit sluggish, which makes me wonder if this scales well to big projects. Stability is also an unknown: in my limited testing, certain IDE windows seemed to get stuck in an “always on top” mode—I have no idea why.

Another possible limitation is the available APIs. Python, Perl, C++ all have lots of APIs etc. to draw on. In the case of FreePascal, you are much more limited—or you need to use the APIs developed for other languages.

Overall: Lazarus is definitely attractive, but it needs more investigation.

Geek notes

Lazarus misc. notes that I will eventually move elsewhere:

Multiple forms

I spent a couple days trying to figure this one out. Adding a second form to a project is easy: File -> New Form. But accessing it from another form is another story. The secret is this: to access a second form—which we will assume Lazarus defined in Unit2.pas, add unit2 to the uses section of Unit1.pas (or wherever you are trying to access it from). (Source: http://forum.ubuntu-tr.org/index.php?topic=8876.0 [daphne’s comment]). Once you’ve done that, then MyNewForm.Show and MyNewForm.ShowModal will work as expected.

P.S., don’t forget that Pascal (including FreePascal) is not case sensitive.