DEV Community


Posted on • Updated on

Creating fast GUIs with Crystal, GTK and Glade

There's this misconception that building GUIs is often hard, tedious and requires a lot of skill. Or at least that's what electron was supposed to fix.

While electron certainly gives developers a head-start, it also hides many problems that they are going to come across. Some of which are: Performance, Vulnerabilities and Build Sizes.

When it comes to native GUIs, as a GNU/Linux and GNOME enthusiast, I decided to go with GTK, a FOSS widget toolkit for GUIs.

Let's get started!


Glade is a RAD tool that enables quick and easy development of user interfaces for the GTK toolkit and the GNOME desktop environment.


From my time playing around with Glade, I made the following conclusions:

  • It's fast
  • It's easy
  • It's beautiful

glade screenshot

The middle panel is where you create your UI, by drag-n-dropping widgets from the menu bar. If you are familiar with CSS' flexbox, you can use similar concepts using containers > boxes, allowing you to create responsive designs!

On the right panel, you get to edit properties of the selected widget. You might notice (by looking at the left panel) that I haven't given all widgets an ID, that's because most of them are static and I don't need to know or edit their properties in backend.

IMPORTANT: Don't forget to bind the destroy signal under GtkWidget of your main window to gtk_main_quit so that the backend exits when the window closes!

signal bind screenshot


I used Crystal for my backend. There's a shard that provides binding for GObject Introspection.

GitHub logo jhass / crystal-gobject

gobject-introspection for Crystal

The repo includes many examples to get you started!

First things first, we need to load and bind our Glade file:

builder = Gtk::Builder.new_from_file "#{__DIR__}/"
Enter fullscreen mode Exit fullscreen mode

Now, let's say that we made a Switch in Glade, with the ID of my_switch and we want to check if it's ON or OFF:

my_switch = Gtk::Switch.cast(builder["my_switch"])

puts "my_switch is #{ ? "on" : "off"}"
Enter fullscreen mode Exit fullscreen mode

Every widget has it's own events and properties, like Gtk::Switch#on_state_set which gets triggered when the state of a certain switch changes!

TIP: Unsure about what's available? Use macros!
eg. {{ &.name.stringify }}

Last but not least, it's time to show our window (in my case, with the ID of main_window):

window = Gtk::Window.cast builder["main_window"]
Enter fullscreen mode Exit fullscreen mode

And that's all!


I used it to create a GUI for my previous project, Crycord:

GitHub logo GeopJr / Crycord

A Discord Client modification with plugins. Uses BeautifulDiscord's CSS injector. Oh it's also written in Crystal!

Ko-Fi donate button liberapay MIT


Crycord is a modular Discord Client Mod written in Crystal.

Uses asar-cr.


You can download the statically linked build from the releases page!


  1. shards install
  2. crystal build --release

Note: Static builds can only be built in AlpineLinux


$ ./crycord -h

<== [Crycord] ==>
    -v, --version                    Show version
    -h, --help                       Show help
    -l, --list                       Lists all available plugin groups & plugins
    -r, --revert                     Reverts back to original asar
    -p PLUGINS, --plugins=PLUGINS    Selects the plugin(s) to install. Split multiple groups with commas(,).
    -c CSS_PATH, --css=CSS_PATH      Sets CSS location
                                     Forces an asar path
                                     Selects the plugin group(s) to install. Split multiple groups with commas(,).
$ ./crycord -c ./Downloads/css.css

Flatpak Detected:
Make sure it has access to your CSS file
Usually ~/Downloads is accessible
Extracting core.asar...
Installing enable_css...
Installing enable_https...
Packing core.asar...
Restart Discord to see the results!


There's a GTK…

which can be found here:

GitHub logo GeopJr / Crycord-GUI

A GUI for Crycord written in Crystal, GTK and Glade

Ko-Fi donate button liberapay MIT


Crycord-GUI is a gui for Crycord using GTK.


You can download the statically linked build from the releases page!


  • Run it
  • Ta-da!


Most of the interface is made using Glade. Use IDs only on widgets you are planning to modify. Switches' IDs in the 'Plugins' tab should match the names of plugins and groups of Crycord.


main plugins run revert about


  1. Fork it (
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request


  • GeopJr - creator and maintainer

I'm happy with the way it turned out, here's a screenshot of it displaying the STDOUT of Crycord:

screenshot of crycord gui

Had quite some fun as this is my first experience with GTK and will definitely use it more in the future!

Discussion (0)