A new Julia GUI Engine has appeared! Mousetrap.jl is now available

Available here: https://github.com/Clemapfel/mousetrap.jl

Features

  • Designed specifically for Julia
  • Choose from 40+ pre-made Widgets, or create your own widgets from scratch
  • Fully abstracted, OpenGL-based rendering engine
  • Hand-written 10-chapter manual and verbose doc strings for every symbol
  • Available for Linux, Windows, and Mac
  • Licensed lGPL-3.0, meaning it can be used in closed-source, for-profit projects

Background

So far, when wanting to create a GUI for Julia, options were limited to wrappers around frameworks in other language, or web-based front-ends. Mousetrap aims to bring Julia users a native, fully featured, well-documented GUI engine that contains everything one would need to create a proper desktop App. This is made possible by calling the GNOME C software stack internally, though users of mousetrap will not have to interact with a single GNOME function or C-type directly.

Julia packages sometimes have a problem with lacking documentation. Intending to lead by example, I have put just as much effort into mousetraps documentation, as into the actual Julia code. This hopefully creates a smooth learning experience for users of any skill level.

While already fully featured, mousetrap just released, so some bugs or instability may be expected. Consider opening an issue when you encounter a bug, crash, or missing features.
Ideally, once Julia static compilation finishes
development
, mousetrap
will be stable and flawless, allowing Julia to become well suited for front-end development.

Thank you.
C.


Disclaimer

While also based on the C-versions GTK4 / Adwaita, mousetrap has no affiliation with GNOME or any of the developers of GTK.jl, or GTK4.jl.

I’ve also made an announcement on Reddit, which contains some additional comments on GNOME libraries in general.

98 Likes

Very nice! :grinning:

But it it does not work for me yet. Created an issue: hello world crashes on Ubuntu 22.04 · Issue #11 · Clemapfel/mousetrap.jl · GitHub

Excited to learn about this! A small issue with the “Julia Crash Course” in your manual: the code

struct T end
T() = return T()

causes infinite recursion. It can be replaced by e.g.

struct T
    T() = new()
end
1 Like

Could the installation process be simplified? Why is there more than one JLL? Is there any reason the packages are not registered?

4 Likes

How does this play with Makie? Can I present Makie plots and visualizations to the window you create?

I have been using Makie so far to create GUIs, so am surprised that Makie isn’t mentioned anywhere on this post or in the documentation.

4 Likes

Theoretically you could render to a OpenGL canvas, I have not tried this though and I don’t think it will be officially supported in the future

1 Like

I’m waiting for registering it until it’s somewhat stable, the reason for the multiple jlls can be found here. Once it’s on the registry installation will be a one-liner like it should be

5 Likes

What’s the main reason this doesn’t build upon Gtk4.jl?
Seems like it could just offer high level API for that?

6 Likes

awesome, now we just need to re-implement openscad with it :smiley:

1 Like

I found this statement surprising. I would guess that supporting GLMakie.jl is almost essential for Mousetrap.jl to be widely used for GUIs in Julia.

2 Likes

I have an application in which I need to display grayscale images in fullscreen on a second monitor. Can it be easily accomplished in Mousetrap.jl?

I think he means Mousetrap.jl is infrastructure code and he will not officially support GLMakie.jl; because it doesn’t need to (and/or he doesn’t want to maintain it).

[I see I misread, you were asking for support for (renderable) OpenGL canvas, rather than support for GLMakie, what I though you were asking for/needing supporting. If you were asking for support for OpenGL canvas, then that seems needed to be able to support GLMakei (it’s strictly not technically true, you could copy the pixels out of it, but then you would just rather use CairoMakie). Would support for CairoMakie in Moustrap be enough for you? I mean the possibility to use both together somehow, it means a similar thing, support for a renderable (non-OpenGL) canvas in Moustrap, that you could point CairoMakie to.]

I.e. not that GLMakie couldn’t depend on Mousetrap. Am I wrong, I think the support should go in the other direction, GLMakie supporting Mousetrap. Currently Makie supports OpenGL (optionally, i.e. one of its backends), with GLMakie, and it should depend on Mousetrap, rather than Makie? [Makie’s other backend, except for maybe CairoMakie, e.g. for Vulkan (for Nvida or AMD) would not work for Moustrap, since it uses OpenGL not Vulkan, currently at least.] GLMakie means targeting the screen, in some way, but always in a window (also full-screen supported?).

GLMakie thus could have used Moustrap, hypothetically (had it come first) or whatever (GTK4 or Qt also options) to provide that window. Currently it does display its windows using GLFW I believe.

You’re thinking of if you want to provide your own windows (or full-screen) with on (or more) graphs, coexisting with something else. Your application would do that something else, and thus depend on Mousetrap. But it would need to disable somehow the default method in GLMakie, of making its own window. I suppose it can’t be done without the help of GLMakie. I.e. it already created one for you.

What I think needs to happen and does happen, is that GLMakie makes an OpenGL context. You just have to have access to it, and you need to point it somehow towards Mousetrap. I think Moustrap might actually already support that (I’m not sure). But that just mean it will display it for you, and keep doing that, updating it transparently to the windows in case of changes, or with some manual intervention. But note, Mousetrap doesn’t need to know or care that’s it displaying, i.e. if it’s from GLMakie or you app or from somewhere else, to it it’s just a bunch of pixels.

[I know GLMakie is actually used for even one game already (a Minecraft clone if I recall). I can’t find it currently, but not it’s not to be confused with GitHub - JuliaBerry/PiCraft.jl: Manipulate Minecraft on the Raspberry Pi from Julia which is Julia controling actual Minecraft. I just stating this to point out you can do a lot with Makie, including 3D, and I suppose it adds some text overlayed, relating to the game. Possibly you could do what you want only with GLMakie. I suppose it’s missing what you want, GUI-interaction/pointing with the mouse, or (editable) text-boxes, stuff Mousetrap and the like is for. That GLMakie could be used for a game is likely because it’s keyboard controlled?]

I wasn’t directly asking for support for myself really, others were.

I was just surprised that supporting embedding Makie.jl is not one of the core aims of any new GUI library. Not necessarily via dependencies, just by making sure its easy to embed an OpenGL canvas and working with Makie.jl people like @sdanisch to make sure there are easy ways to get practical interop.

Its hard to overstate how good GLMakie.jl is for interactive visualization.

10 Likes

If Mousetrap.jl would just be an higher level API for Gtk4.jl, it would already “just work”:

Same goes for other projects like GtkObservables.

Seeing the deployment problems etc, is also the reason why I’m so surprised that it doesn’t build upon Gtk4.jl, so I suspect there must be some pretty good reason?

5 Likes

I couldn’t possibly agree more, and hence why I am equally as surprised as Raf to see no mentioning of Makie in the documentation.

To me this appears to be a case where it is better to reach out and work together rather than in isolation. But then again I know nothing about the source code of either opengl or mousetrap, so :man_shrugging:

Let’s try not to come across as accusatory here :slight_smile: While I also like seeing packages compatible with Makie, not everybody has an interest in plotting so the author might not even have had that aspect on their radar at all while writing the library. GUIs are a much broader area than what Makie covers. I’m glad someone’s putting in this kind of work into Julia’s GUI system one way or another, and we’ll see if there are synergies to be had with GLMakie in due time, I’m sure.

28 Likes

I thought that this was not an accusation. I apologize if it was perceived as such.

But I need to defend myself, because I feel like I voiced a reasonable opinion. For a simple user like me it is much better to not have to divide my time on deciding which competing tool should I be using for the same task and then learning such a tool (and yes, I’ve been using GLMakie to build GUIs so for me these two tools serve the same purpose). Many people that come to Julia as users share this opinion. I can provide this post as an example How can we create a leaner ecosystem for Julia? and in my experience teaching Julia this sentiment of wanting leaner ecosystem and more cooperation is rather common. So, I think it is normal to wonder why there was no effort (at all, according to the original post) on the package cooperation, which makes the front user experience simpler/easier. This isn’t an accusation. It’s voicing a common concern among many users.

4 Likes

Nice work! It would be great if interactive plotting is supported!

Right, sorry, did not mean to single you out like that and your reply wasn’t all that accusatory by itself. It’s just one of many messages in this thread questioning why the author of the package could possibly have done things this way, and if I was the author and reading those I’d certainly not feel so good about it. We always need to have an eye on the dogpiling mechanism in this forum, it happens pretty often when people are passionate about a topic.

24 Likes

Hi, I’m using Julia 1.11.1 and Mousetrap v0.3.1, and when trying to run the test as part of the installation process, I get the following error message:

julia> Pkg.test("Mousetrap")
     Testing Mousetrap

     Testing Running tests...
[ERROR] In Mousetrap.main: MethodError: Cannot `convert` an object of type Nothing to an object of type Mousetrap.detail._Window
The function `convert` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  convert(::Type{Mousetrap.detail._Window}, ::Mousetrap.detail._WindowAllocated)
   @ Mousetrap ~/.julia/packages/CxxWrap/5IZvn/src/CxxWrap.jl:686
  convert(::Type{Mousetrap.detail._Window}, ::Mousetrap.detail._WindowDereferenced)
   @ Mousetrap ~/.julia/packages/CxxWrap/5IZvn/src/CxxWrap.jl:687
  convert(::Type{Mousetrap.detail._Window}, ::T) where T<:Mousetrap.detail._Window
   @ Mousetrap ~/.julia/packages/CxxWrap/5IZvn/src/CxxWrap.jl:682
  ...

Stacktrace:
  [1] Window(_internal::Nothing)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:400
  [2] (::var"#176#180")(app::Application)
    @ Main ~/.julia/packages/Mousetrap/CHEs7/test/runtests.jl:2874
  [3] (::TypedFunction)(args::Application)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:91
  [4] (::Mousetrap.var"#14#15"{TypedFunction})(app::Application)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:1542
  [5] (::TypedFunction)(args::Application)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:91
  [6] (::Mousetrap.var"#6#8"{TypedFunction})(x::Tuple{CxxWrap.CxxWrapCore.CxxRef{Mousetrap.detail._Application}})
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:657
  [7] safe_call(scope::String, f::Function, args::Tuple{CxxWrap.CxxWrapCore.CxxRef{Mousetrap.detail._Application}})
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:190
  [8] run!(arg1::Mousetrap.detail._ApplicationAllocated)
    @ Mousetrap.detail ~/.julia/packages/CxxWrap/5IZvn/src/CxxWrap.jl:624
  [9] run!(app::Application)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:1511
 [10] main(f::Function, application_id::String)
    @ Mousetrap ~/.julia/packages/Mousetrap/CHEs7/src/Mousetrap.jl:1552
 [11] top-level scope
    @ ~/.julia/packages/Mousetrap/CHEs7/test/runtests.jl:2785
 [12] include(fname::String)
    @ Main ./sysimg.jl:38
 [13] top-level scope
    @ none:6
 [14] eval
    @ ./boot.jl:430 [inlined]
 [15] exec_options(opts::Base.JLOptions)
    @ Base ./client.jl:296
 [16] _start()
    @ Base ./client.jl:531
     Testing Mousetrap tests passed

julia>

What should I do in this case, in order for it to work properly?