I think if you’re considering Gtk or Qt for it’s cross-platformness, you should probably also consider Tcl/Tk. It’s a lot smaller and faster than the others, and if one of them is good enough, Tcl/Tk almost certainly is better.
And if Tcl/Tk isn’t good enough? You know, sometimes that higher standard of quality is required for consumers, and if it is, you’ll waste so much time trying to get that quality out of a “cross-platform GUI framework” that you might’ve just as well used a “native” framework and written your code twice, because your program will always be bigger than your competitors, and slower than them, and it’ll always feel a little bit off even if you do everything else right.
For me, I’ve completely written off this kind of “cross-platformness” because that kind of hassle just isn’t worth it.
Accessibility is a quality that is arguably even more important for business applications than it is for consumers, and Tk doesn’t have it, at all. That should be a deal-killer, unless you’re developing an application for a task that’s inherently visual (e.g. working with graphics).
To the person who downvoted my comment as a troll, do you have any suggestions on how I could have written it better? I’m not trolling; I’m genuinely advocating for accessibility (check out my profile). If it came off as too harsh, that’s just because I feel strongly about this subject.
I’ve also been getting a bunch of frivolous “troll” flags on comments I made in good faith. Perhaps someone is abusing the comment downvoting system? I don’t think you should have to back down from what you said, it was a good point and not harsh at all.
This is also one of the reasons why Electron is awesome(ish): you get all the web platform accessibility tools and APIs. And there is tons of content about how to make accessible applications with web technologies, which IIRC was not the case with QT/GTK.
But (and you may have anticipated this point) is a framework really all that accessible if every application written with it is ginormous and requires a whole bunch of CPU and RAM just to get up & running?
Agreed, particularly when there are good choices for writing your business logic that will run and interoperate more or less cleanly no matter where you are. You technically don’t even have to write (most of) your code “twice”, just the UI bits, which are probably going to be quite different anyway because of the different UI metaphors prevalent on different platforms.
going to be quite different anyway because of the different UI metaphors prevalent on different platforms.
Count on it!
And it’s hard to be fluent in those metaphors when they’re so different from system to system unless you force yourself to use those other systems often enough that you wouldn’t put up with a Qt or Gtk build of your Mac or Windows app anyway.
I have been thinking electron/react native as cheap way (in time and money) to get cross platform applications. And as money<->time<->quality dependency chain dictates, you will lose certain amount of fit and finish when you take that approach. Lot of times it is correct call to do (I rather take non-native application than no application at all) but it is always a trade-off which needs to made, not just defaulted to.
GTK is not the native GUI framework used on Linux, but the toolkit used by GNOME and several other GUI systems for Unix-like operating systems, which almost all have no native GUI toolkit. This distinction is not some childish GNU/Nitpick: It’s a further extension of the nightmare described. Mixing applications that use one or the other of these toolkits is inevitable. There are subtle-to-crippling differences in key combinations, fonts (selection, antialiasing, etc.), icon styles, cursor size, localization, rendering resolution, and on and on. This happens even when one of GTK and Qt is configured to emulate the other as exactly as possible. It does, however, make it easier to accept problems coming from actual cross-platform applications – Chromium, IntelliJ – that (rightly) have no idea what ‘A Linux GUI’ looks like: Everything already looks wrong, so Google’s home-grown UI toolkit can’t make it worse.
From a Linux user’s perspective, this is the sad state of GUI frameworks in general: All of our frameworks are natively cross-platform in all the wrong ways.
This is probably why Gnome has been seeming themselves as more a part of a platform of their own, if not an operating system entirely. Controversial or not… I think they might be in the right, and you’re on the money why.
There’s a similar argument to be made for systemd: cohesion matters, especially for desktop computing. Actually, platforms matter way more for adoption and growth of almost any software ecosystem than I think people realize. For example, take this rant about why AWS continues to beat out Google Cloud after years of trying to catch up: https://gist.github.com/chitchcock/1281611
One of the things I really like about systemd that people forget is that is unified all the little disparate nexuses (nexii?) in Unix. fstab, crontab, inittab, inetd.conf, etc all have different syntax, poor expressiveness for things like quotas, isolation, dependency graph, etc, and often involve ugly syntax or worse, shell scripts. systemd makes these concerns all one unified thing - you can have a service that depends on both a mountpoint and a socket, for instance.
Right! It’s one of those things that aren’t nice until you take the time to learn it, and then you don’t really want to go back or at least that’s the case for me. I’m absolutely not going to say systemd is perfect, it’s not, and I agree with the people that say it’s doing way too much, to an extent. It’s overkill for a lot of systems.
I don’t really trust the “consistency” argument for historical reasons.
Back when I was a huge OS X fanboy (in the age of 10.3, 10.4 or so) the fact that it was “consistent” and “more polished” was all the rage on all the forums. Yet if you opened Finder, iTunes and Pages you had three completely different themes.
We were rationalizing it (Apple’s HGI includes excellent and consistent guidelines about which one to use for each specific purpose yadda yadda) but truth is everyone just did their own thing. Not to mention the myriad tiny quirks that went beyond the theme. It was about as consistent as Windows 10 is these days, at best. But it had a lot of street cred in the designer community so everyone sold it to you as the apex of consistent design.
Nowadays every time I hear the “it’s not consistent” card brought up it makes me shudder. The ghost of usenet postings past, I guess.
I don’t use Gnome enough to know if it has all these tiny quirks, too. Maybe it doesn’t have them – I imagine it doesn’t. For me, it’s hardly a big gain. To paraphrase one of my teachers, there’s a lot of Zen in the simplicity of a blank sheet of paper but if you turn that in you’re gonna get an F.
I never used OS X much so I don’t know how it compares, but one of annoying the inconsistencies in Linux is that stuff like “Save file” dialogs are all different, because they use different toolkits. Bookmarked a directory in a Qt app? Better bookmark it again in that GTK app!
The last Windows version I used is 7, but there those kind of things were a lot more consistent, which I think is a boon.
Back when I was a huge OS X fanboy (in the age of 10.3, 10.4 or so) the fact that it was “consistent” and “more polished” was all the rage on all the forums. Yet if you opened Finder, iTunes and Pages you had three completely different themes.
Honestly, I think X was the beginning of the decline, but we hadn’t realized it yet. Comparing X to 9 reveals that 9 is a far more consistent and usable UX than X is. X had to reconcile not only the NeXT (dock for instance) and Mac UIs together, but also make concessions to Windows switchers (like single-window applications), while adding new metaphors of its own (drawers, sheets). As a result, X feels really muddled.
Also downplayed was Apple’s increasing paternalism and desire to be a consumer electronics company. It was there all along since NeXT took them over inside-out.
Consistency-wise maybe it was but, IMHO, that just says more about how overrated consistency is. OS X was better that OS 9 by any measure. It was inconsistent, and probably worse than NeXT in terms of UI (I may be subjective here because I loved NeXT…), but it allowed people to do a bunch of important things really well, and that’s why it was a resounding success. (As “resounding” as 5% or 10% of the market share can be, or whatever it had back then, but I guess there’s a discussion to be had about the hardware there…)
You seem to be writing this from the perspective of it being a Linux problem but windows and mac have a long history of popular applications using non-native bespoke UI toolkits.
At least on Linux, most open source software tries for some kind of cohesiveness with the rest of the system instead of just doing whatever looks cool at the moment.
Simpler GUIs can be constructed using libyui to
offer 3 GUIs for your app: GTK3, Qt5, and ncurses. This helps appeal to end-users
with different toolkit loyalties (KDE/LXQt/Lumina users often dislike GTK apps and
vice versa for GNOME/Cinnamon/MATE/LXDE users; people like me with minimal setups
prefer TUIs). dnfdragora (basically
Synaptic for DNF) is built on libyui.
There are two root problems, but they’re closely related:
Good cross-platform GUIs are really hard because different platforms favour different user abstractions.
If you have a successful OS, then you have no incentive to make a cross-platform version of its GUI toolkit.
The first one is a big part of why Electron is successful: the Chrome team has done a pretty good job of matching native platform UI abstractions for web UI elements and you inherit this. To give a really trivial example, the shortcut keys for navigating within the default platform’s text field are different between Windows and Mac. It took Qt years to get that right (I think they finally fixed it around 2010ish). Get that wrong, and your app feels subtly wrong on at least one platform. And that’s one of the simpler things to get right.
The major GUI platforms these days are iOS, Android, Windows, and Mac[1]. Apple, Google, and Microsoft all invest a lot in those platforms and have a big incentive to make it easy to write native-feeling applications. None of them has an incentive to make sure that GUI apps work as well on their competitors’ platforms (though this may change: even Microsoft is shipping Electron apps like Teams because it’s the easiest way of supporting Mac / Windows / Linux, though Electron has no mobile story and so doesn’t help with iOS / Android).
There are a couple of honourable mentions not on the list. I still have fond memories of GNUstep. A bunch of companies used it to do *NIX ports (and Windows ports) of Mac applications. OpenStep remains one of the best designed GUI frameworks of all time, but it’s a bit dated now. GNUstep did a complete OpenStep implementation, but didn’t manage to catch up with the improvements Apple made and their Foundation implementation (which had a few big users) was a lot more polished than their AppKit. Objective-C was a great language for application development in the ‘90s and early 2000s, but it’s quite dated now. Some people are still building things on GNUstep, but I don’t really know why. It’s mostly people doing Android ports of iOS apps, and they’re not using the GUI parts.
There’s also Xamarin Forms. This is actually great for the original problem the author suggested (‘displaying 2 text fields and 4 buttons in their favorite color’). It supports Mac, Windows, iOS and Android, and *NIX via GTK#. It lacks some really important things (no outline view, for example), but it has the basic set of things that you’d want for mobile GUIs, at least. It also makes it possible to add native views into your view hierarchy on each platform, if you want to incorporate platform-specific features. I probably wouldn’t advocate it for a complex app, but it largely tackles the cross-platform problem by doing a useful subset well and punting on everything else.
I know people give Tk a lot of grief. But the API is fairly manageable, and with themes can look quite slick and modern https://ttkthemes.readthedocs.io/en/latest/themes.html. The themes are also like an extra line of code to apply with a library like the one in the link.
Screenreader and accessibility support are both big points, but Wayland? Is that really a relevant problem for a desktop-oriented toolkit today?
Don’t get me wrong, I’ve been using it on various embedded platforms for at least four years and I’m generally happier than with X11. But so far the Wayland’s killer desktop feature is Xwayland, which I think makes it possible to run Tk apps, too (I haven’t tried it but I don’t see why it wouldn’t work). I know some people who use it successfully, on very specific hardware, and with a pretty specific workflow (not necessarily exotic, but mostly “just a couple of terminals, emacs/vim and a web browser” which I can totally relate to because that’s my pretty much my workflow, too). But by and large, Wayland support seems to be something you can do without for now.
Can’t say I blame toolkit developers for that. The general state of documentation on Wayland is very bad, and a lot of things are still changing. Unless you work with/on it every day for a few months – either because you’re paid to do it or because Wayland is literally your hobby – there’s no way you can get to do anything useful with it. (Edit: or at least I, for one, don’t see how. I’ve written Wayland-related code on two contracts and it’s been pretty tortuous. It took a lot of research, reading mailing lists and commit messages and poking people on IRC just to figure out the basics There’s no way I would have spent so much of my own free time on it). If I were to write a GUI toolkit today, Wayland support would be just above support for holographic projectors on my todo list.
Edit: also:
IMO, nothing on that page looks slick and modern, and Tk especially doesn’t feel slick and modern. It’s very 90s.
I prefer to run without Xwayland. Pretty much never need it, all apps I use daily are GTK/Qt/SDL2/winit and they work great natively. Xwayland didn’t support HiDPI for a long time but there’s a solution now which was the main reason I got rid of it.
on very specific hardware
You mean literally anything not powered by a GPU made by the awful green company? :)
You mean literally anything not powered by a GPU made by the awful green company? :)
No. I deliberately avoided the awful green company when I built my new desktop two years ago, and Wayland is one of the reasons I did it. It’s still pretty finicky.
I know it runs great for some people. As with any other project, it’s getting to work on everyone else’s machine that’s hard :-).
What does slick and modern feel like? Everything else I’ve used for desktop software (Qt, web+js, Cocoa/GNUstep, GNOME, Motif, Delphi) is at best from the 90s too.
In my experience, a concrete example is nautilus (GNOME’s file manager), whether in its full form or as used in open and save dialogs in other applications, like Firefox. The GTK3 version is noticeably slower than the old GTK2 one (or other currently existing GTK2 forks of it)—especially the awful type-to-search functionality which replaced the old behaviour—in addition to being nearly unusable from the keyboard. GNOME’s ever-growing hostility and/or lack of care towards usability for keyboard-driven workflows in GTK3 and their GNOME 3 applications is astonishing.
As a person who uses software to get things done, I would take lightweight, easy to develop, maintain, and use over slick and modern literally any day of the week.
GTK only supports accessibility on unix, Qt on Win/Mac too. GTK and Qt are the two toolkits that adopted Wayland first.
Smaller frameworks, especially anything “lightweight” that implements its own drawing for everything (doesn’t just abstract over GTK/Win32/Cocoa like wxWidgets does): mostly nope.
I’m hoping for Flutter to mature enough that it can be used for this purpose. The author is right that desktop doesn’t seem to be a priority for them at the moment, but I think that the other two mentioned points (Google abandoning projects & Dart being pretty new and niche) are not that big of a deal.
Sure, Google is often killing consumer products, but this fear seems overblown for their open source projects. And while Dart is definitely lagging behind in terms of libraries and modern language features (even though non-nullable types should help with that once they land), the tooling is in my experience already more mature than many of the tools in the JS ecosystem.
Are Dart & Flutter perfect? No, definitely not. But compared to JS & Electron or C++/Python & Qt, going with Flutter might not be such a bad choice in the hopefully not too distant future.
I think the lowest-common-denominator approach of cross-platform GUI is perhaps untenable. Supporting the metaphors on a native system that differs enough (the obvious example here is Mac OS’ global menu bar which is the application root - an application can run without any other presence including windows) without feeling totally alien seems like a lost cause. I think it’s either making your application logic isolated enough from the frontend to support truly native UIs (unless lower level technical details inform high-level UX), or perhaps totally embrace the platform you’re on and deliver a good experience there. (Open data standards so you can exhange data between applications across platforms could take away the sting of the latter.)
We got the monkey’s paw of apps on Linux, but they all suck.
Unfortunately, the article doesn’t mention the Red language with its native cross-platform GUI engine (Win32, Cocoa, GTK and almost-finished Android) and a declarative DSL for interface specification. Granted, it’s still in the alpha stage, but IMO is mature enough for small and mid-sized personal projects (+ prototyping and aforementioned RAD), and the design goals somewhat resonate with the author’s sentiment.
For an apples-to-apples comparison of GUI frameworks in general, I recommend 7GUIs benchmark; here is the Red version, clocking under ~300LOC for all 7 tasks.
It has been 8 years in active development as of now, what of it? The amount of features packed into toolchain and standard library easily puts it in the ballpark of other 1.0 languages, and right now it’s on par with Rebol2 (the main reference point).
Tallying version numbers without ever evaluating the project on its technical merits won’t make a fair judgment or constructive criticism.
Consider also sustainability and user experience: when developers say “ready”, they want newcomers to have a truly 1.0, smooth sailing (better docs, larger ecosystem, more diverse community, opportunities to contribute at any level of experience, etc) and to stick with them for a long haul; if they cannot provide that, then they simply don’t set the wrong expectations, at the cost of downplaying themselves (saying “alpha”). In such case tech doesn’t matter, people do.
Red is barely alpha, there is almost no documentation, GTK is not supported and toolchain is still 32 bit only (It seems that 64 bit toolchain will be commercial product, part of “Red/Pro”…)
I have included the ones that I thought were “mature” and “popular” enough to be deemed usable.
Please tell me how much time did you spend using it and what of the experience gained during that time made you think that it’s “barely alpha” (also, compared to what?).
GTK branch is pretty much operable, one can either compile from sources or take an automated build to try it out.
Toolchain is still 32 bit only
True, partially that’s the limitation stemming from using Rebol2 (32-bit only itself) during the bootstrapping phase. Many options on how to tackle planned 64-bit transition are on the table, each with its pros and cons.
It seems that 64 bit toolchain will be commercial product, part of “Red/Pro”…
Red/Pro will be a commercial product and will support 64-bit, so as the community version; one simply takes priority over the other.
Seems like Red does not fit the bill.
That’s non sequitur, since most of your claims were refuted by the actual facts (including 7GUIs benchmarks that I provided). Now, do you have something constructive to add to the topic at hand?
While Vala seems to have some nice improvements over C, I don’t really understand why they invented a whole new language in order to get what?
To get a language that feels kinda like C#, but whose native object system is GObject.
[the author’s requirements] It should have the same non-native look and feel on all platforms […] The only non web based GUI framework that comes close to the requirements listed above seems to be Flutter
revery (famously powering onivim 2)? heck, QtQuick/QML? Don’t dismiss QML as “you can finally write your app in Javascript or something” if you like Flutter — QML is the original Flutter before Flutter.
They keep piling stuff on top of QT like QML, so you can finally write your app in Javascript or something. I asked people who are writing QT apps professionally and apparently they are still writing everything in C++ (QtWidgets or however they call it).
I write large Qt applications professionally, and we combine a C++ backend/model with a QML GUI, with a bare minimum of javascript. It has its flaws, but you can achieve a nice balance of efficient C++ code for most of the logic, readable declarative UI description, and hardware accelerated rendering.
Chart components are missing. This entirely depends on the field you are working in, but I often find myself adding a chart to the application. Charts are not part of the QT and you have to find the library that does this for you. Make sure to check their licenses as they are often under GPL license, and you have to buy commercial license if you don’t want to release the source code of your app.
There is a Qt module for charts. “Qt Charts can be used as QWidgets, QGraphicsWidget, or QML types.”
As someone who uses Qt a lot, I have plenty of gripes with it, but this article is not a good assessment of its capabilities and shortcomings, and smacks of angry ranting with only the barest amount of research into the solutions they’re ranting about (It’s not even written “QT”, it’s “Qt”).
libui is currently mid-alpha software[,] much of what is already there is not feature-complete, some of it will be buggy on certain platforms, and there’s a lot of stuff missing[, including:]
Being written in C is a benefit because it’s very easy to write C bindings for other languages, and many languages have tools to do so automatically.
It’s a big part of the reason libraries like SQLite are available everywhere, for almost every language, while libraries like Qt only have one or two custom built language bindings.
Being written in C is a benefit because it’s very easy to write C bindings for other languages
That’s only partly true. It’s easy to call C functions from other languages, but every time you invent a new object model in C then you need to manually add a load of bridging for that, whereas if you have a C++ library with C++11 smart pointers for ownership then you get proper memory management and bindings for most OO languages for free. Even wrapping C in C++ to get automatic memory management is non-trivial and requires some manual steps.
I’ve written Common Lisp bindings for several C libraries, and also a few for Python, and all of the “object models” I’ve seen were handled with zero effort on my part. Most of the time the “objects” are opaque pointers and the “methods” are just plain functions that take an opaque pointer as the first parameter.
The manual memory management is a bummer, but most languages have some way to hide that, and it would be required with a C++ binding, too.
I’m curious how you’re creating bindings to C++ so easily? How does it handle name mangling? And templates?
I haven’t had any luck using C++ with Swig or cl-autowrap, and I’d love to find a good solution…
If the API is very clean and, for example, always takes the object as the first argument then you can usually get things right (expose those functions as methods), but it gets very complex if the object model has any concept of subtyping. With C++, this is exposed in the source code for the binding generator to use and it can insert explicit casts where necessary. With Objective-C, it’s in the source code and also visible for run-time introspection. With C, it’s based entirely in conventions and so you need to encode those in the binding generator.
If I want to create bindings for the Foo GUI library, can I pass a FooTextField* to a function that accepts a FooWidget*? If this is a C++ or Objective-C API, then this is trivial to determine because FooTextField will be a subclass of FooWidget, or this function may even be a method on FooWidget that is inherited by FooTextField. In a C API, this may be purely a convention. Similarly, on memory management, if I have a C++ API that returns a std::shared_ptr<FooWidget> then most bindings generators need absolutely no code at all to get the memory management right. If it’s a C API that has consistent memory management with acquire and release reference functions, then you can probably handle it automatically, but C APIs make it very easy to have ad-hoc ownership models (e.g. this function returns a pointer to a shared buffer, this returns an interior pointer to some other object, and so on).
I’ve written a C++ library that has a public API surface defined purely in terms of C++11 smart pointers or primitive types. SWIG can bridge it with almost no code. I’ve also written generic binding systems for GNU Smalltalk and from JavaScript to Objective-C, which work on almost any Objective-C API without any code. I’ve written a binding generator for C to JavaScript, but it was impossible to handle common API idioms.
To give a trivial example, it’s incredibly common in C libraries to take char* arguments. I need to read the documentation to learn:
Is this a NULL-terminated string or a thing with the length somewhere else?
Is it something that should map to a string or a buffer in high-level languages?
Who owns the memory at the end of the call?
If it’s the callee, how is it freed (what impact does that make on how the caller allocates it)?
I agree that there are corner cases where C is more difficult or C++ can be easier, but in general, an arbitrary C library will be easier to bind than an arbitrary C++ library, IME.
C++ has all the same difficulties as C, and then a boatload of new ones like move semantics, references, templates, name mangling, unique_ptr, etc.
Partly it’s a tooling issue - many languages have tools to generate C bindings automatically, but most of them don’t support C++ - and the reason is that C++ is much more difficult to wrap in general.
To highlight what I mean, here are two functions from GDAL, which happens to export both a C and C++ API:
At first glance the raw pointer return value and char* parameters seem to backup your argument about memory management, but in fact those functions are from the C++ API, showing that the issues don’t go away with C++. Fortunately, the GDAL documentation is good, and points out that the OGRGeometry remains owned by the library.
It comes down to good API design. In any language, you can use abstractions that are difficult to bridge because your type system doesn’t express invariants (even in memory-safe languages, things like thread safety are not usually part of the type system). The difference is that the subset of C++ that is most difficult is C. If you have a well-designed C API, you can write a tool that bridges that API to another language relatively easily. If you have a well-designed C++ API you can use a tool that bridges any well-designed C++ API to another language because the conventions that you are building in C are either part of the language or the standard library in C++. Things like std::shared_ptr, std::unique_ptr, std::span need bridging once but after that you can get memory management right for any library that exposes modern C++ APIs.
Limiting the discussion to “well designed” APIs, or APIs where the person creating the binding has direct control over the API, is almost pointless, IMO. In general, the person creating a language binding won’t have any control over the API being wrapped. Even if a C++ API can be easier to wrap, it’s not helpful if 99% of them aren’t in practice.
If you have a well-designed C API, you can write a tool that bridges that API to another language relatively easily. If you have a well-designed C++ API you can use a tool that bridges any well-designed C++ API to another language because the conventions that you are building in C are either part of the language or the standard library in C++.
With C there’s no need to write a tool because general purpose tools already exist. Swig and cl-autowrap are two examples. What tool are you refering too that generates C++ bindings?
Some of the time. It has gotten better recently, but even their docs admit it doesn’t handle C++ entirely:
Because of its complexity and the fact that C++ can be difficult to integrate with itself let alone other languages, SWIG only provides support for a subset of C++ features.
Not to mention that a lot of libraries in the wild don’t use C++ smart pointers because they’re relatively new…
C++ programming language. After trying different things over the years, I can dare to say that C++ is a terrible language when it comes to writing GUIs. Instead of focusing on the problem that your GUI is trying to solve you find yourself performing workarounds around the language quirks (e.g: string split is still missing from the standard library in 2020). A grizzled C++ veteran will probably scoff at this statement while carefully copying his string split implementation from the previous project [2].
Reality seems to disagree, given the evidence that most GUI applications are written in C++, or at least use GUI toolkits written in C++.
And I’m hardly a “grizzled C++ veteran”, but the author has a pretty outdated view of C++. In the specific case of string splitting, the defacto standard way of doing it is boost::split. Whether that belongs in the standard library or not is a matter of opinion, but historically C++ hasn’t been a “batteries included” language.
I don’t like comments like these. If someone says that a language that they’ve used is bad for them at a certain task, they are right. Even if the wording they use isn’t particularly to your liking, such as by being especially hyperbolic, what they’re expressing is a quality they perceived in their own subjective experience of a language, and the manifestation of language is naught but the collective subjective experiences of that language. If programs were developed completely in isolation from humans, we could perhaps shift the lens to a simple quantitative approach, but that’s simply not true. Software is social, and if people are overwhelmingly complaining about something in a programming language, no matter how trite or “wrong” you believe they are being, what does it actually accomplish to tell them they should simply change their mind about that feeling?
I have zero experience writing GUIs, but it seems to me that declarative UI like SwiftUI or the upcoming Jetpack Compose is the wave of the future and perhaps the best way to approach creating cross-platform GUI frameworks. It’s unfortunate that the two examples that I just mentioned are tied to macOS/iOS and Android, but perhaps they could be ported to other platforms like Mono did with C#?
Jetpack looks interesting. Yeah, I hope whatever sane approach cross pollinates out to everyone. I feel like we went full web and overshot some things. If I had to make Winamp right now, I’d probably use Electron and that’s kind of crazy? It’s not really on the web but I’m using web tech.
I have a lot of experience writing Windows GUIs, mostly in C# WinForms and WPF, and have tried C++/MFC a bit. The C# ones are quite nice IMO, and MFC is kind of manageable in comparison. I don’t know how much support there is on other OSes - it does seem to be more than “none” with Mono. But that kind of just confirms the author’s point. Windows and OS X both have perfectly fine GUI app development languages and environments, and they don’t really support any other OS right.
I don’t think we’ve figured out the view layer yet. The view layer (for me) is when all my good habits go out the window. My view code is completely different than the “plain old code”. Components are a nice move but it doesn’t tidy up nicely for me. There’s code in the view and it’s weird. Maybe view code is not code at all. Maybe it’s a document, a result. It’s something we haven’t found the right paradigm for. Maybe it’s a database. Maybe it’s a blob. Maybe it’s a frizzlewuzzle.
I quite like the approach popularised by winforms and react, where only essential-local state (like text cursor location) is held in a component, while everything else is derived from externally-set properties.
QT website is one big clusterfuck of corporate bullshit and hard to find stuff. They keep redesigning it and every year its getting worse and worse. It’s impossible to find relevant information for your questions and your best bet is relying on the search engine.
I use duck.com and it always finds what I need for Qt, example: QMessageBox Qt
QT is available under LGPL license which prohibits you from statically linking your application without releasing the source code. Maybe that’s not such a big issue but I personally prefer statically linked blobs over the mess that is caused with shared libraries. You can always buy a commercial license that gives you the rights to statically link your application but it comes with a hefty price (if you are even able to find that information on their shoddy website).
Yeah, whatever. If you make money - pay, if you don’t - it is free.
Some developers don’t like the QT’s MOC (Meta Object Compiler) that is used for signals and slots. I don’t have an opinion about that. C++ lacks introspection features and sometimes you have to create a workarounds with such code generation nonsense.
They keep piling stuff on top of QT like QML, so you can finally write your app in Javascript or something. I asked people who are writing QT apps professionally and apparently they are still writing everything in C++ (QtWidgets or however they call it).
It is possible to write C++ or Python.
Chart components are missing. This entirely depends on the field you are working in, but I often find myself adding a chart to the application. Charts are not part of the QT and you have to find the library that does this for you. Make sure to check their licenses as they are often under GPL license, and you have to buy commercial license if you don’t want to release the source code of your app.
C++ programming language. After trying different things over the years, I can dare to say that C++ is a terrible language when it comes to writing GUIs. Instead of focusing on the problem that your GUI is trying to solve you find yourself performing workarounds around the language quirks (e.g: string split is still missing from the standard library in 2020). A grizzled C++ veteran will probably scoff at this statement while carefully copying his string split implementation from the previous project [2].
You said “you can write Qt in Python” half a dozen times but the author already wrote about that on the bottom of the article.
A sharp eye will catch the blasphemy I dared to write down and argue how the bindings exist and you can actually use X programming language to develop in Y framework. Yes the bindings exist but in my limited experience they were quite lacking to the point of uselessness. The documentation was often missing and the tutorials were harder to find if you were even able to find anything. In the end if you have to rely on the documentation of the framework’s primary programming language, you may as well write the entire application in that language instead of fooling around with the half done bindings.
I personally don’t like python so I’ve never written Qt with python but ime everywhere else this appears universally true. Language binding interfaces, especially in the case of high level scripty languages, will always be second class citizens, and you’ll always have to choose between kludgy use patterns or imposing a restrictive abstraction on top of the bindings.
The proof is tautological. Qt is primarily developed around C++, and therefor there will always be inconsistencies in translating those interfaces into other languages. Tell me, does Qt use python’s string representation or does it use their own C++ string representation? Is Python’s nondeterministic garbage collection simply not an issue in relation to Qt’s expectations for destructor call order? Is Qt’s API design oriented around Python’s type system or C++’s?
Yes, and GHC is written with C so code interacting between C and Haskell should have zero caveats, right? You didn’t respond in concrete to any of my questions, by the way.
They keep piling stuff on top of Qt like QML, so you can finally write your app in Javascript or something.
I don’t see how having more options for how to build your UI is a bad thing…
Especially given QML allows for declaratively defining the interface rather than building it programmatically, something I think many people would agree is a good idea. (Separation of logic and presentation is generally regarded as good practice). In fact later on in the very same article being forced to define UI programmatically is used as an argument against wxwidgets.
While Vala seems to have some nice improvements over C, I don’t really understand why they invented a whole new language in order to get what? Another layer of abstraction to get poor man’s C++. For the uninitiated reading this, Vala first generates C code and that C code is later compiled with a C compiler. So when it’s time to debug your application you have to debug the generated C code. That must be loads of fun.
Given you just explained how bad C++ was, perhaps that is why? (Vala is in fact very little like C++, and some of its features make it imo a lovely tool for GUI development).
Also I don’t really buy the argument about debugging. It sounds akin to saying “The C compiler first generates {assembly,llvm} and then that is later compiled. So when it’s time to debug your application you have to debug the generated {assembly, llvm}. That must be loads of fun.”
All you need to do is create a small native wrapper that opens a new tab in the user’s existing browser and package it in an platform specific installer.
Has anyone created something like this? I’d love to be able to ship an javascript frontend that launches in a new instance of Firefox or Chrome (without most browser decorations).
A very small library to build modern HTML5 desktop apps in Go. It uses Chrome browser as a UI layer. Unlike Electron it doesn’t bundle Chrome into the app package, but rather reuses the one that is already installed. Lorca establishes a connection to the browser window and allows calling Go code from the UI and manipulating UI from Go in a seamless manner.
Ah, I misinterpreted what you meant by “a new instance” of the browser.
I’m not aware of a way to get what you’re describing—it seems like you either need to package an entire browser yourself, or at least as much of it as you need, or else you need to rely on the user’s existing browser and don’t have a way to make it look as if your app is its own separate thing.
You don’t need to use Qt with C++; the Python bindings are quite good.
GTK is the native GUI framework used on Linux. According to their website, they claim that the framework is cross platform although apart from Gimp, I haven’t seen many notable applications written in it.
Both Firefox and Chrome use GTK, which seem reasonable notable applications?
I have some good experiences using Python’s tkinter for developing cross-platform GUIs btw, although it’s quite minimal compared to, say, Qt, and doesn’t come with a RAD, I found it works quite well even for more complex applications, has a native look on Windows, and the performance tends to be reasonable.
I’m not saying that it’s on the same level of abstraction or maturity as the other frameworks discussed, but I’ve been really impressed with Gio. I can write my interface once in Go and run it as a desktop app on every major OS, as a phone native application on iOS and Android, and in the browser using WASM and WebGL.
Are “GUI frameworks” really necessary? The only thing that you really need is to be able to dump your pixels into a window. Many interesting applications (games, text and image editors, etc) do not really need any “widget”, just a window with the pixels that you are meant to see. I have written a fair share of graphical applications and never needed a “button” or a “menu”. Just pixels and mouse and keyboard support.
That certainly works, and I have done that a lot myself, but there is a vast number of things you have to implement to reach an acceptable level of features. For example, think of a simple text box. You have to implement:
Copy, Paste, Cut (all of them via standard shortcut CTRL+C, CTRL+V, CTRL+X and via right click menu)
Keyboard input depending on user’s locale (I’ve seen too many programs that just ‘dump pixels’ assume that I have US keyboard layout. Spoiler alert: I don’t.)
All of this, of course, has to support full Unicode with all its intricacies (think caret position in Arabic or with complex symbols that use combining characters, etc.)
Themes (e.g. dark theme for people who use OLED displays)
Proper scaling for high resolution screens
Using system fonts and the system font renderer to look native
Many shortcuts and quirks you may not even know because you’ve never used them, but your users will miss them.
The list goes on and on. You will grow grey hair before you finished your first text box, quite literally. Of course, you can just brush all of that aside and just claim “I’ don’t need that”. But I do, because I want to write robust applications that use standard GUI widgets that have been established for decades. That’s what the users want. It is the only way you can create a clean GUI that behaves in a more or less standardized and predictable way.
I think if you’re considering Gtk or Qt for it’s cross-platformness, you should probably also consider Tcl/Tk. It’s a lot smaller and faster than the others, and if one of them is good enough, Tcl/Tk almost certainly is better.
And if Tcl/Tk isn’t good enough? You know, sometimes that higher standard of quality is required for consumers, and if it is, you’ll waste so much time trying to get that quality out of a “cross-platform GUI framework” that you might’ve just as well used a “native” framework and written your code twice, because your program will always be bigger than your competitors, and slower than them, and it’ll always feel a little bit off even if you do everything else right.
For me, I’ve completely written off this kind of “cross-platformness” because that kind of hassle just isn’t worth it.
I come here to say about Tcl/Tk and FLTK: both are way lighter options.
Accessibility is a quality that is arguably even more important for business applications than it is for consumers, and Tk doesn’t have it, at all. That should be a deal-killer, unless you’re developing an application for a task that’s inherently visual (e.g. working with graphics).
Do you know if command line tools are inherently accessible to screen readers, or does something additional have to be done?
Yes, command-line tools are inherently accessible.
Although I’ve always had trouble with the ones which add pseudo-gui elements.
To the person who downvoted my comment as a troll, do you have any suggestions on how I could have written it better? I’m not trolling; I’m genuinely advocating for accessibility (check out my profile). If it came off as too harsh, that’s just because I feel strongly about this subject.
I’ve also been getting a bunch of frivolous “troll” flags on comments I made in good faith. Perhaps someone is abusing the comment downvoting system? I don’t think you should have to back down from what you said, it was a good point and not harsh at all.
This is also one of the reasons why Electron is awesome(ish): you get all the web platform accessibility tools and APIs. And there is tons of content about how to make accessible applications with web technologies, which IIRC was not the case with QT/GTK.
But (and you may have anticipated this point) is a framework really all that accessible if every application written with it is ginormous and requires a whole bunch of CPU and RAM just to get up & running?
To paraphrase a common refrain in Functional Programming circles, “islands of backend logic in a sea of GUI code”.
Agreed, particularly when there are good choices for writing your business logic that will run and interoperate more or less cleanly no matter where you are. You technically don’t even have to write (most of) your code “twice”, just the UI bits, which are probably going to be quite different anyway because of the different UI metaphors prevalent on different platforms.
Count on it!
And it’s hard to be fluent in those metaphors when they’re so different from system to system unless you force yourself to use those other systems often enough that you wouldn’t put up with a Qt or Gtk build of your Mac or Windows app anyway.
I have been thinking electron/react native as cheap way (in time and money) to get cross platform applications. And as money<->time<->quality dependency chain dictates, you will lose certain amount of fit and finish when you take that approach. Lot of times it is correct call to do (I rather take non-native application than no application at all) but it is always a trade-off which needs to made, not just defaulted to.
GTK is not the native GUI framework used on Linux, but the toolkit used by GNOME and several other GUI systems for Unix-like operating systems, which almost all have no native GUI toolkit. This distinction is not some childish GNU/Nitpick: It’s a further extension of the nightmare described. Mixing applications that use one or the other of these toolkits is inevitable. There are subtle-to-crippling differences in key combinations, fonts (selection, antialiasing, etc.), icon styles, cursor size, localization, rendering resolution, and on and on. This happens even when one of GTK and Qt is configured to emulate the other as exactly as possible. It does, however, make it easier to accept problems coming from actual cross-platform applications – Chromium, IntelliJ – that (rightly) have no idea what ‘A Linux GUI’ looks like: Everything already looks wrong, so Google’s home-grown UI toolkit can’t make it worse.
From a Linux user’s perspective, this is the sad state of GUI frameworks in general: All of our frameworks are natively cross-platform in all the wrong ways.
This is probably why Gnome has been seeming themselves as more a part of a platform of their own, if not an operating system entirely. Controversial or not… I think they might be in the right, and you’re on the money why.
There’s a similar argument to be made for systemd: cohesion matters, especially for desktop computing. Actually, platforms matter way more for adoption and growth of almost any software ecosystem than I think people realize. For example, take this rant about why AWS continues to beat out Google Cloud after years of trying to catch up: https://gist.github.com/chitchcock/1281611
One of the things I really like about systemd that people forget is that is unified all the little disparate nexuses (nexii?) in Unix. fstab, crontab, inittab, inetd.conf, etc all have different syntax, poor expressiveness for things like quotas, isolation, dependency graph, etc, and often involve ugly syntax or worse, shell scripts. systemd makes these concerns all one unified thing - you can have a service that depends on both a mountpoint and a socket, for instance.
Right! It’s one of those things that aren’t nice until you take the time to learn it, and then you don’t really want to go back or at least that’s the case for me. I’m absolutely not going to say systemd is perfect, it’s not, and I agree with the people that say it’s doing way too much, to an extent. It’s overkill for a lot of systems.
As a long time Linux user I don’t see this as a big problem. Having choice is part of what makes Linux systems so flexible.
People who want a consistent interface across applications can use GNOME or KDE.
Maing GUI apps that look non-native has been long fashionable on Windows, and now they have their GTK vs Qt issue in form of Metro vs “normal”.
I don’t really trust the “consistency” argument for historical reasons.
Back when I was a huge OS X fanboy (in the age of 10.3, 10.4 or so) the fact that it was “consistent” and “more polished” was all the rage on all the forums. Yet if you opened Finder, iTunes and Pages you had three completely different themes.
We were rationalizing it (Apple’s HGI includes excellent and consistent guidelines about which one to use for each specific purpose yadda yadda) but truth is everyone just did their own thing. Not to mention the myriad tiny quirks that went beyond the theme. It was about as consistent as Windows 10 is these days, at best. But it had a lot of street cred in the designer community so everyone sold it to you as the apex of consistent design.
Nowadays every time I hear the “it’s not consistent” card brought up it makes me shudder. The ghost of usenet postings past, I guess.
I don’t use Gnome enough to know if it has all these tiny quirks, too. Maybe it doesn’t have them – I imagine it doesn’t. For me, it’s hardly a big gain. To paraphrase one of my teachers, there’s a lot of Zen in the simplicity of a blank sheet of paper but if you turn that in you’re gonna get an F.
I never used OS X much so I don’t know how it compares, but one of annoying the inconsistencies in Linux is that stuff like “Save file” dialogs are all different, because they use different toolkits. Bookmarked a directory in a Qt app? Better bookmark it again in that GTK app!
The last Windows version I used is 7, but there those kind of things were a lot more consistent, which I think is a boon.
Honestly, I think X was the beginning of the decline, but we hadn’t realized it yet. Comparing X to 9 reveals that 9 is a far more consistent and usable UX than X is. X had to reconcile not only the NeXT (dock for instance) and Mac UIs together, but also make concessions to Windows switchers (like single-window applications), while adding new metaphors of its own (drawers, sheets). As a result, X feels really muddled.
Also downplayed was Apple’s increasing paternalism and desire to be a consumer electronics company. It was there all along since NeXT took them over inside-out.
Consistency-wise maybe it was but, IMHO, that just says more about how overrated consistency is. OS X was better that OS 9 by any measure. It was inconsistent, and probably worse than NeXT in terms of UI (I may be subjective here because I loved NeXT…), but it allowed people to do a bunch of important things really well, and that’s why it was a resounding success. (As “resounding” as 5% or 10% of the market share can be, or whatever it had back then, but I guess there’s a discussion to be had about the hardware there…)
You seem to be writing this from the perspective of it being a Linux problem but windows and mac have a long history of popular applications using non-native bespoke UI toolkits.
At least on Linux, most open source software tries for some kind of cohesiveness with the rest of the system instead of just doing whatever looks cool at the moment.
Simpler GUIs can be constructed using libyui to offer 3 GUIs for your app: GTK3, Qt5, and ncurses. This helps appeal to end-users with different toolkit loyalties (KDE/LXQt/Lumina users often dislike GTK apps and vice versa for GNOME/Cinnamon/MATE/LXDE users; people like me with minimal setups prefer TUIs). dnfdragora (basically Synaptic for DNF) is built on libyui.
There are two root problems, but they’re closely related:
The first one is a big part of why Electron is successful: the Chrome team has done a pretty good job of matching native platform UI abstractions for web UI elements and you inherit this. To give a really trivial example, the shortcut keys for navigating within the default platform’s text field are different between Windows and Mac. It took Qt years to get that right (I think they finally fixed it around 2010ish). Get that wrong, and your app feels subtly wrong on at least one platform. And that’s one of the simpler things to get right.
The major GUI platforms these days are iOS, Android, Windows, and Mac[1]. Apple, Google, and Microsoft all invest a lot in those platforms and have a big incentive to make it easy to write native-feeling applications. None of them has an incentive to make sure that GUI apps work as well on their competitors’ platforms (though this may change: even Microsoft is shipping Electron apps like Teams because it’s the easiest way of supporting Mac / Windows / Linux, though Electron has no mobile story and so doesn’t help with iOS / Android).
There are a couple of honourable mentions not on the list. I still have fond memories of GNUstep. A bunch of companies used it to do *NIX ports (and Windows ports) of Mac applications. OpenStep remains one of the best designed GUI frameworks of all time, but it’s a bit dated now. GNUstep did a complete OpenStep implementation, but didn’t manage to catch up with the improvements Apple made and their Foundation implementation (which had a few big users) was a lot more polished than their AppKit. Objective-C was a great language for application development in the ‘90s and early 2000s, but it’s quite dated now. Some people are still building things on GNUstep, but I don’t really know why. It’s mostly people doing Android ports of iOS apps, and they’re not using the GUI parts.
There’s also Xamarin Forms. This is actually great for the original problem the author suggested (‘displaying 2 text fields and 4 buttons in their favorite color’). It supports Mac, Windows, iOS and Android, and *NIX via GTK#. It lacks some really important things (no outline view, for example), but it has the basic set of things that you’d want for mobile GUIs, at least. It also makes it possible to add native views into your view hierarchy on each platform, if you want to incorporate platform-specific features. I probably wouldn’t advocate it for a complex app, but it largely tackles the cross-platform problem by doing a useful subset well and punting on everything else.
I know people give Tk a lot of grief. But the API is fairly manageable, and with themes can look quite slick and modern https://ttkthemes.readthedocs.io/en/latest/themes.html. The themes are also like an extra line of code to apply with a library like the one in the link.
No Wayland support (though some fork/port/thing added that via SDL2 apparently??), no screenreader accessibility support (someone tried to integrate AT-SPI in python in 2009 and that seems to be it??)..
IMO, nothing on that page looks slick and modern, and Tk especially doesn’t feel slick and modern. It’s very 90s.
Screenreader and accessibility support are both big points, but Wayland? Is that really a relevant problem for a desktop-oriented toolkit today?
Don’t get me wrong, I’ve been using it on various embedded platforms for at least four years and I’m generally happier than with X11. But so far the Wayland’s killer desktop feature is Xwayland, which I think makes it possible to run Tk apps, too (I haven’t tried it but I don’t see why it wouldn’t work). I know some people who use it successfully, on very specific hardware, and with a pretty specific workflow (not necessarily exotic, but mostly “just a couple of terminals, emacs/vim and a web browser” which I can totally relate to because that’s my pretty much my workflow, too). But by and large, Wayland support seems to be something you can do without for now.
Can’t say I blame toolkit developers for that. The general state of documentation on Wayland is very bad, and a lot of things are still changing. Unless you work with/on it every day for a few months – either because you’re paid to do it or because Wayland is literally your hobby – there’s no way you can get to do anything useful with it. (Edit: or at least I, for one, don’t see how. I’ve written Wayland-related code on two contracts and it’s been pretty tortuous. It took a lot of research, reading mailing lists and commit messages and poking people on IRC just to figure out the basics There’s no way I would have spent so much of my own free time on it). If I were to write a GUI toolkit today, Wayland support would be just above support for holographic projectors on my todo list.
Edit: also:
For some of us, that’s a feature ;-)
I prefer to run without Xwayland. Pretty much never need it, all apps I use daily are GTK/Qt/SDL2/winit and they work great natively. Xwayland didn’t support HiDPI for a long time but there’s a solution now which was the main reason I got rid of it.
You mean literally anything not powered by a GPU made by the awful green company? :)
No. I deliberately avoided the awful green company when I built my new desktop two years ago, and Wayland is one of the reasons I did it. It’s still pretty finicky.
I know it runs great for some people. As with any other project, it’s getting to work on everyone else’s machine that’s hard :-).
What does slick and modern feel like? Everything else I’ve used for desktop software (Qt, web+js, Cocoa/GNUstep, GNOME, Motif, Delphi) is at best from the 90s too.
GNOME/GTK3 feels the most modern and polished.
Is “modern and polished” supposed to be synonymous with “slow and buggy”?
I’ve never noticed GTK3 being slow and buggy. What exactly is slow and buggy?
In my experience, a concrete example is nautilus (GNOME’s file manager), whether in its full form or as used in open and save dialogs in other applications, like Firefox. The GTK3 version is noticeably slower than the old GTK2 one (or other currently existing GTK2 forks of it)—especially the awful type-to-search functionality which replaced the old behaviour—in addition to being nearly unusable from the keyboard. GNOME’s ever-growing hostility and/or lack of care towards usability for keyboard-driven workflows in GTK3 and their GNOME 3 applications is astonishing.
I’d invite you to take a look at the Adapta KDE Kvantum theme for Qt, as well as KDE’s default Breeze/Breeze-Dark.
As a person who uses software to get things done, I would take lightweight, easy to develop, maintain, and use over slick and modern literally any day of the week.
These are excellent points. How do other gui frameworks do on accessibility and Wayland support?
GTK only supports accessibility on unix, Qt on Win/Mac too. GTK and Qt are the two toolkits that adopted Wayland first.
Smaller frameworks, especially anything “lightweight” that implements its own drawing for everything (doesn’t just abstract over GTK/Win32/Cocoa like wxWidgets does): mostly nope.
I’m hoping for Flutter to mature enough that it can be used for this purpose. The author is right that desktop doesn’t seem to be a priority for them at the moment, but I think that the other two mentioned points (Google abandoning projects & Dart being pretty new and niche) are not that big of a deal.
Sure, Google is often killing consumer products, but this fear seems overblown for their open source projects. And while Dart is definitely lagging behind in terms of libraries and modern language features (even though non-nullable types should help with that once they land), the tooling is in my experience already more mature than many of the tools in the JS ecosystem.
Are Dart & Flutter perfect? No, definitely not. But compared to JS & Electron or C++/Python & Qt, going with Flutter might not be such a bad choice in the hopefully not too distant future.
I think the lowest-common-denominator approach of cross-platform GUI is perhaps untenable. Supporting the metaphors on a native system that differs enough (the obvious example here is Mac OS’ global menu bar which is the application root - an application can run without any other presence including windows) without feeling totally alien seems like a lost cause. I think it’s either making your application logic isolated enough from the frontend to support truly native UIs (unless lower level technical details inform high-level UX), or perhaps totally embrace the platform you’re on and deliver a good experience there. (Open data standards so you can exhange data between applications across platforms could take away the sting of the latter.)
We got the monkey’s paw of apps on Linux, but they all suck.
Unfortunately, the article doesn’t mention the Red language with its native cross-platform GUI engine (Win32, Cocoa, GTK and almost-finished Android) and a declarative DSL for interface specification. Granted, it’s still in the alpha stage, but IMO is mature enough for small and mid-sized personal projects (+ prototyping and aforementioned RAD), and the design goals somewhat resonate with the author’s sentiment.
For an apples-to-apples comparison of GUI frameworks in general, I recommend 7GUIs benchmark; here is the Red version, clocking under ~300LOC for all 7 tasks.
Hasn’t Red been in alpha for ages?
It has been 8 years in active development as of now, what of it? The amount of features packed into toolchain and standard library easily puts it in the ballpark of other 1.0 languages, and right now it’s on par with Rebol2 (the main reference point).
Tallying version numbers without ever evaluating the project on its technical merits won’t make a fair judgment or constructive criticism.
Consider also sustainability and user experience: when developers say “ready”, they want newcomers to have a truly 1.0, smooth sailing (better docs, larger ecosystem, more diverse community, opportunities to contribute at any level of experience, etc) and to stick with them for a long haul; if they cannot provide that, then they simply don’t set the wrong expectations, at the cost of downplaying themselves (saying “alpha”). In such case tech doesn’t matter, people do.
Red is barely alpha, there is almost no documentation, GTK is not supported and toolchain is still 32 bit only (It seems that 64 bit toolchain will be commercial product, part of “Red/Pro”…)
Seems like Red does not fit the bill.
Please tell me how much time did you spend using it and what of the experience gained during that time made you think that it’s “barely alpha” (also, compared to what?).
Presence of official reference documentation, formal specification, Github wiki and community-provided resources doesn’t qualify as “almost no” in my book.
GTK branch is pretty much operable, one can either compile from sources or take an automated build to try it out.
True, partially that’s the limitation stemming from using Rebol2 (32-bit only itself) during the bootstrapping phase. Many options on how to tackle planned 64-bit transition are on the table, each with its pros and cons.
Red/Pro will be a commercial product and will support 64-bit, so as the community version; one simply takes priority over the other.
That’s non sequitur, since most of your claims were refuted by the actual facts (including 7GUIs benchmarks that I provided). Now, do you have something constructive to add to the topic at hand?
To get a language that feels kinda like C#, but whose native object system is GObject.
revery (famously powering onivim 2)? heck, QtQuick/QML? Don’t dismiss QML as “you can finally write your app in Javascript or something” if you like Flutter — QML is the original Flutter before Flutter.
I write large Qt applications professionally, and we combine a C++ backend/model with a QML GUI, with a bare minimum of javascript. It has its flaws, but you can achieve a nice balance of efficient C++ code for most of the logic, readable declarative UI description, and hardware accelerated rendering.
There is a Qt module for charts. “Qt Charts can be used as QWidgets, QGraphicsWidget, or QML types.”
As someone who uses Qt a lot, I have plenty of gripes with it, but this article is not a good assessment of its capabilities and shortcomings, and smacks of angry ranting with only the barest amount of research into the solutions they’re ranting about (It’s not even written “QT”, it’s “Qt”).
Don’t forget about FreePascal. The older tools are always overlooked.
Lazarus seems to be on the list, actually… is this not the same?
For those who want a simple API and a native look, there’s libui: https://github.com/andlabs/libui/
However, straight from the Readme:
[Comment from banned user removed]
“Disclaimer”? Why would I need to add a disclaimer when talking about C projects?
Being written in C is a benefit because it’s very easy to write C bindings for other languages, and many languages have tools to do so automatically.
It’s a big part of the reason libraries like SQLite are available everywhere, for almost every language, while libraries like Qt only have one or two custom built language bindings.
That’s only partly true. It’s easy to call C functions from other languages, but every time you invent a new object model in C then you need to manually add a load of bridging for that, whereas if you have a C++ library with C++11 smart pointers for ownership then you get proper memory management and bindings for most OO languages for free. Even wrapping C in C++ to get automatic memory management is non-trivial and requires some manual steps.
I’m going to disagree.
I’ve written Common Lisp bindings for several C libraries, and also a few for Python, and all of the “object models” I’ve seen were handled with zero effort on my part. Most of the time the “objects” are opaque pointers and the “methods” are just plain functions that take an opaque pointer as the first parameter.
The manual memory management is a bummer, but most languages have some way to hide that, and it would be required with a C++ binding, too.
I’m curious how you’re creating bindings to C++ so easily? How does it handle name mangling? And templates?
I haven’t had any luck using C++ with Swig or cl-autowrap, and I’d love to find a good solution…
If the API is very clean and, for example, always takes the object as the first argument then you can usually get things right (expose those functions as methods), but it gets very complex if the object model has any concept of subtyping. With C++, this is exposed in the source code for the binding generator to use and it can insert explicit casts where necessary. With Objective-C, it’s in the source code and also visible for run-time introspection. With C, it’s based entirely in conventions and so you need to encode those in the binding generator.
If I want to create bindings for the Foo GUI library, can I pass a
FooTextField*
to a function that accepts aFooWidget*
? If this is a C++ or Objective-C API, then this is trivial to determine becauseFooTextField
will be a subclass ofFooWidget
, or this function may even be a method onFooWidget
that is inherited byFooTextField
. In a C API, this may be purely a convention. Similarly, on memory management, if I have a C++ API that returns astd::shared_ptr<FooWidget>
then most bindings generators need absolutely no code at all to get the memory management right. If it’s a C API that has consistent memory management with acquire and release reference functions, then you can probably handle it automatically, but C APIs make it very easy to have ad-hoc ownership models (e.g. this function returns a pointer to a shared buffer, this returns an interior pointer to some other object, and so on).I’ve written a C++ library that has a public API surface defined purely in terms of C++11 smart pointers or primitive types. SWIG can bridge it with almost no code. I’ve also written generic binding systems for GNU Smalltalk and from JavaScript to Objective-C, which work on almost any Objective-C API without any code. I’ve written a binding generator for C to JavaScript, but it was impossible to handle common API idioms.
To give a trivial example, it’s incredibly common in C libraries to take
char*
arguments. I need to read the documentation to learn:I agree that there are corner cases where C is more difficult or C++ can be easier, but in general, an arbitrary C library will be easier to bind than an arbitrary C++ library, IME.
C++ has all the same difficulties as C, and then a boatload of new ones like move semantics, references, templates, name mangling, unique_ptr, etc.
Partly it’s a tooling issue - many languages have tools to generate C bindings automatically, but most of them don’t support C++ - and the reason is that C++ is much more difficult to wrap in general.
To highlight what I mean, here are two functions from GDAL, which happens to export both a C and C++ API:
At first glance the raw pointer return value and char* parameters seem to backup your argument about memory management, but in fact those functions are from the C++ API, showing that the issues don’t go away with C++. Fortunately, the GDAL documentation is good, and points out that the OGRGeometry remains owned by the library.
It comes down to good API design. In any language, you can use abstractions that are difficult to bridge because your type system doesn’t express invariants (even in memory-safe languages, things like thread safety are not usually part of the type system). The difference is that the subset of C++ that is most difficult is C. If you have a well-designed C API, you can write a tool that bridges that API to another language relatively easily. If you have a well-designed C++ API you can use a tool that bridges any well-designed C++ API to another language because the conventions that you are building in C are either part of the language or the standard library in C++. Things like
std::shared_ptr
,std::unique_ptr
,std::span
need bridging once but after that you can get memory management right for any library that exposes modern C++ APIs.Limiting the discussion to “well designed” APIs, or APIs where the person creating the binding has direct control over the API, is almost pointless, IMO. In general, the person creating a language binding won’t have any control over the API being wrapped. Even if a C++ API can be easier to wrap, it’s not helpful if 99% of them aren’t in practice.
With C there’s no need to write a tool because general purpose tools already exist. Swig and cl-autowrap are two examples. What tool are you refering too that generates C++ bindings?
Swig automatically handles memory management and object bridging for C++ APIs that use standard C++ smart pointers.
Some of the time. It has gotten better recently, but even their docs admit it doesn’t handle C++ entirely:
Not to mention that a lot of libraries in the wild don’t use C++ smart pointers because they’re relatively new…
Exactly, in addition to be usable from D (as @catwell noted in ref bellow), I am assuming libui is usable from Zig and Nim as well.
https://github.com/andlabs/libui#language-bindings
Reality seems to disagree, given the evidence that most GUI applications are written in C++, or at least use GUI toolkits written in C++.
And I’m hardly a “grizzled C++ veteran”, but the author has a pretty outdated view of C++. In the specific case of string splitting, the defacto standard way of doing it is boost::split. Whether that belongs in the standard library or not is a matter of opinion, but historically C++ hasn’t been a “batteries included” language.
I don’t like comments like these. If someone says that a language that they’ve used is bad for them at a certain task, they are right. Even if the wording they use isn’t particularly to your liking, such as by being especially hyperbolic, what they’re expressing is a quality they perceived in their own subjective experience of a language, and the manifestation of language is naught but the collective subjective experiences of that language. If programs were developed completely in isolation from humans, we could perhaps shift the lens to a simple quantitative approach, but that’s simply not true. Software is social, and if people are overwhelmingly complaining about something in a programming language, no matter how trite or “wrong” you believe they are being, what does it actually accomplish to tell them they should simply change their mind about that feeling?
I agree, but the author stated it as a fact, not his opinion.
That’s what I meant by hyperbole. It’s still at the end of the day their opinion that it’s a fact, so the same applies.
I have zero experience writing GUIs, but it seems to me that declarative UI like SwiftUI or the upcoming Jetpack Compose is the wave of the future and perhaps the best way to approach creating cross-platform GUI frameworks. It’s unfortunate that the two examples that I just mentioned are tied to macOS/iOS and Android, but perhaps they could be ported to other platforms like Mono did with C#?
Jetpack looks interesting. Yeah, I hope whatever sane approach cross pollinates out to everyone. I feel like we went full web and overshot some things. If I had to make Winamp right now, I’d probably use Electron and that’s kind of crazy? It’s not really on the web but I’m using web tech.
I have a lot of experience writing Windows GUIs, mostly in C# WinForms and WPF, and have tried C++/MFC a bit. The C# ones are quite nice IMO, and MFC is kind of manageable in comparison. I don’t know how much support there is on other OSes - it does seem to be more than “none” with Mono. But that kind of just confirms the author’s point. Windows and OS X both have perfectly fine GUI app development languages and environments, and they don’t really support any other OS right.
I don’t think we’ve figured out the view layer yet. The view layer (for me) is when all my good habits go out the window. My view code is completely different than the “plain old code”. Components are a nice move but it doesn’t tidy up nicely for me. There’s code in the view and it’s weird. Maybe view code is not code at all. Maybe it’s a document, a result. It’s something we haven’t found the right paradigm for. Maybe it’s a database. Maybe it’s a blob. Maybe it’s a frizzlewuzzle.
I quite like the approach popularised by winforms and react, where only essential-local state (like text cursor location) is held in a component, while everything else is derived from externally-set properties.
Reply to Cons of Qt:
I use duck.com and it always finds what I need for Qt, example: QMessageBox Qt
Yeah, whatever. If you make money - pay, if you don’t - it is free.
Holywar-like con. Qt has official Python bindings: https://www.qt.io/qt-for-python
It is possible to write C++ or Python.
With Python bindings it is possible to hook up matplotlib: https://matplotlib.org/3.1.3/gallery/user_interfaces/embedding_in_qt_sgskip.html
Qt has official Python bindings: https://www.qt.io/qt-for-python
Note: Not affiliated with Qt. Using Qt for work.
You said “you can write Qt in Python” half a dozen times but the author already wrote about that on the bottom of the article.
I personally don’t like python so I’ve never written Qt with python but ime everywhere else this appears universally true. Language binding interfaces, especially in the case of high level scripty languages, will always be second class citizens, and you’ll always have to choose between kludgy use patterns or imposing a restrictive abstraction on top of the bindings.
Do you have a proof of that? otherwise is FUD.
The proof is tautological. Qt is primarily developed around C++, and therefor there will always be inconsistencies in translating those interfaces into other languages. Tell me, does Qt use python’s string representation or does it use their own C++ string representation? Is Python’s nondeterministic garbage collection simply not an issue in relation to Qt’s expectations for destructor call order? Is Qt’s API design oriented around Python’s type system or C++’s?
It is very easy to write correct interfaces between C (and thus C++) and Python. CPython is written in C. So I don’t understand your concern.
Yes, and GHC is written with C so code interacting between C and Haskell should have zero caveats, right? You didn’t respond in concrete to any of my questions, by the way.
I didn’t say it should have zero caveats. I said it is easy to make it work.
You asked for proof that python for qt, like all other gui language bindings, was a second class citizen. I provided proof :)
I don’t see how having more options for how to build your UI is a bad thing…
Especially given QML allows for declaratively defining the interface rather than building it programmatically, something I think many people would agree is a good idea. (Separation of logic and presentation is generally regarded as good practice). In fact later on in the very same article being forced to define UI programmatically is used as an argument against wxwidgets.
Given you just explained how bad C++ was, perhaps that is why? (Vala is in fact very little like C++, and some of its features make it imo a lovely tool for GUI development).
Also I don’t really buy the argument about debugging. It sounds akin to saying “The C compiler first generates {assembly,llvm} and then that is later compiled. So when it’s time to debug your application you have to debug the generated {assembly, llvm}. That must be loads of fun.”
Has anyone created something like this? I’d love to be able to ship an javascript frontend that launches in a new instance of Firefox or Chrome (without most browser decorations).
Yes.
Lorca:
I think Electron is pretty much what you’re describing, right?
I’d like to not pacakge in an entire chromium installation!
Ah, I misinterpreted what you meant by “a new instance” of the browser.
I’m not aware of a way to get what you’re describing—it seems like you either need to package an entire browser yourself, or at least as much of it as you need, or else you need to rely on the user’s existing browser and don’t have a way to make it look as if your app is its own separate thing.
You don’t need to use Qt with C++; the Python bindings are quite good.
Both Firefox and Chrome use GTK, which seem reasonable notable applications?
I have some good experiences using Python’s tkinter for developing cross-platform GUIs btw, although it’s quite minimal compared to, say, Qt, and doesn’t come with a RAD, I found it works quite well even for more complex applications, has a native look on Windows, and the performance tends to be reasonable.
They only use certain elements of GTK on Linux; the cross-platform parts of their UIs are built into them.
Oh okay, I thought it was all GTK but guess not 😅
Yeah, Firefox was always XUL (well, may just be web stuff rendered by Gecko now) but rendered with native-looking widgets.
This article has an obviously true premise, and is not pointing any new light at anything.
I’m not saying that it’s on the same level of abstraction or maturity as the other frameworks discussed, but I’ve been really impressed with Gio. I can write my interface once in Go and run it as a desktop app on every major OS, as a phone native application on iOS and Android, and in the browser using WASM and WebGL.
V has a cross-platform GUI toolkit.
On the other hand, it’s still in alpha, and the V development pace is really slow.
Are “GUI frameworks” really necessary? The only thing that you really need is to be able to dump your pixels into a window. Many interesting applications (games, text and image editors, etc) do not really need any “widget”, just a window with the pixels that you are meant to see. I have written a fair share of graphical applications and never needed a “button” or a “menu”. Just pixels and mouse and keyboard support.
That certainly works, and I have done that a lot myself, but there is a vast number of things you have to implement to reach an acceptable level of features. For example, think of a simple text box. You have to implement:
The list goes on and on. You will grow grey hair before you finished your first text box, quite literally. Of course, you can just brush all of that aside and just claim “I’ don’t need that”. But I do, because I want to write robust applications that use standard GUI widgets that have been established for decades. That’s what the users want. It is the only way you can create a clean GUI that behaves in a more or less standardized and predictable way.