A declarative way for fast creating simple GUI on Common Lisp
Switch branches/tags
Nothing to show
Clone or download
Permalink
Failed to load latest commit information.
examples Initial Commit Aug 19, 2016
.gitignore Initial commit Aug 18, 2016
LICENSE Initial commit Aug 18, 2016
package.lisp Initial Commit Aug 19, 2016
qt-utils.lisp Initial Commit Aug 19, 2016
readme.org Fix a little bugs on readme.org Aug 19, 2016
simple-gui.asd Initial Commit Aug 19, 2016
simple-gui.lisp Initial Commit Aug 19, 2016
utils.lisp Initial Commit Aug 19, 2016

readme.org

Simple-GUI

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-)

Then we will have a look at some examples. The first example is a simple dialog that says hello to the given name: ./examples/greeting.png ./examples/greeting1.png

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:

  • Use (q-application) first to create Qt Application instance, and refer to the single Qt Application instance the same way in program.
  • Use q-widget, q-push-button etc. 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 -.
  • Use :set inside a GUI element to set initial property of this element. For example, the (:layout ...) inside (:set ...) of (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 set-layout method call.
  • Use :add to add child widget or layout to parent widget or layout. Only subclass of q-widget and q-layout can be add in this way. It can add any number of child widget or layout. In (:add obj1 obj2 ...), each obj can either be a new object defined by any Qt GUI elements like q-h-box-layout or a existed Qt GUI element.
  • To refer to any existed Qt GUI element, use (gui object-name).
  • Use :connect or :con to 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) The web.lisp example:

./examples/web.png

The cards.lisp example:

./examples/cards.png

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 connect.
  • To use a Qt Enum, Foo::FooBar can 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/").
  • Use (q-connect object :clicked :bool #'func) or similar q-connect* macro to connect signal after create the gui element.
  • Use it to 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 foo to qfoo, they are indicated in simple-gui::*convert-special-cases*.