1. 38

I know this is very subjective. My objective with this question is not to determine what is the best solution out there but collect some feedback and stories on what people been using. Threads like this are an opportunity to discover new stuff as well as I bet someone will link some niche kit that will make some other reader quite happy.

I am interested in learning what you enjoy using for cross-platform native GUI app development. The way I’m defining native here is anything that is not electron. I know that allows a lot of stuff in that would normally not be considered native such as languages that run on VMs and draw their own controls without using whatever the OS provides, but in my mind that is OK for this question. I’m specially curious about toolkits or languages that are nimble and allow you to get a lot done in terms of GUI without using too much resources.

    1. 26

      I’m going to give a null option here. There just isn’t anything native that’s both good and portable.

      • I used to find Cocoa somewhat enjoyable, but it’s obviously totally non-portable. I feel like nowadays it’s getting more buggy and the documentation has degraded. There are no more Technical Notes getting published, and new APIs ship with “No Overview Available” instead of docs.
      • Qt is intimately tied to C++, and I just can’t stomach C++.
      • I’m currently using GTK, but on macOS it feels even slower and more alien than Electron.

      I haven’t seen anything close to web dev tools for native GUI development. Xcode can inspect GUI, but it’s a toy compared to browser’s inspector. I can edit CSS live without reloading my UI, and control every pixel with relative ease. I can build fancy animated web UI in a shorter time than it takes me to get a makefile work across systems.

      1. 5

        You can use a Python binding with Qt. There’s PyQT5 and PySlide (and Qt, which is a wrapper around both; depending on what’s installed).

        1. 1

          Interesting! I can’t recall seeing such apps in the wild. Do you know any popular apps that are built using that combo?

          1. 2

            I wrote this one:

            https://gitlab.com/djsumdog/mpvbuddy

            and have a few more I haven’t released yet.

      2. 4

        Yeah I’m yet to find a cross platform GUI toolkit that makes for nice Mac apps, Cocoa is really the only option if you want to make something that feels polished and high quality. But often the apps using these cross-platform toolkits are apps that wouldn’t get ported to the Mac otherwise, so I’m willing to accept the tradeoff of a slightly clunky GUI in exchange for having access to a useful piece of software.

      3. 2

        What version of GTK do you use right now?

    2. 24

      I’m gonna go with Qt on this one. I learned it a long time ago (I think it was still at version 2!) and it never really let me down. It’s got very good documentation, and it’s pretty reliable for long-term development. I have projects that have been through three Qt versions (3.x, 4.x, 5.x) and the migration has been pretty painless each time. It’s not on the nimble end of the spectrum and it’s C++, but I found it to be the most productive, even though the widgets library hasn’t been as high on the parent company’s priority list. (They insist that’s not true but actions speak louder than words…). I’ve used it for huge projects (200 KloC+) and it held out great.

      I used GTK 2 back in the day, too, and while some bits weren’t exactly enjoyable, it was generally efficient, and it was a pretty safe bet for cross-platform development, and an especially safe bet for Linux and Unix development. I really wanted to like GTK 3. I don’t know if it’s because I’m getting grumpy and impatient, or if there really is something objectively wrong with it, but I didn’t manage to like it, and now I tend to avoid it, both when it comes to writing code that uses it and when it comes to using applications written against it. Also I’m not sure how its cross-platformness is doing these days.

      I’ve played with Dear ImGui and I can definitely say I enjoy it. I’ve used it for some pretty small and special-purpose tools (and obviously you get about as much native integration with it as you get with Electron :P) but I definitely had fun with it. I’ve also

      1. 6

        I’m also a big fan of QT, and in particular, QtQuick is the single most productive rapid prototyping platform I’ve ever used (beating out even Visual Basic and Electron). The first app I ever wrote with it started out as an excuse to learn Qt Quick, and I had a working, polished app within two weeks.

      2. 4

        I really like Qt as well. I recently started building things with PyQt5 and it’s been pretty nice to work with:

        https://gitlab.com/djsumdog/mpvbuddy

      3. 2

        +1 for Qt. I was surprised to see Telegram’s desktop client not using Electron, when every popular IM client is using it, and the UI seems much faster, and pleasant to work with. Another advantage is, Qt is available on more platforms than Electron, so if you like to be portable, don’t want to be limited by GNU/Linux, Windows, or macOS, then Qt is a good choice.

      4. 1

        I’ve also

        Did you intend to continue?

        1. 2

          Did you intend to continue?

          It looks like I did but whatever I wanted to say has long been swapped to the write-only section of my memory :)

      5. 1

        Happy with Qt too, but only when keeping the project up to date (and then it’s much easier with small projects). The least progress I’ve ever made as part of a software team was when we had a long-running Qt app where some parts were Qt5-ready, but we were mostly building with Qt4 and even then using 3-to-4 adapters in parts. Not that this isn’t true of other frameworks, but that sticks out as a raw nerve in my memory.

        I’ve also used wxwidgets (but long enough ago that I don’t remember much specific, it seemed to work), GNUstep (OK if you don’t use any super-modern Cocoa APIs, where the approach to claiming 100% coverage has been to stub out all of the implementations), and Eclipse RCP which is a real curate’s egg.

    3. 16

      There was a conversation on this topic a few months ago that might be of interest as well: https://lobste.rs/s/xx0snw/what_s_best_gui_library_around

    4. 10

      As someone who dosen’t normally do GUI stuff and needed to add a GUI to an existing C codebase[0], I found libagar[1] pleasant to work with. It was also fairly easy to hack on to add a few new features I needed. If you’re writing C or C++ and need to get something going quickly, it’s about as easy as imgui (which is also nice). If you want to see a simple code example, I have one at [2].

      Edit: I realize I didn’t really talk about why you might want to use Agar. Some key features that I think are compelling:

      • Consistent, well documented widget library
      • A large selection of different widgets
      • Theme-able using a CSS-like system
      • At run-time, widgets are represented using a “VFS” which seems a lot like a DOM and gives many of the same benefits
        • Including a “GUI Debugger” which is very much like the web inspector in a browser, although it’s still being developed and is a bit more limited than the web inspector at present
      • Very portable - platform-specific bits are well abstracted, and new back-ends could be added with relative ease
        • including to embedded systems
      • “Pure C” - if you have a C compiler, you can probably build it for your platform
      • Almost the entire library is thread-safe
      • Lazy updating system avoids re-draws when they aren’t needed
      • Unlike Qt or GTK, if you know C, you pretty much understand all the “special sauce” (although I haven’t really used Qt or GTK, so take this with a grain of salt)
        • Agar does have an object system, which is how the VFS is implemented, however it’s much simpler than GObject, based on my limited experience with that
      • Good support for unicode and fonts

      0 - https://github.com/HeRCLab/nocsim

      1 - http://libagar.org/

      2 - https://github.com/charlesdaniels/teaching-learning/tree/master/libraries/libagar/graph_editor

      1. 2

        libagar does look pretty interesting. How much customization support does it have for changing the direct appearance of widgets (ie. checkboxes, tabs, scroll-bars etc.)? While I don’t personally mind, I think many users of a hypothetical application would find it to be rather ugly.

        1. 7

          The colors and font can be changed very easily.

          Changing the shape/size of things would be difficult. e.g. the amount of roundness of the buttons. In principle, I think the styling system could be augmented with CSS-type parameters (e.g. button-radius), but nobody has Done The Work™.

          It would be possible I think to write a theming system a la GTK themes and have the library look in ~/.config/agar or something. Probably not even very hard. But again nobody has Done The Work™.

          I am fortunate in that for my use-case, appearance doesn’t matter much since my consumers are either myself or other grad students. If I was trying to say sell a product to consumers, I would probably be inclined to put some thought into the theming system.

          FWIW Agar’s author is very friendly and hangs out on IRC/Discord quite a bit. If you want a feature and can write the code for it, he’s usually very willing to either provide meaningful feedback or else merge it.

          1. 2

            Cool, thanks for the response! I’m actually in a similar situation, my users for now are a couple post-docs and grad students in a lab (though it’s recently been expanded to some other professional scientists), so the appearance is really secondary to the functionality. I think implementing CSS is one of the harder parts of making a functional web browser, but something more limited that offers some appearance customization would be nice. I sadly don’t have the time to look into implementing that, but I’ll keep it in the back of my mind!

            1. 1

              No problem.

              The CSS part works as of 1.6.0, or so I am told. I built the GUI for noc-tools with a pre-release version of 1.6 and it had a few bugs I had to hack around. If you just want pretty colors you should be able to do that with little difficulty. Now that 1.6 is done it should be as easy as AG_LoadStyleSheet("something.css");. This is the style.css that I used. The documentation has more complete examples.

    5. 10

      Caveat: this is an alpha-level project.

      I’m really enjoying using Gio. It let’s you write cross platform GUIs in pure Go and essentially sits on top of each platform’s EGL implementation.

      I’ve found it to be extremely easy to write simple interfaces that run reliability on all desktop oses and on mobile.

      It definitely has some missing features (and big ones, like accessibility and common widgets), but it’s developing rapidly.

      1. 4

        For those like me who didn’t know about it, here’s a description of EGL from the official website:

        EGL is an interface between Khronos rendering APIs such as OpenGL ES or OpenVG and the underlying native platform window system. It handles graphics context management, surface/buffer binding, and rendering synchronization and enables high-performance, accelerated, mixed-mode 2D and 3D rendering using other Khronos APIs.

        EGL provides mechanisms for creating rendering surfaces onto which client APIs like OpenGL ES and OpenVG can draw, creates graphics contexts for client APIs, and synchronizes drawing by client APIs as well as native platform rendering APIs.

      2. 1

        I’ve been poking around Gio also, and it seems really pleasant to use. I would love to be able to write “native” desktop applications in pure Go.

      3. 1

        It looks really cool, especially the wasm output. The missing accessibility sucks though, I don’t need it (yet), but I feel irresponsible using a tool where it’s missing.

    6. 9

      Racket’s racket/gui is good, I’ve never used it for anything particularly big though and the controls it offers out of the box are kinda limiting. You’re gonna have to do a lot of stuff yourself. Still, the fact that you don’t have to do any complicated build processes to work with it and release your program, because it’s built into the standard library that you get when you download DrRacket, is reason enough to put me off using anything more powerful, like Qt.

      1. 4

        Yeah, Racket is leaps and bounds more pleasant to use than any of the cross-platform alternatives I’m aware of. The simplicity of the build really spoils you; raco distribute and you’re done. Even works in wine.

    7. 9

      Definitely Gtk.

      Qt always feels like it’ll be the best choice, but then you’re either stuck with writing C++ (and it’s not even “normal” C++), or using bindings that tend to cut corners because cooperating with QtC++ is too tricky and awkward.

      I recently hit that when trying to write a Qt GUI for a Rust program: the bindings existed, but were not capable of creating their own QObjects – so forget about spinning up a worker thread that can talk to the UI sensibly (perhaps you could somehow, but the documentation was insufficient, and mostly randomly generated).

      By comparison, gtk.rs has fantastic, idiomatic bindings, and a mpsc channel replacement that talks over glib’s event loop. I’m not sure if it’s all because of it being C-backed and thus easier to talk to, but I remember the same thing when doing GUI in Perl back in the day: Qt bindings existed, Gtk bindings were good.

      1. 2

        +1 for Gtk. They’ve put a lot of work into their multiple language support of late, so you can code in Javascript or Python just as easily as you can in C or Vala.

      2. 1

        I recently hit that when trying to write a Qt GUI for a Rust program: the bindings existed, but were not capable of creating their own QObjects

        Out of interest, which rust Qt bindings did you try? I experimented with qmetaobject-rs (https://woboq.com/blog/qmetaobject-from-rust.html) a few months back. Using qmetaobject-rs itself seemed ok, but the project I tried to implement consisted of some tree-shaped data which I wanted the GUI to view and modify. However, when I tried to represent the data in rust, I couldn’t find an idiomatic way to represent a tree in rust. The only information I could find online suggested breaking out of rust’s ownership model by storing the tree’s nodes in an “Arena”. Essentially I ended up with an application that was part qml (fine), part bindings and boilerplate to marshal data between qml and rust (could be an acceptable cost if we get the best of both worlds…) and a bunch of rust code which was mostly just working around rust, not benefiting from it. At that point, I abandoned it.

        In case it isn’t obvious, I am not a Rust programmer. I keep trying to learn it, but so far I can’t seem to find the right project to try it out on (I also tried writing some rust in a functional style a while back, but despite borrowing many ideas from functional programming, rust doesn’t feel like a good functional programming language (which is fine, I don’t think it’s meant to be one)). I suspect that most of my issues with rust are that I am trying to write Haskell in Rust, or trying to write C++ in Rust, instead of writing in Rust. I am still on the lookout for how to represent hierarchical data properly in Rust.

        1. 1

          I used rust-qt, aka ritual: https://rust-qt.github.io/. Back then it was the only access to “raw Qt” that I could find on areweguiyet.com (nowadays it doesn’t seem to be there at all). qmetaobject-rs look a bit more fleshed out but also QML-centric: I could find any examples of its use with plain old QtGUI so I gave up on it – perhaps prematurely.

          I suspect that most of my issues with rust are that I am trying to write Haskell in Rust, or trying to write C++ in Rust, instead of writing in Rust

          That was very much I experience when I started off with Rust: I kept writing things and thinking to myself “this would’ve Just Worked in C! Why is this so hard!?”. After a while the Rust Mindset clicks in and everything becomes fairly obvious from the get go – I found myself fighting the borrow checker a lot less the when I started subconsciously designing my programs in a way that it’s obvious what owns what. I imagine your experience might be negatively impacted by the fact that you’re trying to marry it to Qt which has its own mindset of what things are and how they talk, to it reinforces your regular habits and thus making Rust seem even more unnatural in this whole puzzle.

          1. 1

            qmetaobject-rs look a bit more fleshed out but also QML-centric

            It certainly is QML-centric. Whether that’s a good thing depends of course whether you want to use QML. Personally, I quite like QML, as long as it’s being used as a declarative UI description language, delegating all the heavy lifting to C++ or another language.

            I imagine your experience might be negatively impacted by the fact that you’re trying to marry it to Qt

            This is an excellent point.

    8. 7

      Gui toolkits are pretty bad in general, but I’ve had the most fun (and the least irritation) using Tk.

      That said – Tk is missing some fairly important modern features out of the box (like support for alpha & 24 bit colors), and some other features are only provided by third party libraries (like native-look widgets, embedding videos and html), and almost all bindings will involve dropping into tcl instead of using the C++ API directly (for … some reason), which adds whole classes of potential errors between user code and the actual toolkit. Tk also has some inconsistent naming gotchas, though fewer than any other toolkit I’ve used.

      Ultimately, if I need to write a GUI and I don’t need anything super fancy, the first toolkit I’ll reach for is Tk. It’s extremely widely supported (both in terms of platforms & in terms of bindings) and it’s very fast to get things up and running.

      1. 2

        I agree with everything you said. Chiming in with a positive anecdote: I successfully did a little side project (for $$$, not open source, so I cant show off the source code) using Python+Tk. I used Python because I needed NumPy + SciPy, and went with TkInter because I had used it before and found it straightforward to work with. I was able to deploy on Windows (what the client wanted to use) using pynsist with minimal troubles. I used ttkthemes to make the UI look a little more “modern”.

        Earlier versions of the program used the same stack but with PyInstaller, which also worked on Windows, but the executable size was a problem as it hugely inflated startup time.

        Another Tk program that I think turned out OK was gmixerctl, which I wrote during my stint of using OpenBSD on my laptop, as I missed pavucontrol. That was my first experience with TkInter, and I found it really easy to get started with.

        If you want to use Python, Perl, TCL, or another language with decent Tk bindings, it’s really nice for those small utility programs where you just need a few basic widgets to wire something up for the user. Another place it can shine is if you want to do some visualizations from one of those languages; the “canvas” is very easy to use and can export to some common formats. It beats fooling with something like d3.js and friends in my experience, especially if the rest of your code doesn’t run in a browser.

        As the parent posted noted, the situation for localization / HiDPI is not compelling however. I would probably not pick Tk for anything large or complicated.

    9. 5

      I actually like FLTK and even the FOX toolkit. These are both small and readable in my opinion. FOX is written by a single guy! They are largely C++98 style code but that doesn’t bother me, having written plain old C for so long. They produce relatively small binaries. The biggest drawbacks are no accessibility support and no Wayland and sadly it seems like it’s not possible to build a small toolkit with either of those things.

      Now, I do not write any native GUI software professionally, so this is all just for fun. If I did this professionally I’d definitely just pick GTK+.

      1. 2

        I really enjoyed FLTK as well, too bad it hasn’t evolved much since the late 90s.

    10. 5

      SWT (from Eclipse) was the least sucky of the non-web cross-platform options I’ve tried. Top-notch accessibility is an absolute requirement for any project I do, and SWT has that covered pretty well. It uses platform-native controls as much as possible, and implements platform accessibility APIs for its custom controls. Still, it kind of sucked, particularly on Mac. For some reason, SWT’s wrapper over the file picker dialog didn’t work for me on Mac, so I had to drop down to AppKit for that. I also had to drop down to AppKit to set up a global menu bar only on Mac the way I wanted it. (I didn’t want a menu bar on Windows.)

      wxWidgets takes the same general approach as SWT, but it doesn’t implement platform accessibility APIs for its custom controls. Also, there are some platform-specific gotchas. I’ve never done a major project with wx myself, but I have a friend who has done several. The biggest problem that he ran into is that to get an accessible, native list view control, you have to use wxListView on Windows, but wxDataViewCtrl on Mac. That’s a major divergence for an application that relies heavily on a list view in its main UI.

      Edit: I realize I didn’t exactly answer the question. But what I enjoy using is a bit beside the point. If I’m developing a cross-platform application, what matters to me is providing a good user experience (with a special focus on accessibility) while trying to reuse code across platforms. That’s work, not fun.

      1. 1

        I had an SWT app many years ago. I used JFaces, not raw SWT. It wasn’t too bad. Deployment with SWT always seemed like a major PITA, due to requiring the user to have Java installed. The cleanest option seemed to be bundling a jre with with the install. And if you’re bundling Java, why not use Swing? Or Exelsior Jet native compiler. How did you handle it?

        1. 2

          if you’re bundling Java, why not use Swing?

          Accessibility. Particularly on Windows, Swing uses something called the Java Access Bridge, which IIUC is kind of second-class with screen readers compared to native controls.

          As for how I handled deployment, I used Avian. Actually it’s more complicated than that. I wanted to write my application in Python, using CPython, so I could re-use some existing code from a previous project. So I used Avian with its own classpath library as just enough JVM to run SWT, then added pyjnius to bridge Java and Python. It was hacky but worked well enough.

    11. 4

      I experimented a bit with the Red language’s GUI toolkit and found it very interesting. It allowed me to quickly prototype and test some GUI idea once. See e.g. one user’s page with a list of simple examples

    12. 4

      Gtk+ has great support for bindings so it’s good in any language. Python & Rust for example are very pleasant to use.

      But I’m also fond of html+js+css running on a localhost web server. Jupyter is a great example of this. Can you imagine trying to build a UI that rich with any other tools?

    13. 3

      I’m making my own. Backend sdl, backend either nanovg or sw rendering. I wanted something retained mode (imo immediate mode is overrated), but still lightweight and embeddable.

    14. 3

      I’ve got a few cross-platform GUI apps I work on (eg evilpixie, a pixel-art app). My primary requirement is that stuff looks (reasonably) native on each platform.

      I’ve settled on Qt, and it’s great… but I do find it too big and overbearing for my tastes. I’d love to use libui for such things - it’s light and uses native widgets and all that, but there are still crucial bits missing for me - decent menu support, a bitmap wrapper, table widget… I’ve got high hopes for it though (and have contributed the odd patch here and there).

    15. 3

      Python’s TKinter has worked fairly well for me for some simple-ish GUIs in the past (there are Tk bindings for many languages, but I never used them). It doesn’t cover 100% of the use cases, but that’s fine. If you just want some simple light-weight GUI without too much ceremony and boilerplate code then TKinter works well.

      If you have a large complex app then Qt is probably a better choice in most cases.

    16. 2

      Stretching it but I like to make Telegram bots. I see it as a framework for making collaborative apps based on messages. You can send GIFs, maps, files, multiple choice keyboards, etc. And you get fast clients for mobile that a lot of people already have installed. All you need to do is some HTTP POST requests to api.telegram.org.

    17. 2

      ocaml + lablgtk if I want to write a small-footprint app that I can stick to building on linux and let other people deal with building on other platforms, racket if I have to distribute cross platform executables myself and if using a decent amount of ram is not an issue. (the racket gui does not take up nearly as much ram as electron but it’s still in the 100s of megabytes range.)

    18. 1

      HTML + JS

      Works on all the platforms most people care about.

    19. 1

      I’ve been working on my own ui toolkit in rust and metal/wgpu/vulkan (ill go full wgpu when it’s ready). Gui toolkits are overrated, rust makes it easy to roll your own.

      1. 11

        Gui toolkits are overrated, rust makes it easy to roll your own

        It’s easy to show a couple buttons. It’s not easy to support all input methods (keyboard, mouse, touch, tablet!), all windowing systems (okay there’s winit/sdl2/etc but they come with their own quirks), internationalization, accessibility, and complex widgets. And do it all well.

        1. 4

          Boy do I agree here. Working on https://github.com/Kethku/neovide has proven to me that in the current state its nearly impossible to do in rust. Font fallback alone is just not there yet. Let alone handling all the various keyboard layouts properly.

          1. 3

            ooh, I saw that one! I wish someone ported the cool cursor effects to Alacritty :D

            in the current state its nearly impossible to do in rust

            The language doesn’t really matter though, Rust can call anything (pango, harfbuzz, anything you want).

            And a terminal emulator style app is probably the canonical example where you can get away without a full GUI toolkit! This thread is more about “widgety” desktop UI stuff.

            handling all the various keyboard layouts properly

            hm, Alacritty (winit-based) doesn’t have any problems with my layouts (en(colemak), ru)

      2. 5

        I’m not trying to be snarky but if it were easy to do there would already be an easy, cross language, cross platform gui system. Even nice libs like QT or gtk don’t get you there