Simple-GUI is a declarative tool for defining GUI in Common Lisp. It’s more convenient than other Common Lisp GUI wrapper libraries when writing simple gui programs. Currently, it use CommonQt as its backend so it can run on both Linux, Windows and Mac with actually GUI built with the Qt Library. It’s quite staightforward to use. Start with loading the Simple-GUI library:
(ql:quickload :simple-gui) ;;; For easier use in small GUI applications, we recommend use these packages: ;; simple-gui for q-application and any GUI defining macros (use-package :simple-gui) ;; q- for all CommonQt methods, rename in a lispy way (use-package :q-)
The following is the source code:
(defun main () (q-application) (q-widget main (:set (:window-title "What's your name?") (:layout (q-h-box-layout - (:add (q-line-edit name) (q-push-button button (:set (:text "OK")) (:connect (:clicked #'(lambda () (information 'q-message-box (gui main) "Simple GUI" (concatenate 'string "Hello, " (text (gui name))))))))))))) (show (gui main)) (exec (q-application)))
Just run (main) in REPL will see the result. In the example above, we can see using Simple-GUI is quite simple to create simple GUI programs. Only things need to know:
(q-application)first to create Qt Application instance, and refer to the single Qt Application instance the same way in program.
q-push-buttonetc. to create a GUI element, the name mapping rule is
QFooBar => q-foo-bar. After this is a name given to this GUI element, which is in a different name space with common lisp variables and functions. If you don’t need to refer to this name after creating it, such as a layout, you can specify its name as
:setinside a GUI element to set initial property of this element. For example, the
(q-widget main ...)is use to set the layout of q-widget named main. The general rule is
(:set (:layout ...))will be convert to a
:addto add child widget or layout to parent widget or layout. Only subclass of
q-layoutcan be add in this way. It can add any number of child widget or layout. In
(:add obj1 obj2 ...), each
objcan either be a new object defined by any Qt GUI elements like
q-h-box-layoutor a existed Qt GUI element.
- To refer to any existed Qt GUI element, use
:conto connect a given Qt signal to a function, which can be a lambda or a function define later. Simple-GUI does’t provide a way to connect a Qt signal to a Qt slot, since in CLOS, methods (Qt slot is a special kind of method) don’t belong to class or instance, but a dependent concept. Restrict a Qt signal can only be connected to a function doesn’t restrict the functionality of Qt. If the original Qt signal takes arguments, such as
clicked(bool, int), you can use the connect as
(:connect (:clicked :bool :int) #'func). The Qt signal name conversion is the same as Qt methods, see the next instruction.
- Call Qt method in the same way as Common Lisp function or method. In fact, all Qt methods are in the
q-package. Put the object that this Qt method is call on in the first place of arguments and then other arguments. If this method is a static method, like
(information ...)as shown above, you should pass the Qt class name as the first argument, in the previous example, is
q-message-box. The Qt method name is converted in this way:
fooBar => foo-bar.
You may have a look on other examples in the examples directory.
web.lisp is a minimum Qt WebView demo, Simple-GUI provides all Qt GUI elements in the same way to use as above, including the
q-web-view and the Qt OpenGL module.
cards.lisp is a simple game, which require you to pick up cards with same picture to eliminate them (you need to run it after entering the examples directory, or press C-c C-~ in Emacs with slime after open the source)
There are some other usages of Simple-GUI not mentioned above:
- Use a
:connect*to connect the Qt signal but can pass an extra data to the function. For example,
(:connect* (:clicked) #'func data), the function connected to
func, which takes an additional argument as its first argument and then other arguments as same as when connect with
- To use a Qt Enum,
Foo::FooBarcan be refered to as
foo/foo-bar, to compare Qt Enums, use
(qt:enum= enum1 enum2).
- To create a non gui Qt Element, for example, QUrl, use
(q-new q-url "http://www.example.com/").
(q-connect object :clicked :bool #'func)or similar
q-connect*macro to connect signal after create the gui element.
itto refer to the current GUI element inside a GUI element constructing macro.
- You may refer to Qt 4.8 Official Doc to search for Qt classes and methods API.
- Some of Qt method names are conflict with symbols in common-lisp package, so they are renamed from
qfoo, they are indicated in