Ask HN: How to do cross platform GUI?
In essentially every discussion about desktop applications there are a lot of comments about how not to build desktop apps, but very little sharing of resources showing how to do it right.
I’ve seen people defend electron, talk about core logic in a cross platform language and native gui code and any number of other options.
As a middle of the road developer I think it’s difficult to find any consensus (besides electron being both simple and hated).
What resources are there for building quality, functional cross platform desktop application?
397 comments
[ 3.4 ms ] story [ 253 ms ] threadIf you're careful, you could build something which works on every desktop starting with mid-1990s.
For newer platforms, if you want it to be a "true desktop app", you could bundle the HTTP server. Whatever your platform, there are many options.
I am talking about a true desktop app, not a web app.
Are desktop apps dead?
Sounds like you already know the big players so I won't repeat them. Instead, here are some off-kilter ideas:
1. Casual use, general interest, notification-requiring, simple single-file data requirements, tolerant of desktop / mobile split sessions? Try making a chat bot for Telegram, FB, Discord, Slack..
2. Dynamic, visualization-focused UI with simple options that need to be tweaked interactively? Try Imgui[0] or Godot[1]
3. Scientific or data-centric stuff pulling in data from here and there, but meant for interactive exploration? Try Wolfram / Mathematica or an IPython notebook / GoogleColab
[0] https://github.com/ocornut/imgui/wiki/Software-using-dear-im...
[1] https://medium.com/swlh/what-makes-godot-engine-great-for-ad...
Cool recommendations, thanks!
As a Mac user I prefer native applications if available. But still, I would consider a well-written Qt application.
For example, qBittorrent is quite alright.
https://en.m.wikipedia.org/wiki/Qt_(software)
https://www.qbittorrent.org/
Where should I look? I’m willing to put in the work!
http://zetcode.com/gui/pyqt5/
There are a few others here:
https://wiki.python.org/moin/PyQt/Tutorials
The 2020 one there may be what you're looking for, more than hello world but doesn't quite all the way get to the kitchen sink, just maybe the silverware drawer.
Qt is LGPL. PySide is LGPL. PyQt is "GPL but allows you to link from popular open source licenses".
https://riverbankcomputing.com/pipermail/pyqt/2014-February/...
So it is more like MIT licensed projects give you the freedom to use in a GPL project.
https://en.wikipedia.org/wiki/GPL_linking_exception
https://riverbankcomputing.com/commercial/license-faq
https://upload.wikimedia.org/wikipedia/commons/e/e8/Qt_Creat...
I always see Qt mentioned, so I'm definitely not trying to discredit it. I just never seem to see common examples with it compared to something written in Electron.
Now, don't let the screenshots color your impressions as to what kinds of UI designs are possible under Qt: Ripcord's UI is bare-bones on purpose; it's a selling feature. I bring up this application because it lets you do a more apples-to-apples comparison: IM clients these days are a poster child of an Electron app that uses orders of magnitude more resources than they should for the functionality provided. Ripcord lets you compare the experience and performance with a native app, implementing the same features but without overhead and gratuitous UI shine.
(And personally, I do use it for Slack/Discord instead of official clients.)
The comparison to Electron is somewhat flawed though. I mean, the GUI in an Electron application owes much more to whatever library they choose than to the fact that it runs inside Electron. Electron provides no particular GUI elements to the developer.
Autodesk Fusion 360 uses Qt[1]. (It's 3D CAD modeling software like Solidworks/Inventor). Some screenshots of its UI : https://www.google.com/search?q=%22autodesk+fusion+360%22+ui...
CAD/CAM modeling software is resource intensive and users always complain about slow performance when manipulating big files so writing that type of app in Electron/Chrome/Javascript browser engine would be worse than native C++/Qt.
That said, another competitor Onshape is browser-based and yes, people do complain about its performance.
Some other well-known desktops using Qt are Autodesk Maya and Wolfram Mathematica.[2]
[1] https://forums.autodesk.com/t5/fusion-360-api-and-scripts/wh...
[2] https://en.wikipedia.org/wiki/Category:Software_that_uses_Qt
I've seen some tutorial some time ago, where someone used libwebkit from Rust, but I could not find it again recently, so the point is: There could be libraries allowing you to talk to a rendering engine and this could be a more mInimalistic approach than Electron.
https://alex-hhh.github.io/
I have written a couple GUI applications in Racket; maybe they can serve as motivation to discover Racket's GUI capabilities:
https://github.com/evdubs/chart-simulator
https://github.com/evdubs/renegade-way
There are limitations to Racket's GUI toolkit compared to writing a native Qt/GTK/WPF/Cocoa application. You may find it easy to express simple/not-so-complex interfaces and then find it much more difficult to do other things. There's also the fact that Racket's real threads story isn't so great.
If I needed to write a cross-platform GUI application for the masses, I'd probably pick JavaFX over Racket, but Racket has been very impressive if your initial impression is to not expect much.
If you want a RAD IDE I recommend you to take a look at Lazarus and Xojo ($).
You can try them all and think for yourself. Xojo and LispWorks in particular come with plenty of example apps.
What I’m more looking for are specific resources on how to do it. Like say I choose qt, what then? How do I go from an idea to a cross platform app with a reasonable build pipeline and a clear method for installation?
Also see Qt Creator.
https://platform.uno/
It basically lets you compile WinUI (Windows 10, C#, XAML) apps to run natively on all platforms (Windows, MacOS, Linux, Web, iOS, Android).
Disclaimer: I was part of that project for 3 years.
Although I've not yet tried it myself, there's AndroWish (https://www.androwish.org/home/home). Deploy your TCL/Tk code on Android with minimal changes.
[0]: https://flutter.dev/desktop
When people criticize Electron, I don't think they're saying "given your capacity, you should have picked a different and better point on the tradeoff curve". I think they're just mad that you had the requirements you had and didn't get to apply more resources than you had access to.
So, at first it sounds like they're making a technical argument against anyone who would choose to use Electron, but I think what they're actually doing is instead expressing some kind of economic disappointment in your situation.
(I would probably use Electron on a small budget, Qt on a medium budget, and native apps on a large budget.)
This is a fair assessment. Still, this disappoinment is worth expressing as it makes it clear the current situation (lack of high-quality, mature, cross-platform toolkit using native widgets) is frustrating. You shouldn't be choosing between spending a lot of resources doing things right and spending a reasonable amount producing an inneficient monster that drains your users' system resources.
The particularly annoying part about economics here is the "limited oxygen" nature of software products. If you and I both develop a software tool, but I decide to rush it with Electron while you take it slow with native app per platform, I get to (assuming the tool is a-ok) "suck the oxygen out of the space" by releasing first, and you may lose the motivation/market to create the better tool.
Which is to say, "good today" may be better than "perfect next week", but the big reason why software products suck so badly is that "shitty today" is considered better than "good tomorrow".
AFAIK, this is not correct, as WxWidgets fits the requirements (it's almost 30 years old, cross-platform and native).
I'm curious though, since I haven't extensively developded GUI applications, which are the pratical tradeoffs against a non-native toolkit like Qt.
I don't buy it, something doesn't add up. The look and feel is somewhat out of place, one can tell with one glance it's not native. https://i.imgur.com/LjDhPOv.png
• The scrollbars are too narrow and have only a down arrow at the bottom instead of a combined up and down arrow.
• The font size is wrong in some places in the hex editor.
• The tab in the tab bar is crooked, not rectangular, and lacks a close button.
• The text has too cramped kerning, most noticable in the word "File".
• The underline for key shortcuts is placed too high.
• The ribbing in the lower-right corner is larger.
• Contrast around the menu bar is too harsh.
• The icon bar does not lock (context menu), and always displays a grabber.
• Menu bar and icon bar do not have a context menu.
• The ribbing on the left-right split bar is different.
• The MDI panel only has a close button but not a detach button. There's a obtrusive gradient in the panel title.
• The progress bar does not have the stripe pattern.
I submit that Wx implements its own non-native widgets.
It does for the widgets that have no native equivalent, such as draggable/dockable tabs/panels that you show. You can't say they differ from native ones because there is just no native version, on any platform.
OTOH all the standard UI elements (buttons, checkboxes, text controls, date pickers, ...) are native and not only they look natively, but also behave natively, which is pretty important and different from Qt.
PoEdit comes the closest to looking genuinely native, but the MacOS implementation is clearly flawed.
[1] https://www.wxwidgets.org/about/screenshots/
Or check "Game Develop". The primary interface is a kind of weird rip-off of the MS Office ribbon, but I assume this is a custom widget. There's also a tab interface though, and this doesn't work on either the Windows or GTK versions: it's weird and has a gradient background.
In general, small details like the padding, coloration, and borders drawn around widgets seem to be slightly off on most platforms with just about very wx based GUI I've seen.
The rest of the controls (ribbon, tabs) are indeed non-native and there are no native equivalents for them, so there is not much to say here.
Generally speaking, there shouldn't be any problem with the colours unless you change them explicitly, which is a bad idea for the native controls. Not sure what is wrong with the padding and borders.
Well, let's verify that… https://i.imgur.com/uHfjoUs.png No, they're not.
> draggable/dockable tabs/panels […] You can't say they differ from native ones because there is just no native version
That sounds wrong. Why should they not be? Do you have any proof?
Sorry, I don't know what is this supposed to prove, but I can definitely assure you that all the mentioned controls, and many others, are exactly native controls under the 3 first tier platforms (MSW, GTK and macOS).
> Do you have any proof?
Proof of absence of something is hard to make, all I can say is that you can go through MSDN, GTK and Cocoa documentation to convince yourself.
Regardless, since you're accusing a very old and widespread project of lying ("it uses the platform's native API rather than emulating the GUI" on their front page, versus "I submit that Wx implements its own non-native widgets."), you should directly ask on an official channel, and have an authoritative answer.
> since you're accusing a very old and widespread project of lying
http://enwp.org/Appeal_to_accomplishment Nice fallacy, don't think you can pull cheap tricks like that on HN.
But anyway, let them defend themselves; veritas liberabit vos. FWIW I don't think malicious or intentional lies are involved, although a mighty good explanation is required to square their claim against the evidence that it is plain to see.
Note that one of the posters you've been arguing with ("VZ"; argument here: https://news.ycombinator.com/item?id=24259040), turned out to be the WxWidgets maintainer. According to the comment though, mentioning this constitutes a cheap trick <rolling eyes>.
Regardless, there is a very interesting concept in the explanation: using native widgets through WxWidgets (and possibly, widget toolkits in general) requires following specific guidelines. Failing to do so will make the widgets look bad, even if they're native.
With native UI, eventually the development will stop. With cross-platform, you will, FOREVER, try to catch up.
P.D: i have used more than +12 main languages and as many or more UI toolkits.
The native UIs are running even close to a DECADE without nothing of significance on maintain. The rest? is rewrite, recode or workaround....
If I can buy a cheap roof for $2k but have to replace it every year, or an expensive roof for $15k that will last 50 years, then LONG TERM the cheap roof is the more costly option.
But if I only have $2k instead of $15k, I'm not wrong to buy a cheap roof. Yelling at me about the long term costs of the cheap roof is missing the point. You're just saying that you're disappointed by my lack of $15k.
This happens a lot, because some of the "advice" in this industry is for "startups that if not ship something like now will die", when the majority of the work is not that disposable...
In a sane world we would already have webviews on all platforms and the problem mostly solved for client applications. But there's a lot of forces at work that want to artificially suppress web UI. Chromium doesn't have webview on desktop platforms, but Microsoft's chromium edge does. Apple puts in their special restrictions making up rules for any app that uses wkwebview.
Nobody with the power wants to make webUI universally deployable.
At the end of the day you choose one that you'll actually deploy something with. There's no more right or wrong in UI, it's can you get to the goal of deploying a functional app or not.
There is undeniably a problem with flutter however: while it can be used for desktop applications, it's mobile-first, desktop-sec.. well... desktop-kinda-sorta-works...
We did the business case for cross platform, as we’re a non-tech enterprise organisation with 10.000 employees but few developers. We wanted flutter to win, but react native came out like the sound choice.
What makes you think that?
They have spent more than 3-4 years with millions of dollars on it.
https://flutter.dev/showcase
https://github.com/flutter/flutter/wiki/Desktop-shells
https://flutter.dev/desktop
Still, it seems like Flutter will be a good option once desktop support is more stable.
I still prefer Kotlin, but there have been very, very few occasions where I've not been able to do what I wanted with Dart.
Isn't WebView kind of work around for web browser being overbloated? I mean they made single instance of browser and interfaces for embedding that single instance, but do you really need that for desktop?
There’s also these tiny but high-quality frameworks for C++: https://github.com/andlabs/libui https://github.com/cycfi/elements
JavaFX doesn't seem as snappy as native OS GUI frameworks, but I've found it very nice to develop for. It comes with reactive model out of the box, and there are some extra libraries that take it up to 11.
I'm very comfortable with Java, but one of the issues I've had is the size of the resulting binary with the JRE included (it's possible to not include a JRE of course, but it's much easier to have it bundled from a user perspective). You can use jlink to reduce the size of the bundled JRE so that it only includes relevant modules, but does it actually reduce the binary size by a significant amount?
Also, JavaFX doesn't seem to have backing from larger organizations like Electron does. Are there any well-known apps created with JavaFX. I know IntelliJ was created with Java but using Swing if I recall correctly.
I would say that's pretty acceptable for a real app.
- https://docs.nodegui.org/
- https://react.nodegui.org/
Alternatively you could use a compatibility version of OpenGL, like 3.3 which will run on any desktop OS, then use a windowing lib like glfw and UI framework like Dear ImGui which is graphics API agnostic. I use this particular combination all the time and it never lets me down. Sokol is another options which is a very thin layer over many graphics APIs.
I can't speak for Unity, but as far as Godot is concerned, the workflow for certain things like layout and text styling leave a lot to be desired if you're not making games.
Really, that just means waiting until more suitable plugins are available.
There’s also FuncUI, an elm-like layer over Avalonia written in F#.
It leverages the entire Qt system with the power of .NET. We use it on embedded medical devices.
So I'd start by asking yourself whether you really need your application to be cross platform.
The real question is "where do you draw the line for cross platform code?". In other words, do you want everything to be potentially shared or do you only want the "business logic" to be shared? Unless theres a real constraint on time, I've found the best option to be starting with shared core + native views and migrating the view logic into the shared core over time as you discover the UI patterns.
You can have native feel by using a framework that binds to the native directly. In my opinion Xamarin is the best option currently, but Kotlin Multiplatform is a possibility once they mature.
It has accessibility problems, excludinga certain group of users, including blind people. I'd urge you to reconsider.
I wrote a little framework for this: https://github.com/jdarpinian/web-ui-skeleton
This is getting weird very quickly (not to mention that Ctrl-S in browser windows saving file without confirmation is a UX I wouldn't want to use)
There are several decent options. You could build a modal that displays a view of the file system sourced from the server. Or you could pop a real native file dialog from the server, and I'm betting it's possible to either make it a real modal of the browser window or do a good enough simulation depending on platform. Or in the future you could use the native file system API that is currently in origin trial.
I submit that this is not weirder than most cross-platform UI toolkits that implement their own whacky replacements for the native file dialogs.
See https://www.w3.org/TR/secure-contexts/#is-origin-trustworthy
Running inside a real browser also limits the keyboard shortcuts you can use, because you don't want to clash with the browser's own shortcuts.
The obvious way to keep the browser authenticated is a session cookie. But cookies are shared between all ports on a domain, so a local attacker who tricks you into visiting another localhost service in the same browser can steal the cookie. localStorage doesn't have that issue, but it's not so convenient for authenticating requests.
Exposing a HTTP port with application state is a million times worse for security
I'm in a position where I'd like to develop a better client for Bitwarden that includes autofill to the point of 1Password, and while I did start with GTK (learning for the first time), seeing no one recommend GTK here (compared to multiple people recommending Qt) isn't filling me with confidence
The downside would be the desire to port to GTK+ 4 in some amount of time, which might require a large amount of effort depending on the application. On the other hand, if you're starting today you could also start with GTK+ 4...
Whereas under the old model (GTK+ 2.x) it was forwards compatible (if that is the right word) - you code against a stable but actively developed version, and your code will work with no or minimal changes for multiple years, and you will receive the benefits of new versions (historical examples: changes to file open/save dialogs, theming changes, window resize grippers, dragging windows from menubars, ...).
Beware that, if you use GTK, you exclude a certain segment of the population who need Accessibility and aren't on Linux. This definitely includes screen reader users, but probably also users of voice recognition, switch control etc. QT works much better here. This is yet another tradeoff to make.
The changes should make it similar to the way Qt works and should make it easier to plug in a Windows/Mac a11y backend. If there is interest in implementing/maintaining this then please help out if you're able.
If you really, really want your app to use Gtk+ on Linux and be reasonable elsewhere, consider wxWidgets.