This blog post assumes that you have Erlang installed with wxWidgets support enabled, as this comes by default.

One of the things I like to do is to explore all the mysteries that OTP has bundled by default, and one of those things is wxErlang.

wxWidgets

But first, let’s talk about wxWidgets. wxWidgets is a GUI C++ library that allows developers to create applications that are cross-platform compatible. It was started in 1992 by Julian Smart. It’s object-oriented and has bindings for several programming languages, including Erlang.

wxErlang

It’s a binding for wxWidgets that OTP includes by default when installing Erlang. It’s used for applications like :observer and :debugger.

wxErlang is functional instead of object-oriented, and the events are managed as messages to processes. It allows multiple Erlang processes to handle the same application. The only drawback is that we need to do manual memory handling. This means destroying objects after using them.

Hello World in Erlang

It’s an Erlang library, so it seems fitting to start with an example in Erlang. For that, let’s start an Erlang Emulator or erl session

> erl

and type the following:

1> wx:new().
{wx_ref,0,wx,[]}
2> M = wxMessageDialog:new(wx:null(), "Hello World").
{wx_ref,35,wxMessageDialog,[]}
3> wxMessageDialog:showModal(M).
5100
4> wxMessageDialog:destroy(M).
ok

wxMessageDialgo modal

Don’t you love the dots at the end of each line?! But enough of Erlang! This is an Elixir blog post.

Hello World in Elixir

We’ll write the same program but this time in iex instead of erl using Elixir.

So, fire up an iex session

> iex

and type:

1> :wx.new()
{:wx_ref, 0, :wx, []}
2> m = :wxMessageDialog.new(:wx.null(), 'Hello World')
{:wx_ref, 35, :wxMessageDialog, []}
3> :wxMessageDialog.showModal(m)
5100
4> :wxMessageDialog.destroy(M)
ok

wxMessageDialgo modal

Great! We got a message dialog with the text “Hello World”. Let’s dig deeper into what we are doing

1> :wx.new()

This line creates an environment and memory mapping with wxWidgets and needs to be called once per application at the beginning. It stores a reference in the current process, you can see it by doing Process.info(self()) and looking for the wx_env key.

2> m = :wxMessageDialog.new(:wx.null(), 'Hello World')

And this creates a new MessageDialog object with the text “Hello World”. You had probably noticed that we are passing a charlist instead of a binary. This is because Erlang uses charlist instead of binaries as strings. :wx.null() tells the message box that this element doesn’t have a parent, it’s a top level element.

3> :wxMessageDialog.showModal(m)

The previous line created the message box object, but we need to call showModal to make it visible.

4> :wxMessageDialog.destroy(M)

Lastly, after we close the message box, we need to destroy the object to reclaim the memory. Remember that this is a C++ library.

Some real examples of wxErlang

wxErlang demo

:wx.demo()

wx demo

Erlang/OTP observer app

:observer.start()

observer

Erlang/OTP debugger app

:debugger.start

debugger

You can find other examples here.

Conclusion

This was just a quick introduction to wxErlang. Now you know that this binding exists and comes by default with OTP. Applications like :observer and :debugger use it for their UI. In a next post, we’ll dig deeper into how to use wxErlang to create more complex applications.