9 ms·
GUI development with Rust and GTK 4
- tcper 4y agoFirst time known GTK supports CSS.
- pshirshov 4y agoOh, they even had support for hotkey customization with css rules but, unfortunately, got that removed too.
- nextaccountic 4y agoWhat about relm4? Is it generally feature complete? Can one use relm4 for most things, and drop to gtk4 for the oddball task that is not supported? https://relm4.org/ https://relm4.org/
- phaer 4y agoDon't know relm4, but website says its based on GTK as well
- mixedCase 4y agoRelm4 is actually based on gtk-rs, and you will be using gtk-rs widgets all the time. I have to say however that despite heroic efforts by the authors, it doesn't really feel as nice as the "real" Elm architecture precisely because of the imperative focus of gtk-rs' API, the nature of Rust's memory management system, and depending on what you're doing you may feel forced far too often to drop from fantasy land to reap the benefits of the abstraction. I'd still consider it next time I tackle a native app, but having tried Slint for writing simple UIs and having read some iced code, I think I'd only go for it if I'm really going for the Gtk native look and ecosystem.
- nextaccountic 4y agoYep, relm4 is based on gtk4! What I am asking is, does relm4 have all gtk4 widgets and is generally feature complete? Is there any reason at all to prefer using gtk4 directly rather than the more ergonomic relm4?
- mixedCase 4y agoYou may have to do some bindings yourself, I remember once looking to try out a libadwaita widget and it wasn't fully supported in the available bindings, don't know about the full library of gtk4-specific widgets. As for feature complete, depends on your definition. It's on 0.6 and major changes do arrive and updates do break user code, but you certainly can write apps with it.
- nu11ptr 4y agoAFAIK, for better or worse, this is the only UI crate (other than HTML-like UI using something like Tauri) that provides a full set of widgets/capabilities on Rust. Every other UI lib is incomplete in some way or falls short for anything other than a toy or specialty type app in my experience. UPDATE: Things I have my eye on as they mature: Slint, egui, and iced. I'm especially watching iced as Pop_os is using it for their DE and likely will add quite a few widgets.
- DoctorOW 4y agoThere are plenty of situations where GTK might be better than Slint, but not so overwhelmingly that I'd call it only for toy apps.
- nu11ptr 4y agoWhile you can create one on your own, any lib that doesn't have a tree widget isn't ready for primetime IMO. Obviously others may have a different opinion. Also, I don't believe there is any way to embed a webview at this point which is often necessary to embed things like charts or other widgets you don't want to create on your own.
- jerf 4y agoGUI toolkits are like MS Word... as the saying goes, everybody only uses 10% but everyone uses a different 10%. This is one of the major things that makes it so hard to have a truly world-class widget set. Making "a" widget set is easy. Making a great one is staggeringly enormous.
- nu11ptr 4y agoI agree - which is why it seems like a better idea to either write bindings to an existing one or use something like Tauri/flutter/etc. It will be VERY hard to both 1) create an adequate UI paradigm in Rust -AND- 2) have a complete widget set large enough to create any business app
- 4y ago
- kramerger 4y agoWhat are the disadvantages of using 'static here? I wonder if a garbage collected language would have a more accurate life time for that object
- CyberDildonics 4y agoYou wonder based on what? Static will put something in the binary itself and it will be memory mapped in, which won't even need to be directly allocated.
- vlovich123 4y agoThe apostrophe isn’t superfluous. ‘Static in this context refers to static lifetime. Lifetimes have absolutely 0 impact on runtime.
- CyberDildonics 4y agoI'm not sure what this has to do with the parent post or how it contradicts what I said. https://doc.rust-lang.org/std/keyword.static.html https://doc.rust-lang.org/std/keyword.static.html
- vlovich123 4y agoYou are referring to static variables which have ‘static lifetime. OP is asking about ‘static lifetime and whether GC would somehow collect garbage more precisely (it wouldn’t). You’re basically talking past each other.
- celeritascelery 4y agoHow would you get a static lifetime without a static object?
- unshavedyak 4y agoUnrelated to the above convo, but: An owned object can be bound by a static lifetime, for example. Eg, `fn foo<T: 'static>(t: T){}\n foo(String::new());`
- jph 4y agoRust GTK4 "hello world" app, as a downloadable project, demonstrating the builder pattern: https://github.com/SixArm/rust-guideposts/blob/main/projects/crates/gtk4/hello_world/src/main.rs https://github.com/SixArm/rust-guideposts/blob/main/projects...
- codedokode 4y agoHonestly this looks like programming style from 90s. Why not design UIs in an editor that saves layout to XML?
- maister 4y ago> Why not design UIs in an editor that saves layout to XML? Not sure if you are being sarcastic or not, but nothing is more 90s than XML based layout descriptions. Mozilla XUL (recently retired) comes to mind.
- silon42 4y agoXUL needs to be resurrected (reimplemented)
- afavour 4y ago> Why not design UIs in an editor that saves layout to XML? It's funny because that's my personal nightmare. I'm a JS to Rust developer so I'm biased but the likes of React and Svelte have spoiled me with the ease with which you can integrate reactive components into a UI in a way that you simply can't when you're using a separate XML file. I agree that the example given looks old-school but Rust has a wonderful macro system, I can imagine building a really slick compose method with macros that generates this kind of code underneath.
- geekrax 4y agoI guess we have come the full circle. Speaking from a mobile dev's perspective, the native UI design in 2010s was done by XML based files (storybooks in iOS/macOS, XML layout files in Android) and native code would "connect" with the XML files in various ways. Now the development is moving towards declarative approach using frameworks such as SwiftUI and Compose. This builder pattern resembles quite a bit of how you would declare UI in SwiftUI and Compose.
- jscipione 4y agoI wondered how Rust would tackle the problem of creating a GUI without C++/Java style inheritance and now I see the answer: you must explicitly compose all "inherited" traits in your subclass. "Unfortunately, nobody found yet a good way to do that. Which is why, as of today, subclassing of GObjects in Rust requires to mention all ancestors and interfaces ..."
- jerf 4y agoYou can create UIs entirely out of composition. It's not even that hard, or that foreign per se. The problem you see there is a mismatch between Rust and GTK specifically, not GUIs in general. Of course, all the major GUIs are inheritance based, but I count that as less evidence than I might under other circumstances because GUI toolkits are multi-decade endeavors at the top end, and all the viable ones date to when inheritance was still the Law of the Land.
- shadowgovt 4y agoReact is the most interesting GUI approach to me in this regard, as while you can use inheritance if you use the class-based component approach, functional components are, well, functions and can be built by rules of composition. I tend to do a lot of UI in the form of "component with a dozen parameters that almost nobody wants to use every day" that is wrapped by "specialization of the general component that has a few parameters and then uses the general component by wiring those parameters and some logic together." Any type of "hot patching" is a bit more difficult (I can't easily just reach down a component's tree and mutate it from outside, not unless I've pre-wired the component to allow for that, and the semi-artificial limitation of the use of the tree model as a single `children` property means that such odd wiring gets weird fast if I want to get fancy). But it's a perfectly serviceable UI toolkit framework that is free of requiring inheritance. ETA: deferring to nu11ptr's taxonomy, React is not a widget toolkit by any means by itself. I find https://react.semantic-ui.com https://react.semantic-ui.com to be perfectly serviceable in that regard as a base, easy-to-modify widget toolkit.
- mike_hearn 4y ago
- SaintSeiya 4y agoAt this rate programming languages will reinvent GUI builders from Delphi/Lazarus in 2050
- dagw 4y agoI still find it quite sad that the pinnacle of GUI programming tools was reached over 20 years ago, when Delphi 6 was released, and we've been going more or less downhill ever since.
- afavour 4y agoI see it differently: UI needs have gotten more complex. Like how we used to have web sites that said "best viewed in 800x600 in Netscape Navigator" we rarely design one size fits all UIs any more like we did in Delphi.
- SaintSeiya 4y agoThere's nothing in "modern" UI that cannot be done with Lazarus GUI Builder: Dynamic layouts? check, anchors? check, flexbox? check, custom components? check nested hierarchies of elements? HIDPI? check Vector Graphics? check Multiresolution? check and so on. All of them compiled to native (and looking native) on every platform under the sun. As said before, GUI design peaked in the 90's
- zacmps 4y agoDoes that extend to internationalisation or accessibility? (Real questions, Lazarus was before my time)
- nu11ptr 4y agoHonestly, all the momentum went to web UIs...desktop UI R&D then just died more or less.
- oblio 4y agoTechnically the pinnacle was around 2010. Guess what happened around that time? Firstly, the web won. Secondly, mobile cemented the demise of the desktop. Especially since mobile is horribly anti-crossplatform GUI toolkit, especially against open source toolkits.
- JaggerJo 4y agoThe code to declare/build the widgets is quite nice. Modifying widgets by hand on certain signals or manually re-wiring all the signals seems a bit outdated to me. Wonder if something like FuncUI [1] could be built on top of it. [1] https://github.com/fsprojects/Avalonia.FuncUI https://github.com/fsprojects/Avalonia.FuncUI
- nkrisc 4y agoIf you're like me and like pictures in your books: https://docs.gtk.org/gtk4/visual_index.html https://docs.gtk.org/gtk4/visual_index.html
- curt15 4y agoThis is a typical code snippet: final class Gtk.Label : Gtk.Widget implements Gtk.Accessible, Gtk.Buildable, Gtk.ConstraintTarget { /* No available fields */ } What language is that in?
- pdntspa 4y agoHas anyone gotten GTK to compile on Windows without using MSYS? I would love to use pygobject with Python but the build chain and how to get it working is extremely confusing to me. Back in the days of gtk2, pygtk2 used to work wonderfully and compiled with MSVC
- mitchhentges 4y agoIt's a hidden gem, but gvsbuild [1] has made it easier again these days - I just discovered it ~a year ago and it's beautiful :) [1] https://github.com/wingtk/gvsbuild https://github.com/wingtk/gvsbuild
- gwbas1c 4y agoWhat about making it easy to import Rust business logic into C# / Swift / whatever GUI language you're using? I get the value of 100% (or 50% or 80%) implementing the UI in Rust; especially for tools that won't benefit from a native UI, or tools that only need light integration into platform-specific UI features. I've also shipped a desktop product that had a 100% native UI and a cross-platform codebase. Today, implementing that cross-platform codebase in Rust and then importing it into native C# and Swift codebases for the Mac and Windows variants would be ideal.
- bradrn 4y agoNo experience with Rust, but for a couple of personal projects I’ve written the logic in Haskell and the GUI in C++ (e.g. https://github.com/bradrn/brassica/blob/master/ARCHITECTURE.md https://github.com/bradrn/brassica/blob/master/ARCHITECTURE....). It works pretty well, at least for smaller projects — the basic idea is that the Haskell code gets compiled into a library (static on Windows, dynamic on Linux) which the C++ side can link to. I’d imagine doing the same with Rust would be even easier, since it’s less of a pain to marshal stuff across the language barrier.
- bryanlarsen 4y agoThat's a good option. It's easy to make a library in Rust that exports a C linkage, and it's easy to link a C library in most languages. Some languages have richer linkages to Rust (for example Python). A similar option would be to use the native UI with a Rust binding -- for example cacao on MacOS. The advantage of this approach is if your whole team knows Rust they can help with patching and maintenance. It doesn't help at the beginning because presumably the person who knows AppKit also knows ObjectiveC and/or Swift. But once the UI is created a single code base is an advantage for maintenance.
- kodablah 4y agoHaving integrated C# and Rust recently[0], I have found that unlike Node w/ neon and Python w/ PyO3 + PyO3 Asyncio, there is no good Rust integration with .NET. Interopterus, rnet, etc leave a good bit to be desired. I ended up writing all the unsafe bindings myself and used cbindgen on the Rust side to make a header and ClangSharpPInvokeGenerator to generate the C# binding. But you still have to manually handle ownership/freeing yourself, e.g. with SafeHandle. The ecosystem[1] could use something better, but nothing is there yet. 0 - https://github.com/temporalio/sdk-dotnet https://github.com/temporalio/sdk-dotnet, specifically https://github.com/temporalio/sdk-dotnet/tree/main/src/Temporalio/Bridge https://github.com/temporalio/sdk-dotnet/tree/main/src/Tempo... 1 - https://areweextendingyet.github.io/ https://areweextendingyet.github.io/
- rvz 4y agoWhy use this when it implements one platform's GUI well, and for the others platforms (Windows, macOS) it does it very badly? At this point, you might as well use Tauri.
- TingPing 4y agoDepends on your goal. Linux can be a project’s primary platform, or you can do a native UI on each platform.
- rvz 4y agoBoth options are very time consuming and maintenance heavy building a native UI for each platform. If I were to do that, I would target Windows and Mac first since that is where the users are. Tauri is the obvious choice to target all platforms in the quickest amount of time to market with less native specific maintenance.
- TingPing 4y agoYou assume every project is commercial. I just make software to solve my problems and I use Linux. GTK is the nicest option to me.
- mwcampbell 4y agoIt may be worth noting that GTK, including version 4, doesn't have any accessibility support for Windows or macOS, but only for free desktops using AT-SPI.
- dpcx 4y agoThe documentation looks better than when I was trying to write some Rust with GTK (2020), when it was basically an output of the C functions that could be called...
- PaulDavisThe1st 4y agoWhile I do not, and almost certainly will not, code with Rust, it was very interesting to read this and compare it to doing GUI programming with Gtkmm (the C++ wrapper for GTK), which I've done for more than 20 years. Some things seem a bit weird and ugly, and some idioms seem rather nice. Overall, not a clear win but certainly worth seeing the differences and similarities and thinking about them a little bit.
- butz 4y agoWould it be a good idea for a programmer that did not work with Rust before, to dive into GUI programming with GTK4? I'd like to build a simple desktop application for mainly personal use, been dabbling with PyGObject and GJS a bit, but haven't accomplished much yet.
- larusso 4y agoI got flashback memories from my days in Obj-c. I love rust but tend to stay away from reference counting as much as possible :). The first example with the two buttons showed my main annoyance with them. They had to decide which closure keeps a strong reference and which one a weak. A refactor later can be a tricky thing because one always needs to double check again if the reference links are still correct. At least with obj-c these errors will only pop up at runtime.
- throwaway689236 4y ago> At least with obj-c these errors will only pop up at runtime But it's not a good thing. There's still an error, you're just increasing the chance to miss it.
- larusso 4y agoNo I wanted to imply that I actually don’t know how rust handles this case. I think runtime errors are the worst especially with UI. Even when you have a full integration e2e test suite. I take compile errors over runtime errors any day.
- bsder 4y agoGreat! So, let's refactor that UI code out into a function. Something a beginner is very likely to do as that code becomes more complex. Oops. The borrow checker is going to beat you over the head. And beginners aren't likely to understand that it isn't their fault. Rust needs to figure out a way to do GUIs ergonomically without requiring closures.
- kangalioo 4y agoWhich UI code specifically are you referring to and why would the borrow checker prevent you from factoring it out?
- bsder 4y agoWell, I think the one that stuck out was here: https://github.com/SixArm/rust-guideposts/blob/main/projects/crates/gtk4/hello_world/src/main.rs https://github.com/SixArm/rust-guideposts/blob/main/projects... But here: https://github.com/gtk-rs/gtk4-rs/blob/master/examples/text_viewer/main.rs https://github.com/gtk-rs/gtk4-rs/blob/master/examples/text_... and here: https://github.com/gtk-rs/gtk4-rs/blob/master/examples/clock/main.rs https://github.com/gtk-rs/gtk4-rs/blob/master/examples/clock... The moment some poor slob of a beginner tries to refactor any of those closures into a "normal" function, they're going to get beat over the head by the borrow checker. Yes, I know why they're required in Rust. And it makes sense once you know Rust well. But a beginner isn't likely to understand why they can't refactor a closure into a function in Rust without a whole lot of clone(). Coding "examples" for Rust need to stop using that closure style--especially in "beginner" code.