GUI Recommendation and tutorial?

I am terrrible at Guis. (The last one I built was using perl/tk in 1997.)
For the toy I am using to learn Rust, I need to build a gui. Relatively simple windows, some scorlling panels, some pull down lists, some buttons, and some text boxes. I expect a real graphic designer could do much better, but I will settle for simple.
From what I have been able to find, it looks like egui / eframe is suited to the task. Is that a good choice, or is there something cleaner?
Also, it would really help if there were a tutorial rather than just samples. Did I miss that?
Thank you,
Joel

Looks like there are tk bindings - if you want to revisit 1997:

https://crates.io/crates/tk

1 Like

For me iced is the library that feels most native to use in Rust. But, be aware, that it uses a lot of advanced features of the language and thus might be a bit harder to use by someone new to Rust itself. The code base itself is very well structured and there are a bunch of apps out there that are worth a look, even if you are not interested in iced itself.

To get you started, there is the Unofficial Guide and a lot of examples in the repo itself.

Feel free to join the iced discord. Good community, with very helpful people.

1 Like

I’ve used egui+eframe in some projects with simple GUI, nothing fancy. It really is straightforward to use. I managed to create some GUI by just following (I.e., copy +paste +adapt) the examples. A tutorial would be nice, yes, but you can create a simple GUI using eframe without one.

1 Like

I like egui, though when I started using it it was the first time I had done anything non-trivial with an immediate mode GUI, and it took me a while to wrap my head around the idea of recreating the entire GUI on each frame.

It's surprisingly easy to use (again, once the paradigm clicks (if you have only used retained mode GUI's before)).

Because it needs to be fast, its layout engine doesn't come close (feature-wise) to things like CSS. (Though even ignoring performance requirements, I would argue that's a feature, not a bug). The lack of flamboyant layout features had a very positive side-effect for us: We realized after a while that we spent far less time trying to understand how to, proverbially, "center a div". (That's not to say egui is completely devoid of these types of issues, but the point is that you pretty quickly discover whether something is possible or not, and can move on if it isn't).

If you need an external source to update the GUI then some special handling is needed. For instance, if the GUI is idle, but a thread receives a notification from a server, which should cause the GUI to update, then you need use a mechanism to force the GUI to update itself. This is very easy to do, but it's something we weren't aware of in the beginning and it caused some confusion.

I too am terrible at GUIs. And from that perspective, I would recommend egui.

1 Like

I found the fltk crate quite helpful and lightweight. Also, fltk-fluid allows to build the UI with the help of a graphical interface. I haven’t used that in a long time, so I don’t know the current status.

The default look is a little bland, but you can apply other themes.

Thanks. This and the other replies are VERY helpful.

This is an interesting alternative. I like the Unofficial Guide and related resources. On the other hand, I think there is a killer constraint I should have mentioned and forgot. While I need to do the development on Windows, the result needs to run on MacOS.
Yours,
Joel

Your life will be easier if you can find a macos box to compile your macos binary. Go ahead and develop on whatever OS you like but compile on the os you want to run on.

Good point. I can install Rust on the MacOS box when I get that far. And then copy the src over. The MacOS box is my wife's. And the goal, if I actually get this to work, is for her to use the program.

I have asked on the iced discord, and the response was iced works very well on Macs, too.

Thanks. I had misread the notes I saw. Now I have to read both egui and iced more carefully :slight_smile:
Yours,
Joel

Regarding portability, egui also supports running on a browser / wasm.

3 Likes

Yep, I release OneTalker for macOS, but to build pkgs and sign things, it's best doing that all directly in macOS. I know atim cross compile with zigbuild though, but they build dmgs only. Most of my stuff I borrowed (with recognition) from halloy which is one of the best iced apps out there. Read their code.

Consider also using web UI and graphics. It is very portable and you won't tie with a particular framework.

Saw a passing mention of something in looking at one of the iced examples. Are iced or egui inherently multithreaded? I am using RefCell/Rc/Weak in my underlying data model. I know there are alternatives I can use that are multi-threading safe.
Yours,
Joel

I can only speak about egui, and no it's not multithreaded (in the sense that you can pass UI contexts to different threads and use them from there (with some minor exceptions (see below))). The typical way to do multi-threading is to use channels to communicate between the UI thread and the background worker thread(s).

Sending messages from the GUI to a worker thread is trivial, but the reverse requires some understanding of how egui's immediate mode works.

So there's an update() function that is called for every frame. In it, you nonblockingly check if there are messages waiting:

  fn update(&mut self, ...) {
    if let Some(msg) = self.rx.try_recv() {
      // Received a message from worker -- process it
      // here, in the GUI thread
    }
  }

The problem I mentioned earlier concerns this precise construct. When egui notices that nothing is happening, it stops updating the GUI. In practice, this means that it stops calling its update() function, which means it won't be able to pick up any messages sent to it. Like I mentioned before, there's a very easy way to solve this, and this is where there is some limited multi-threading support. There is a egui context that can be cloned and passed to another thread. This context can be used to force egui to run its update() function on next frame (making it pick up any waiting messages, in the example above).

(You can also force it to call its update by simply moving the mouse pointer over an egui application window, but that's probably not what you want to rely on).

3 Likes

I do the same, but I do not use Weak. My model can obtain new nodes, but never destroys existing ones, so I am fine to have extra references.

I have been trying to construct a useful GUI in iced. There are a lot of things I like in iced. And between the examples and the compiler feedback I can often make the pieces I have found compile and function.
I have read the author's explanation as to why the documentation is lacking. I understand that the author prefers coding to documenting. (I sympathize but disagree; a separate topic.) But I hvae to observe that using the examples and very limtied explanations to navigate,figure out how to build what one needs, and figure out even what widgets really do, is qutie challenging. Presumably, if one was an experienced GUI programmer coming from a similar framework, it would all just flow. I am not yet even at a place where I can offer to help with the documentation, as all my understanding is guesses.