You are on page 1of 64

ZetCode Ruby Qt tutorial

This is Ruby Qt tutorial. In this tutorial you will learn the basics of GUI programming in Qt with Ruby language. The tutorial is suitable for beginners and intermediate programmers.

Qt
Qt is a cross-platform application development framework. ome of the well known applications developed with Qt are !"#$ %pera$ Google #arth and kype. Qt was first publicly released on &ay '((). It is dual licensed. That means$ it can be used for creating open source applications as well as commercial ones. Qt toolkit is a very powerful toolkit. It is well established in the open source community.

Introduction to Ruby Qt
In this part of the Ruby Qt tutorial$ we will introduce the Qt toolkit and create our first programs using the Ruby programming language. The purpose of this tutorial is to get you started with the Qt toolkit with the Ruby language. Images used in this tutorial can be downloaded here. I used some icons from the tango icons pack of the Gnome pro*ect.

About
Qt is one of the leading toolkits for creating graphical user interfaces. Ruby is a popular scripting language.

Creating a Tooltip
The first e+ample will show a tooltip. , tooltip is a small rectangular window$ which gives a brief information about an ob*ect. It is usually a GUI component. It is part of the help system of the application.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This code shows a tooltip on a window. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize

'

super set*indowTitle ,Tooltip, setToolTip ,This is Qt::*id+et, resize #-$. %-$ o/e 0$$. 0$$ show end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

The e+ample creates a window. If we hover a mouse pointer over the area of the window$ a tooltip pops up.
re&uire 'Qt'

The re&uire keyword imports necessery types that we will use in the application.
class Qt(pp ) Qt::*id+et

The e+ample inherits from a Qt::*id+et. The -idget class is the base class of all user interface ob*ects. The widget is the atom of the user interface. It receives mouse$ keyboard and other events from the window system.
set*indowTitle ,Tooltip,

This method call creates a title for the window.


setToolTip ,This is Qt::*id+et,

The setToolTip method creates a tooltip for the -idget ob*ect.


resize #-$. %-$

.ere we set the width and the height of the window.


o/e 0$$. 0$$

The o/e method moves the window on the screen.


show

-hen everything is ready$ we show the window on the screen.


app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

These three lines set up the application.

0igure1 Tooltip

Centering a window
In the second e+ample$ we will center the window on the screen.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra centers a window on the screen. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' *56T7 1 #-$ 78527T 1 %-$ class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,Center, resize *56T7. 78527T center show end de! center &dw 1 Qt::6es9top*id+et.new screen*idth 1 &dw.width screen7ei+ht 1 &dw.hei+ht 4 1 :screen*idth ; *56T7< / # y 1 :screen7ei+ht ; 78527T< / # o/e 4. y end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

The Qt toolkit does not have a single method to center a window.


*56T7 1 #-$ 78527T 1 %-$

These two constants define the width and height of the application window.
&dw 1 Qt::6es9top*id+et.new

The Qt::6es9top*id+et class provides information about the screen.


screen*idth 1 &dw.width screen7ei+ht 1 &dw.hei+ht

.ere we determine the screen width and height.


4 1 :screen*idth ; *56T7< / # y 1 :screen7ei+ht ; 78527T< / #

.ere we calculate the +$ y coordinates of the centered window. To center a window on the screen$ we need to know the si3e of the screen and the si3e of the window.
o/e 4. y

-e move the window to the computed +$ y coordinates.

Quit button
In the last e+ample of this section$ we will create a 4uit button. -hen we press this button$ the application terminates.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra creates a &uit button. *hen we press the button. the application ter inates. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize

super set*indowTitle ,Quit button, init=ui resize #-$. %-$ o/e 0$$. 0$$ show end de! init=ui &uit 1 Qt::>ushButton.new 'Quit'. sel! &uit.resize ?$. 0$ &uit. o/e -$. -$ connect &uit. "52@(A:'clic9ed:<'<. B&(pp. "ACT:'&uit:<'< end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

The Qt::>ushButton class shows a button in Ruby Qt. It is a rectangular widget and usually shows a te+t label.
init=ui

-e delegate the creation of the user interface to the init=ui method.


&uit 1 Qt::>ushButton.new 'Quit'. sel!

-e create the button widget. The first parameter of the constructor is the label which the button displays. The second parameter is the parent widget of the button.
&uit.resize ?$. 0$ &uit. o/e -$. -$

-e si3e and position the button widget.


connect &uit. "52@(A:'clic9ed:<'<. B&(pp. "ACT:'&uit:<'<

The clic9ed signal is emitted$ when we click on the 4uit button. The connect method connects a signal to a particular slot of an ob*ect. In our case it is the &uit method of the application ob*ect. The B&(pp is a global pointer to the application instance.

0igure1 Quit button This section was an introduction to the Qt toolkit with the Ruby language.

Layout management
In this part of the Ruby Qt programming tutorial$ we will introduce layout managers. -hen we design the GUI of our application$ we decide what components we will use and how we will organi3e those components in the application. To organi3e our components$ we use speciali3ed non visible ob*ects called layout managers. There are several options in Qt. -e can use absolute positioning$ built-in layout managers or create a custom layout manager. -e can also visually build the layouts using the Qt "esigner. Qt has some important built-in layout managers. The Qt::3Bo4Aayout class lines up widgets vertically. Qt::7Bo4Aayout lines up widgets hori3ontally. The Qt::2ridAayout class lays out widgets in a grid. The grid layout is the most fle+ible layout manager. The bo+ layouts can be nested into one another to create comple+ layouts.

Absolute positioning
In most cases$ programmers should use layout managers. There are a few situations$ where we can use absolute positioning. In absolute positioning$ the programmer specifies the position and the si3e of each widget in pi+els. The si3e and the position of a widget do not change$ if you resi3e a window. ,pplications look different on various platforms$ and what looks %! on 6inu+$ might not look %! on &ac. 7hanging fonts in your application might spoil the layout. If you translate your application into another language$ you must redo your layout. 0or all these issues$ use the absolute positioning only when you have a reason to do so.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . we lay out wid+ets usin+ absolute positionin+. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,(bsolute, init=ui resize 0$$. #?$ o/e 0$$. 0$$ end show

de! init=ui set"tyle"heet ,Q*id+et D bac9+round;color: #E%E%E% F, bardeGo/ 1 Qt::>i4 ap.new ,bardeGo/.Gp+, rotunda 1 Qt::>i4 ap.new ,rotunda.Gp+, incol 1 Qt::>i4 ap.new , incol.Gp+, barAabel 1 Qt::Aabel.new sel! barAabel.set>i4 ap bardeGo/ barAabel. o/e #$. #$ rotAabel 1 Qt::Aabel.new sel! rotAabel.set>i4 ap rotunda rotAabel. o/e E$. %H$ inAabel 1 Qt::Aabel.new sel! inAabel.set>i4 ap incol inAabel. o/e %I$. -$ end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In this e+ample$ we show three images using the absolute positioning.


barAabel 1 Qt::Aabel.new sel! barAabel.set>i4 ap bardeGo/

The Qt::Aabel widget is used to hold the image.


barAabel. o/e #$. #$

-e use the o/e method to position the label on the window at +9/:$ y9/:. -hen we resi3e the window$ the labels retain their initial si3e.

0igure1 ,bsolute positioning

Buttons example
In the following e+ample$ we will position two buttons in the bottom right corner of the window.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . we use bo4 layouts to position two buttons in the botto ri+ht corner o! the window. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,Buttons, init=ui resize 00$. %I$ o/e 0$$. 0$$ end show

de! init=ui /bo4 1 Qt::3Bo4Aayout.new sel!

<

hbo4 1 Qt::7Bo4Aayout.new o9 1 Qt::>ushButton.new ,CJ,. sel! apply 1 Qt::>ushButton.new ,(pply,. sel! hbo4.add*id+et o9. %. Qt::(li+nRi+ht hbo4.add*id+et apply /bo4.add"tretch % /bo4.addAayout hbo4 end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

-e use nested bo+ layouts to get our intended layout.


/bo4 1 Qt::3Bo4Aayout.new sel! hbo4 1 Qt::7Bo4Aayout.new

-e use one vertical and one hori3ontal bo+.


o9 1 Qt::>ushButton.new ,CJ,. sel! apply 1 Qt::>ushButton.new ,(pply,. sel!

These are the two buttons that will go into the bottom right corner of the window.
hbo4.add*id+et o9. %. Qt::(li+nRi+ht

-e put the ok button into the hori3ontal bo+. The second parameter is the stretch factor. It e+pands the area allotted to the ok button. It takes all available space left. The alignment of the windget inside this area is controlled by the third parameter. The Qt::(li+nRi+ht will align the button to the right.
/bo4.add"tretch %

This line creates a vertically e+panded white space$ which will push the hori3ontal bo+ with the buttons to the bottom.
/bo4.addAayout hbo4

The hori3ontal bo+ is nested into the vertical bo+.

0igure1 =uttons e+ample

Windows example
The following is a more complicated e+ample with nested bo+ layouts.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . use bo4 layouts to create a *indows e4a ple author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,*indows, init=ui resize 0-$. 0$$ o/e 0$$. 0$$ end show

de! init=ui /bo4 1 Qt::3Bo4Aayout.new sel! /bo4% 1 Qt::3Bo4Aayout.new hbo4% 1 Qt::7Bo4Aayout.new hbo4# 1 Qt::7Bo4Aayout.new windAabel 1 Qt::Aabel.new ,*indows,. sel! edit 1 Qt::Te4t8dit.new sel! edit.set8nabled !alse acti/ate 1 Qt::>ushButton.new ,(cti/ate,. sel!

':

close 1 Qt::>ushButton.new ,Close,. sel! help 1 Qt::>ushButton.new ,7elp,. sel! o9 1 Qt::>ushButton.new ,CJ,. sel! /bo4.add*id+et windAabel /bo4%.add*id+et /bo4%.add*id+et hbo4%.add*id+et hbo4%.addAayout acti/ate close. $. Qt::(li+nTop edit /bo4%

/bo4.addAayout hbo4% hbo4#.add*id+et help hbo4#.add"tretch % hbo4#.add*id+et o9 /bo4.addAayout hbo4#. % setAayout /bo4 end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In this layout$ we use two vertical and hori3ontal bo+es.


bo4 1 Qt::3Bo4Aayout.new sel!

This is the base layout of the e+ample.


windAabel 1 Qt::Aabel.new ,*indows,. sel!

0irst goes the label widget. It goes simply to the top of the vertical bo+.
/bo4%.add*id+et /bo4%.add*id+et hbo4%.add*id+et hbo4%.addAayout acti/ate close. $. Qt::(li+nTop edit /bo4%

/bo4.addAayout hbo4%

In the center part of the window we have a te+t edit widget and two vertically lined up buttons. The buttons go into a vertical bo+. The buttons are aligned to the top within this vertical bo+. The vertical bo+ and the te+t edit go into a hori3ontal bo+. This hori3ontal bo+ goes to the base vertical bo+$ *ust below the label widget.
hbo4#.add*id+et help hbo4#.add"tretch % hbo4#.add*id+et o9 /bo4.addAayout hbo4#. %

The help and the ok button go into another hori3ontal bo+. There is an e+panded white space between these two buttons. ,gain$ the hori3ontal bo+ goes to the base vertical bo+. ''

setAayout /bo4

The base vertical bo+ is set to be the main layout of the window.

0igure1 -indows e+ample

New Folder example


In the last e+ample$ we use the Qt::2ridAayout manager to create a >ew 0older layout e+ample.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . use the 2ridAayout to create a @ew Kolder e4a ple. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,@ew Kolder, init=ui resize 0$$. 0$$ o/e 0$$. 0$$

'/

end

show

de! init=ui +rid 1 Qt::2ridAayout.new sel! na eAabel 1 Qt::Aabel.new ,@a e,. sel! na e8dit 1 Qt::Aine8dit.new sel! te4t 1 Qt::Te4t8dit.new sel! o9Button 1 Qt::>ushButton.new ,CJ,. sel! closeButton 1 Qt::>ushButton.new ,Close,. sel! +rid.add*id+et na eAabel. $. $ +rid.add*id+et na e8dit. $. %. %. 0 +rid.add*id+et te4t. %. $. #. E +rid.setColu n"tretch %. % +rid.add*id+et o9Button. E. # +rid.add*id+et closeButton. E. 0 end end

app 1 Qt::(pplication.new:(R23< Qt(pp.new app.e4ec

In our e+ample$ we have one label$ one line edit$ one te+t edit and two buttons.
+rid 1 Qt::2ridAayout.new sel!

-e create an instance of the Qt::2ridAayout manager.


+rid.add*id+et na eAabel. $. $

-e place the label widget in the first cell of the grid. The cells count from :. The last two parameters are the row and column number.
+rid.add*id+et na e8dit. $. %. %. 0

The line edit widget is placed at the first row$ second column. The last two parameters are the row span and the column span. .ori3ontally$ the widget will span three columns.
+rid.setColu n"tretch %. %

The parameters of the method are the column number and the stretch factor. .ere we set stretch factor ' to the second column. This means$ that this column will take all remaining space. This was set$ because we wanted our buttons to retain their initial si3e.

'2

0igure1 >ew 0older e+ample In this part of the Ruby Qt tutorial$ we mentioned layout management of widgets.

Widgets
In this part of the Ruby Qt programming tutorial$ we will cover basic widgets. -idgets are basic building blocks of a GUI application. %ver the years$ several widgets became a standard in all toolkits on all % platforms. 0or e+ample a button$ a check bo+ or a scroll bar. Qt has a rich set of widgets which covers most of the programming needs. &ore speciali3ed widgets can be created as custom widgets.

Qt::CheckBox
The Qt::Chec9Bo4 is a widget$ that has two states. %n and %ff. The %n state is visuali3ed by a check mark. It is used to denote some boolean property. The Qt117heck=o+ widget provides a checkbo+ with a te+t label.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra uses Qt::Chec9Bo4 wid+et to show/hide the title o! the window. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt'

'5

class Qt(pp ) Qt::*id+et slots 'on=to++led:bool<' de! initialize super set*indowTitle ,Qt::Chec9Bo4, init=ui resize #-$. %-$ o/e 0$$. 0$$ end show

de! init=ui cb 1 Qt::Chec9Bo4.new ,"how Title,. sel! cb.setChec9ed true connect cb. "52@(A:,to++led:bool<,<. sel!. "ACT:,on=to++led:bool<,< cb. o/e -$. -$ end de! on=to++led state i! state set*indowTitle ,Qt::Chec9Bo4, else set*indowTitle ,, end end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In our e+ample$ we place a check bo+ on the window. The check bo+ shows?hides the title of the window.
set*indowTitle ,Qt::Chec9Bo4,

"uring the construction of the window$ we set a title for the window.
cb 1 Qt::Chec9Bo4.new ,"how Title,. sel!

The Qt::Chec9Bo4 widget is created. The first parameter of the constructor is its te+t label. The second parameter is the parent widget.
cb.setChec9ed true

The title is visible at the start of the application. o the check bo+ must be checked too.
connect cb. "52@(A:,to++led:bool<,<.

')

sel!. "ACT:,on=to++led:bool<,<

The to++led signal is emitted when the state of a check bo+ changes. -hen the signal is emitted$ we trigger the on=to++led method.
i! state set*indowTitle ,Qt::Chec9Bo4, else set*indowTitle ,, end

"epending on the state of the check bo+$ we show or hide the title of the window.

0igure1 Qt117heck=o+

Qt::Label
The Qt::Aabel widget is used to display te+t or image. >o user interaction is available.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra uses Qt::Aabel wid+et to show lyrics o! a son+. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,Lou 9now 5' init=ui resize #-$. %-$ o/e 0$$. 0$$ show no 2ood,

'8

end de! init=ui te4t 1 ,Meet you downstairs in the bar and heard your rolled up slee/es and your s9ull t;shirt Lou say why did you do it with hi todayN and sni!! e out li9e 5 was Tan&uerayOn cause you're y !ella. y +uy hand e your stella and !ly by the ti e 5' out the door you tear en down li9e Ro+er MooreOn 5 cheated ysel! li9e 5 9new 5 would 5 told ya. 5 was trouble you 9now that 5' no +ood, label 1 Qt::Aabel.new te4t. sel! label.setKont Qt::Kont.new ,>urisa,. P /bo4 1 Qt::3Bo4Aayout.new /bo4.add*id+et label setAayout /bo4 end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

%ur e+ample shows lyrics of a song in the window.


te4t 1 ,Meet you downstairs in the bar and heard your rolled up slee/es and your s9ull t;shirt ...

-e define a multi line te+t.


label 1 Qt::Aabel.new te4t. sel! label.setKont Qt::Kont.new ,>urisa,. P

-e create the label widget and change its font.


/bo4 1 Qt::3Bo4Aayout.new /bo4.add*id+et label setAayout /bo4

Instead of manually coding the position and si3e of the label$ we put the label into a bo+ layout.

';

0igure1 Qt116abel

Qt::Line dit
The Qt::Aine8dit is a widget that allows to enter and edit a single line of plain te+t. There are undo?redo$ cut?paste and drag @ drop functions available for a Qt::Aine8dit widget.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra shows te4t which is entered in a Qt::Aine8dit wid+et in a Qt::Aabel wid+et. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'on=chan+ed:Q"trin+<' de! initialize super set*indowTitle ,Aine8dit, init=ui resize #-$. %-$ o/e 0$$. 0$$ show

'<

end de! init=ui Qlabel 1 Qt::Aabel.new sel! edit 1 Qt::Aine8dit.new sel! connect edit. "52@(A:,te4tChan+ed:Q"trin+<,<. sel!. "ACT:,on=chan+ed:Q"trin+<,< edit. o/e H$. %$$ Qlabel. o/e H$. E$ end de! on=chan+ed te4t Qlabel.setTe4t te4t Qlabel.adGust"ize end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In our e+ample we show two widgets. , line edit and a label widget. The te+t entered into the line edit is shown in the label widget.
edit 1 Qt::Aine8dit.new sel!

The Qt::Aine8dit widget is created.


connect edit. "52@(A:,te4tChan+ed:Q"trin+<,<. sel!. "ACT:,on=chan+ed:Q"trin+<,<

-hen we type or delete some te+t from the line edit$ the on=chan+ed method is triggered.
de! on=chan+ed te4t Qlabel.setTe4t te4t Qlabel.adGust"ize end

In the on=chan+ed method$ we set the contents of the line edit to the label widget. The adGust"ize method ensures that all te+t is visible.

'(

0igure1 Qt116ine#dit widget

Toggle buttons
Toggle buttons are push buttons with a checkable flag set. Toggle button is a button that has two states. Aressed and not pressed. Bou toggle between these two states by clicking on it. There are situations where this functionality fits well.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra uses to++le buttons to chan+e the bac9+round colour o! a wid+et. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'on=clic9ed:<' de! initialize super set*indowTitle ,To++le button, init=ui resize 0$$. %?$ o/e 0$$. 0$$ show end de! init=ui Qcolor 1 Qt::Color.new $. $. $ set2eo etry 0$$. 0$$. #?$. %I$ set*indowTitle ,To++leButton, Qredb 1 Qt::>ushButton.new 'Red'. sel! Qredb.setChec9able true Qredb. o/e %$. %$ connect Qredb. "52@(A:,clic9ed:<,<. "ACT:,on=clic9ed:<,< Q+reenb 1 Qt::>ushButton.new '2reen'. sel! Q+reenb.setChec9able true Q+reenb. o/e %$. H$ connect Q+reenb. "52@(A:'clic9ed:<'<. "ACT:,on=clic9ed:<,<

/:

Qblueb 1 Qt::>ushButton.new ,Blue,. sel! Qblueb.setChec9able true Qblueb. o/e %$. %%$ connect Qblueb. "52@(A:,clic9ed:<,<. "ACT:,on=clic9ed:<,< Qs&uare 1 Qt::*id+et.new sel! Qs&uare.set2eo etry %-$. #$. %$$. %$$ Qs&uare.set"tyle"heet ,Q*id+et D bac9+round;color: Rs F, R Qcolor.na e end de! on=clic9ed red 1 Qcolor.red +reen 1 Qcolor.+reen blue 1 Qcolor.blue i! Qredb.isChec9ed red 1 #-else red 1 $ end i! Q+reenb.isChec9ed +reen 1 #-else +reen 1 $ end i! Qblueb.isChec9ed blue 1 #-else blue 1 $ end Qcolor 1 Qt::Color.new red. +reen. blue Qs&uare.set"tyle"heet:,Q*id+et D bac9+round;color: Rs F, R Qcolor.na e< end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In the code e+ample$ we use three toggle buttons to change the colour of a rectangular widget.
Qredb 1 Qt::>ushButton.new 'Red'. sel! Qredb.setChec9able true

-e create a Qt::>ushButton widget. The setChec9able method changes the push button into a toggle button.
connect Qredb. "52@(A:,clic9ed:<,<. "ACT:,on=clic9ed:<,<

-e plug the button into the on=clic9ed method call.

/'

Qs&uare 1 Qt::*id+et.new sel! Qs&uare.set2eo etry %-$. #$. %$$. %$$ Qs&uare.set"tyle"heet ,Q*id+et D bac9+round;color: Rs F, R Qcolor.na e

-e create a s4uare widget. -e set its si3e. ,t the beginning$ it is black. In Qt$ we use style sheets to customi3e the appearance of a widget. Inside the on=clic9ed method$ we determine the colour value and update the s4uare widget to a new colour.
red 1 Qcolor.red +reen 1 Qcolor.+reen blue 1 Qcolor.blue

.ere we determine the current colour of the s4uare widget.


i! Qredb.isChec9ed red 1 #-else red 1 $ end

The red part of the colour is changed$ depending on the state of the red toggle button.
Qcolor 1 Qt::Color.new red. +reen. blue

-e create a new colour value.


Qs&uare.set"tyle"heet:,Q*id+et D bac9+round;color: Rs F, R Qcolor.na e<

The colour of the s4uare is updated.

0igure1 Toggle buttons

Qt::ComboBox
The Qt::Co boBo4 is a widget that allows the user to choose from a list of options. It is a selection widget that displays the current item$ and can pop up a list of selectable items. , combo bo+ may be editable. It presents a list of options to the user in a way that takes up the minimum amount of screen space.

//

#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra uses the Qt::Co boBo4 wid+et. The option selected !ro the co bo bo4 is displayed in the label wid+et. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epet ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'on=acti/ated:Q"trin+<' de! initialize super set*indowTitle ,Qt::Co boBo4, init=ui resize #-$. %-$ o/e 0$$. 0$$ show end de! init=ui Qlabel 1 Qt::Aabel.new ,Sbuntu,. sel! co bo 1 Qt::Co boBo4.new sel! co co co co co bo.add5te bo.add5te bo.add5te bo.add5te bo.add5te ,Sbuntu, ,Kedora, ,Mandri/a, ,Red 7at, ,Mint,

connect co bo. "52@(A:,acti/ated:Q"trin+<,<. sel!. "ACT:,on=acti/ated:Q"trin+<,< co bo. o/e -$. 0$ Qlabel. o/e -$. %$$ end de! on=acti/ated te4t Qlabel.setTe4t te4t Qlabel.adGust"ize end end app 1 Qt::(pplication.new (R23 Qt(pp.new

/2

app.e4ec

In our code e+ample$ we have two widgets. , combo bo+ and a label widget. The option selected from a combo bo+ is shown in the label.
Qlabel 1 Qt::Aabel.new ,Sbuntu,. sel!

This is the label$ that will show the currently selected option from the combo bo+.
co bo 1 Qt::Co boBo4.new sel!

-e create the instance of the Qt::Co boBo4 widget.


co co co co co bo.add5te bo.add5te bo.add5te bo.add5te bo.add5te ,Sbuntu, ,Kedora, ,Mandri/a, ,Red 7at, ,Mint,

7ombo bo+ is filled with values.


connect co bo. "52@(A:,acti/ated:Q"trin+<,<. sel!. "ACT:,on=acti/ated:Q"trin+<,<

-hen we select an option from the combo bo+$ the on=acti/ated method is triggered.
de! on=acti/ated te4t Qlabel.setTe4t te4t Qlabel.adGust"ize end

In the on=acti/ated method$ we update the label widget to the currently selected string from the combo bo+.

0igure1 Qt117ombo=o+ widget In this part of the Ruby Qt tutorial$ we have presented several Qt widgets.

Menus & toolbars


In this part of the Ruby Qt programming tutorial$ we will work with menus and toolbar.

/5

, menubar is one of the most visible parts of the GUI application. It is a group of commands located in various menus. -hile in console applications you had to remember all those arcane commands$ here we have most of the commands grouped into logical parts. There are accepted standards that further reduce the amount of time spending to learn a new application. &enus group commands that we can use in an application. Toolbars provide a 4uick access to the most fre4uently used commands.

!imple menu
The first e+ample will show a simple menu.
#!/usr/bin/ruby # # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra shows a si ple enu. 5t has one action. which will ter inate the pro+ra . when selected. author: Jan Bodnar website: www.zetcode.co last odi!ied: @o/e ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::Main*indow de! initialize super set*indowTitle ,"i ple init=ui resize #-$. %-$ o/e 0$$. 0$$ end show enu,

de! init=ui &uit 1 Qt::(ction.new ,TQuit,. sel! !ile 1 enuBar:<.addMenu ,TKile, !ile.add(ction &uit connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<<

end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

/)

-e have a menubar$ a menu and an action. In order to work with menus$ we must inherit from Main*indow widget.
&uit 1 Qt::(ction.new ,TQuit,. sel!

This code line creates a (ction. #ach Menu has one or more action ob*ects. >ote the ampersand C@D character. It creates a shortcut for the item. ,lt E Q. It also underlines the Q character. The shortcut is active$ when the file menu is dropped down.
!ile 1 enuBar:<.addMenu ,TKile, !ile.add(ction &uit

-e create a Menu ob*ect. The ampersand character creates a shortcut. ,lt E 0. The consecutive shortcuts ,lt E 0$ ,lt E Q 4uit the application.
connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<<

-hen we select this option from the menu$ the application 4uits.

0igure1 imple menu

!ubmenu
, submenu is a menu plugged into another menu ob*ect. The ne+t e+ample demonstrates this.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra sub enu creates a

author: Jan Bodnar website: www.zetcode.co last odi!ied: @o/e ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::Main*indow de! initialize super

/8

set*indowTitle ,"ub enu, init=ui resize #?$. #$$ o/e 0$$. 0$$ show end de! init=ui &uit 1 Qt::(ction.new ,TQuit,. sel! !ile 1 enuBar:<.addMenu ,TKile, i p 1 Qt::Menu.new ,5 port, seeds 1 Qt::(ction.new ,5 port news !eed...,. sel! ar9s 1 Qt::(ction.new ,5 port boo9 ar9s...,. sel! ail 1 Qt::(ction.new ,5 port ail...,. sel! i p .add(ction seeds i p .add(ction ar9s i p .add(ction ail !ile.addMenu i p !ile.add(ction &uit connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<<

end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In the e+ample$ we have three options in a submenu of a file menu.


!ile 1 enuBar:<.addMenu ,TKile, i p 1 Qt::Menu.new ,5 port,

-e have two Menu ob*ects. The file menu and the import menu.
seeds 1 Qt::(ction.new ,5 port news !eed...,. sel! ar9s 1 Qt::(ction.new ,5 port boo9 ar9s...,. sel! ail 1 Qt::(ction.new ,5 port ail...,. sel!

-e create three action ob*ects.


i p .add(ction seeds i p .add(ction ar9s i p .add(ction ail

-e add the action ob*ects into the import menu.


!ile.addMenu i p

/;

0inally$ we add the import menu into the file menu.

0igure1 ubmenu

"mages# menus# separators


In the following e+ample$ we will further enhance our previous application. -e will add icons to the menus$ use shortcuts and a separator. >ote that the Gnome desktop might be configured not to display menu icons by default. In such a case we need to enable the enu=ha/e=icons option in the Gnome interface configuration.
+con!tool;# ;;type Boolean ;;set /des9top/+no e/inter!ace/ enus=ha/e=icons True

-e can use the above command or the gconf-editor tool.


#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra shows i a+e enus. shortcuts and a separator author: Jan Bodnar website: www.zetcode.co last odi!ied: @o/e ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::Main*indow de! initialize super set*indowTitle ,5 a+e init=ui resize #?$. #$$ o/e 0$$. 0$$ show enu,

/<

end de! init=ui newpi4 1 Qt::5con.new ,new.pn+, openpi4 1 Qt::5con.new ,open.pn+, &uitpi4 1 Qt::5con.new ,e4it.pn+, newa 1 Qt::(ction.new newpi4. ,T@ew,. sel! open 1 Qt::(ction.new openpi4. ,TCpen,. sel! &uit 1 Qt::(ction.new &uitpi4. ,TQuit,. sel! &uit.set"hortcut ,CtrlUQ, !ile 1 enuBar:<.addMenu ,TKile, !ile.add(ction newa !ile.add(ction open !ile.add"eparator !ile.add(ction &uit connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<< end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In our e+ample$ we have one menu with three actions. %nly the 4uit action will actually do something$ if we select it. -e also create a separator and a 7trl E Q shortcut$ which will terminate the application.
newpi4 1 Qt::5con.new ,new.pn+, openpi4 1 Qt::5con.new ,open.pn+, &uitpi4 1 Qt::5con.new ,e4it.pn+,

These are png images$ that we will use in the application.


newa 1 Qt::(ction.new newpi4. ,T@ew,. sel! open 1 Qt::(ction.new openpi4. ,TCpen,. sel! &uit 1 Qt::(ction.new &uitpi4. ,TQuit,. sel!

.ere we create three action ob*ects. The first parameter is the 5con.
&uit.set"hortcut ,CtrlUQ,

This line creates a shortcut. =y pressing this shortcut$ we will run the 4uit action$ which will 4uit the application.
!ile.add"eparator

-e create a separator. The separator is a hori3ontal line$ which enables us to group menu actions into some logical parts.

/(

0igure1 Images$ shortcut and a separator

A toolbar
The ToolBar class provides a movable panel that contains a set of controls$ which provide a 4uick access to the application actions.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra toolbar creates a

author: Jan Bodnar website: www.zetcode.co last odi!ied: @o/e ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::Main*indow de! initialize super set*indowTitle ,Toolbar, init=ui resize #-$. %-$ o/e 0$$. 0$$ end show

de! init=ui newpi 1 Qt::5con.new ,new#.pn+, openpi 1 Qt::5con.new ,open#.pn+, &uitpi 1 Qt::5con.new ,e4it#.pn+, toolbar 1 addToolBar , ain toolbar, toolbar.add(ction newpi. ,@ew Kile, toolbar.add(ction openpi. ,Cpen Kile,

2:

toolbar.add"eparator &uit 1 toolbar.add(ction &uitpi. ,Quit (pplication, connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<<

end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

-e create a toolbar with three action ob*ects and one separator.


newpi 1 Qt::5con.new ,new#.pn+, openpi 1 Qt::5con.new ,open#.pn+, &uitpi 1 Qt::5con.new ,e4it#.pn+,

Toolbar action ob*ects will display these icons.


toolbar 1 addToolBar , ain toolbar,

The addToolBar method of the Main*indow creates a toolbar for the application. The te+t string gives a toolbar a name. This name is used to reference this toolbar$ because there can be multiple toolbars in one application. If we right click on the window area$ we can see a checkable option$ which shows?hides the toolbar.
toolbar.add"eparator

-e create a vertical separator.


connect:&uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<<

-hen we click on the 4uit action ob*ect$ the application terminates.

0igure1 Toolbar

$ndo redo
The following e+ample demonstrates$ how we can deactivate toolbar buttons on the toolbar. It is a common practice in GUI programming. 0or e+ample the save button. If we save all

2'

changes of our document to the disk$ the save button is deactivated in most te+t editors. This way the application indicates to the user$ that all changes are already saved.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra disables/enables actions on a toolbar author: Jan Bodnar website: www.zetcode.co last odi!ied: @o/e ber #$%#

re&uire 'Qt' class Qt(pp ) Qt::Main*indow slots 'count:<' de! initialize super set*indowTitle ,Toolbar, init=ui resize #-$. %-$ o/e 0$$. 0$$ end show

de! init=ui Qcount 1 # undoi 1 Qt::5con.new ,undo.pn+, redoi 1 Qt::5con.new ,redo.pn+, &uitpi 1 Qt::5con.new ,&uit.pn+, toolbar 1 addToolBar ,!irst toolbar, Qund 1 toolbar.add(ction undoi. ,Sndo, Qred 1 toolbar.add(ction redoi. ,Redo, connect Qund. "52@(A:,tri++ered:<,<. sel!. "ACT:,count:<,< connect Qred. "52@(A:,tri++ered:<,<. sel!. "ACT:,count:<,< toolbar.add"eparator &uit 1 toolbar.add(ction &uitpi. ,Quit (pplication, connect &uit. "52@(A:,tri++ered:<,<. Qt::(pplication.instance. "ACT:,&uit:<,<

end

de! count

2/

action 1 sender i! ,Sndo, 11 action.te4t Qcount 1 Qcount ; % else Qcount 1 Qcount U % end i! Qcount )1 $ Qund.set6isabled true Qred.set6isabled !alse end i! Qcount V1 Qund.set6isabled !alse Qred.set6isabled true end end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In our e+ample$ we have three (ction ob*ects and a separator. ,fter several clicks on the undo or redo buttons$ they become deactivated. Fisually$ the buttons are grayed out.
Qcount 1 #

The Qcount variable determines$ which button is activated and deactivated.


connect Qund. "52@(A:,tri++ered:<,<. sel!. "ACT:,count:<,< connect Qred. "52@(A:,tri++ered:<,<. sel!. "ACT:,count:<,<

7licking on the toolbar button$ the tri++ered signal is emitted. -e connect this signal to the count method.
action 1 sender

=oth toolbar buttons call the count method. -e need to tell between them. This line determines$ which action ob*ect actually emitted the signal.
i! ,Sndo, 11 action.te4t Qcount 1 Qcount ; % else Qcount 1 Qcount U % end

The undo toolbar button subtracts ' from the count variable. The redo adds '. "epending on the value of the count variable$ we enable?disable the toolbar buttons.
i! Qcount )1 $ Qund.set6isabled true Qred.set6isabled !alse end

22

The set6isabled method activates or deactivates the toolbar buttons.

0igure1 Undo redo In this part of the Ruby Qt tutorial$ we mentioned the menus and toolbars.

Dialogs
In this part of the Ruby Qt programming tutorial$ we will work with dialogs. "ialog windows or dialogs are an indispensable part of most modern GUI applications. , dialog is defined as a conversation between two or more persons. In a computer application a dialog is a window which is used to GtalkG to the application. , dialog is used to input data$ modify data$ change the application settings etc. "ialogs are important means of communication between a user and a computer program.

%essage boxes
&essage bo+es are convenient dialogs that provide messages to the user of the application. The message consists of te+t and image data.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra de onstrates Messa+eBo4 dialo+s author: Gan bodnar website: www.zetcode.co last odi!ied: July #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'show6ialo+:<' de! initialize super set*indowTitle ,Messa+e dialo+s,

25

init=ui resize #-$. %-$ o/e 0$$. 0$$ end show

de! init=ui +rid 1 Qt::2ridAayout.new sel! +rid.set"pacin+ # error 1 Qt::>ushButton.new ,8rror,. sel! warnin+ 1 Qt::>ushButton.new ,*arnin+,. sel! &uestion 1 Qt::>ushButton.new ,Question,. sel! in!or ation 1 Qt::>ushButton.new ,5n!or ation,. sel! about 1 Qt::>ushButton.new ,(bout,. sel! +rid.add*id+et +rid.add*id+et +rid.add*id+et +rid.add*id+et +rid.add*id+et error. $. $ warnin+. $. % &uestion. %. $ in!or ation. %. % about. #. $

connect:error. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< connect:warnin+. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< connect:&uestion. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< connect:in!or ation. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< connect:about. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< end de! show6ialo+ button 1 sender i! ,8rror, 11 button.te4t Qt::Messa+eBo4.critical sel!. ,8rror,. ,8rror loadin+ !ile!, elsi! ,*arnin+, 11 button.te4t Qt::Messa+eBo4.warnin+ sel!. ,*arnin+,. ,Cperation not per itted!, elsi! ,Question, 11 button.te4t Qt::Messa+eBo4.&uestion sel!. ,Question,. ,(re you sure to &uitN, elsi! ,5n!or ation, 11 button.te4t Qt::Messa+eBo4.in!or ation sel!. ,5n!or ation,. ,6ownload co pleted., elsi! ,(bout, 11 button.te4t Qt::Messa+eBo4.about sel!. ,(bout,. ,ZetCode Ruby Qt tutorial., end

2)

end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

-e use the 2ridAayout manager to set up a grid of five buttons. #ach of the buttons shows a different message bo+.
i! ,8rror, 11 button.te4t Qt::Messa+eBo4.critical sel!. ,8rror,. ,8rror loadin+ !ile!,

In case we pressed the error button$ we show the error dialog. -e use static methods of the Messa+eBo4 class to show the message bo+es.

0igure1 Info dialog

"nput&ialog
The 5nput6ialo+ class provides a simple convenience dialog to get a single value from the user. The input value can be a string$ a number or an item from a list. , label must be set to tell the user what they should enter.
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra dialo+ shows an input

author: Gan bodnar website: www.zetcode.co last odi!ied: July #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'show6ialo+:<' de! initialize super set*indowTitle ,5nput dialo+, init=ui

28

resize E$$. ?$ o/e 0$$. 0$$ show end de! init=ui show 1 Qt::>ushButton.new ,6ialo+,. sel! connect:show. "52@(A:,clic9ed:<,<. sel!. "ACT:,show6ialo+:<,<< show. o/e #$. #$ Qedit 1 Qt::Aine8dit.new sel! Qedit. o/e %0$. ## end de! show6ialo+ te4t 1 Qt::5nput6ialo+.+etTe4t sel!. ,5nput 6ialo+,. ,8nter your na e, i! te4t !1 nil na e 1 te4t.strip i! not na e.e ptyN Qedit.setTe4t na e end end end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In the code e+ample$ we have a button and a line edit. The button shows an input dialog. -e get some te+t and the te+t is shown in the line edit widget.
te4t 1 Qt::5nput6ialo+.+etTe4t sel!. ,5nput 6ialo+,. ,8nter your na e,

The +etTe4t static method creates the input dialog. The te+t from the dialog is stored in the te+t variable.
i! te4t !1 nil na e 1 te4t.strip i! not na e.e ptyN Qedit.setTe4t na e end end

=efore we update the line edit$ we ensure$ that the te+t variable is not null and that it is not empty and does not consists only from spaces.

2;

0igure1 Input dialog

Color&ialog
The Color6ialo+ class provides a dialog widget for specifying colors. The color dialogHs function is to allow users to choose colors.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . we use the Color6ialo+ to chan+e the color o! a label te4t author: Gan bodnar website: www.zetcode.co last odi!ied: July #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'show6ialo+:<' de! initialize super set*indowTitle ,Color dialo+, init=ui resize E$$. 0$$ o/e 0$$. 0$$ end show

de! init=ui Qlabel 1 Qt::Aabel.new ,ZetCode Ruby Qt tutorial,. sel! /bo4 1 Qt::3Bo4Aayout.new sel! Qlabel.set(li+n ent Qt::(li+nCenter /bo4.add*id+et Qlabel end de! ouse>ress8/ent e/ent

2<

color 1 Qt::Color6ialo+.+etColor i! not color.is3alid return end Qlabel.set"tyle"heet ,Q*id+et D color: Rs F, R color.na e end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

-e show a some te+t in the center of the window. =y clicking on the area of the window$ we show a color dialog. -e change the te+t foreground color to the selected color from the dialog.
de! end ouse>ress8/ent e/ent ...

In order to receive mouse press events for our window$ we must reimplement the ouse>ress8/ent method.
color 1 Qt::Color6ialo+.+etColor

The Color6ialo+ is being created. The selected color is stored in the color variable.
Qlabel.set"tyle"heet ,Q*id+et D color: Rs F, R color.na e

.ere we update the foreground color of the labelHs te+t.

0igure1 7olor"ialog

2(

Font&ialog
The Kont6ialo+ class provides a dialog widget for selecting a font.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . we use the Kont6ialo+ to chan+e the !ont o! a label te4t author: Gan bodnar website: www.zetcode.co last odi!ied: July #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et slots 'show6ialo+:<' de! initialize super set*indowTitle ,Kont dialo+, init=ui resize E$$. 0$$ o/e 0$$. 0$$ show end de! init=ui Qlabel 1 Qt::Aabel.new ,ZetCode Ruby Qt tutorial,. sel! /bo4 1 Qt::3Bo4Aayout.new sel! Qlabel.set(li+n ent Qt::(li+nCenter /bo4.add*id+et Qlabel end de! ouse>ress8/ent e/ent o9 1 Qt::Boolean.new !ont 1 Qt::Kont6ialo+.+etKont o9 i! not o9 return end Qlabel.setKont !ont end end

app 1 Qt::(pplication.new (R23

5:

Qt(pp.new app.e4ec

This e+ample is similar to the previous one. This time$ we change the font of the te+t.
!ont 1 Qt::Kont6ialo+.+etKont o9

The Kont6ialo+ is being created.


i! not o9 return end

The boolean ok variable is true$ if we clicked on the %! button of the dialog. -e return from the method$ if the cancel button was pressed.
Qlabel.setKont !ont

-e update the label to the newly selected font.

0igure1 0ont"ialog In this part of the Ruby Qt tutorial$ we worked with dialog windows.

Painting
In this part of the Ruby Qt programming tutorial we will do some painting. -hen do we need to paintI There are situations$ when we need to create a widget from scratch. In such a case$ we need to do painting. %r we want to create charts$ special ornaments$ effects or widget enhancements. The >ainter class is instrumental when we do some painting in the Qt library. Aaint events are received in the paint8/ent method. To do custom painting$ we must reimplement this method.

5'

'atterns
In Qt$ there are various patterns$ that we can use to fill the interiors of shapes.
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra draws nine rectan+les. The interiors are !illed with di!!erent built;in patterns. author: Gan bodnar website: www.zetcode.co last odi!ied: June #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,>atterns, resize 0-$. #?$ o/e 0$$. 0$$ end show

de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw>atterns painter painter.end end de! draw>atterns painter painter.set>en Qt::@o>en painter.setBrush Qt::7or>attern painter.drawRect %$. %-. P$. H$ painter.setBrush Qt::3er>attern painter.drawRect %0$. %-. P$. H$ painter.setBrush Qt::Cross>attern painter.drawRect #-$. %-. P$. H$ painter.setBrush Qt::6enseI>attern painter.drawRect %$. %$-. P$. H$ painter.setBrush Qt::6enseH>attern painter.drawRect %0$. %$-. P$. H$

5/

painter.setBrush Qt::6ense->attern painter.drawRect #-$. %$-. P$. H$ painter.setBrush Qt::B6ia+>attern painter.drawRect %$. %P-. P$. H$ painter.setBrush Qt::K6ia+>attern painter.drawRect %0$. %P-. P$. H$ painter.setBrush Qt::6ia+Cross>attern painter.drawRect #-$. %P-. P$. H$

end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In the code e+ample$ we will draw nine rectangles and fill them with different brush patterns.
de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw>atterns painter painter.end

end

-hen the window area needs to be redrawn$ the paint8/ent method is called. This happens$ when we resi3e the window$ ma+imi3e it or minimi3e it etc. Inside this method$ we create the >ainter ob*ect. This ob*ect is used to do all painting in Qt. The painting itself is delegated to the draw>atterns method.
painter.set>en Qt::@o>en

The pen ob*ect is used to draw outlines of the shapes. In our e+ample we will not use a pen.
painter.setBrush Qt::7or>attern

-e set a hori3ontal pattern as a brush.


painter.drawRect %$. %-. P$. H$

-e draw a rectangle$ with the current pen and brush. The first two parameters of the method are the +$ y coordinates. The last two parameters are the width and height of the rectangle.
painter.end

#nds painting. ,ny resources used while painting are released.

52

0igure1 Aatterns

!hapes
The Qt painting ,AI can draw various shapes. The following programming code e+ample will show some of them.
#!/usr/bin/ruby # # # # # # # ZetCode Ruby Qt tutorial This pro+ra draws basic shapes

author: Gan bodnar website: www.zetcode.co last odi!ied: June #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,Basic shapes, resize 0-$. #?$ o/e 0$$. 0$$ end show

de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw"hapes painter painter.end

55

end de! draw"hapes painter painter.setRender7int Qt::>ainter::(ntialiasin+ painter.set>en Qt::Color.new %-$. %-$. %-$ painter.setBrush Qt::Brush.new Qt::Color.new %-$. %-$. %-$ path% 1 Qt::>ainter>ath.new path%. o/eTo -. path%.cubicTo E$. -. -$. -$. path%.cubicTo -. PP. -$. -$. painter.draw>ath path% PP. PP -. -

painter.draw>ie %0$. #$. P$. H$. 0$W%H. %#$W%H painter.drawChord #E$. 0$. P$. H$. $. %HW%?$ painter.drawRoundRect #$. %#$. ?$. -$ points 1 XY points.push points.push points.push points.push points.push Qt::>oint.new Qt::>oint.new Qt::>oint.new Qt::>oint.new Qt::>oint.new %0$. %?$. %?$. ##$. %E$. %E$ %I$ %E$ %%$ %$$

poly+on 1 Qt::>oly+on.new points painter.draw>oly+on poly+on painter.drawRect #-$. %%$. H$. H$ baseline 1 Qt::>ointK.new #$. #-$ !ont 1 Qt::Kont.new ,2eor+ia,. -path# 1 Qt::>ainter>ath.new path#.addTe4t baseline. !ont. ,Q, painter.draw>ath path# painter.draw8llipse %E$. #$$. H$. H$ painter.draw8llipse #E$. #$$. P$. H$ end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In this code e+ample$ we draw nine different shapes on the window. , comple+ path$ a pie$ a chord$ a rounded rectangle$ a polygon$ a rectangle$ a character based shape$ a circle and an ellipse.
painter.setRender7int Qt::>ainter::(ntialiasin+

-e use antialiasing in the e+ample. ,ntialiased shapes look better$ but it takes more time to draw them.
painter.set>en Qt::Color.new %-$. %-$. %-$ painter.setBrush Qt::Brush.new Qt::Color.new %-$. %-$. %-$

5)

-e use a dark gray pen and brush to draw the shapes.


path% 1 Qt::>ainter>ath.new path%. o/eTo -. path%.cubicTo E$. -. -$. -$. path%.cubicTo -. PP. -$. -$. painter.draw>ath path% PP. PP -. -

The first comple+ shape is created with the >ainter>ath ob*ect. The AainterAath class provides a container for painting operations. , painter path is an ob*ect composed of a number of graphical building blocks$ such as rectangles$ ellipses$ lines$ and curves.
painter.draw>ie %0$. #$. P$. H$. 0$W%H. %#$W%H painter.drawChord #E$. 0$. P$. H$. $. %HW%?$ painter.drawRoundRect #$. %#$. ?$. -$

These three lines draw a pie$ a chord and a rounded rectangle.


points 1 XY points.push points.push points.push points.push points.push Qt::>oint.new Qt::>oint.new Qt::>oint.new Qt::>oint.new Qt::>oint.new %0$. %?$. %?$. ##$. %E$. %E$ %I$ %E$ %%$ %$$

poly+on 1 Qt::>oly+on.new points painter.draw>oly+on poly+on

-e use an array of five points to create a polygon.


baseline 1 Qt::>ointK.new #$. #-$ !ont 1 Qt::Kont.new ,2eor+ia,. -path# 1 Qt::>ainter>ath.new path#.addTe4t baseline. !ont. ,Q, painter.draw>ath path#

These lines create a character based shape.


painter.draw8llipse %E$. #$$. H$. H$ painter.draw8llipse #E$. #$$. P$. H$

These two lines create a circle and an ellipse respectively.

58

0igure1 hapes

Transparent rectangles
Transparency is the 4uality of being able to see through a material. The easiest way to understand transparency is to imagine a piece of glass or water. Technically$ the rays of light can go through the glass and this way we can see ob*ects behind the glass. In computer graphics$ we can achieve transparency effects using alpha compositing. ,lpha compositing is the process of combining an image with a background to create the appearance of partial transparency. The composition process uses an alpha channel. Cwikipedia.org$ answers.comD
#!/usr/bin/ruby # # # # # # # # # ZetCode Ruby Qt tutorial This pro+ra draws ten rectan+les with di!!erent le/els o! transparency. author: Gan bodnar website: www.zetcode.co last odi!ied: June #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,Transparent rectan+les, resize -P$. P$ o/e 0$$. 0$$ show

5;

end de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! drawRectan+les painter painter.end

end

de! drawRectan+les painter painter.set>en Qt::@o>en !or i in %..%$ painter.setBrush Qt::Brush.new Qt::Color.new $. $. #--. iW#painter.drawRect -$Wi. #$. E$. E$ end end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In the e+ample we will draw ten rectangles with different levels of transparency.
painter.set>en Qt::@o>en

-e use no pen.
!or i in %..%$ painter.setBrush Qt::Brush.new Qt::Color.new $. $. #--. iW#painter.drawRect -$Wi. #$. E$. E$ end

The last parameter of the 7olor ob*ect is the alpha transparency value.

0igure1 Transparent rectangles

&onut !hape
In the following e+ample we create a comple+ shape by rotating a bunch of ellipses.
#!/usr/bin/ruby # ZetCode Ruby Qt tutorial

5<

# # # # # # #

This pro+ra shape

draws a donut

author: Gan bodnar website: www.zetcode.co last odi!ied: June #$$P

re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,6onut, resize 0-$. #?$ o/e 0$$. 0$$ end show

de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw6onut painter painter.end end de! draw6onut painter painter.setRender7int Qt::>ainter::(ntialiasin+ color 1 Qt::Color.new color.set@a edColor ,#000000, pen 1 Qt::>en.new color pen.set*idth % painter.set>en pen w 1 width h 1 hei+ht painter.translate Qt::>oint.new w/#. h/# I#.ti es do painter.draw8llipse ;%#-. ;E$. #-$. ?$ painter.rotate -.$ end

end end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In this e+ample$ we create a donut. The shape resembles a cookie$ hence the name donut. 5(

color 1 Qt::Color.new color.set@a edColor ,#000000,

-e can use a he+adecimal notation to create a color ob*ect.


w 1 width h 1 hei+ht

.ere we determine the width and height of the window.


painter.translate Qt::>oint.new w/#. h/#

-e move the coordinate system to the middle of the window. This way we make the drawing mathematically easier.
I#.ti es do painter.draw8llipse ;%#-. ;E$. #-$. ?$ painter.rotate -.$ end

-e draw an ellipse ob*ect ;/ times. #ach time$ we rotate the ellipse by ) degrees. This will create our donut shape.

0igure1 "onut

&rawing text
In the last e+ample$ we are going to draw te+t on the window.
#!/usr/bin/ruby # ZetCode Ruby Qt tutorial # # This pro+ra draws te4t # on the window #

):

# author: Gan bodnar # website: www.zetcode.co # last odi!ied: June #$$P re&uire 'Qt' class Qt(pp ) Qt::*id+et de! initialize super set*indowTitle ,"oul ate, resize 0I$. #E$ o/e 0$$. 0$$ end show

de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! drawTe4t painter painter.end end de! drawTe4t painter painter.setBrush Qt::Brush.new Qt::Color.new #-. #-. #painter.setKont Qt::Kont.new ,>urisa,. %$ painter.drawTe4t Qt::>oint.new:#$. 0$<. ,Most relationships see so transitory, painter.drawTe4t Qt::>oint.new:#$. H$<. ,They're +ood but not the per anent one, painter.drawTe4t Qt::>oint.new:#$. %#$<. ,*ho doesn't lon+ !or so eone to hold, painter.drawTe4t Qt::>oint.new:#$. %-$<. ,*ho 9nows how to lo/e without bein+ told, painter.drawTe4t Qt::>oint.new:#$. %?$<. ,"o ebody tell e why 5' on y own, painter.drawTe4t Qt::>oint.new:#$. #%$<. ,5! there's a soul ate !or e/eryone, end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

-e draw a song lyrics on the window.


painter.setKont Qt::Kont.new ,>urisa,. %$

-e set a Aurisa font for our te+t.

)'

painter.drawTe4t Qt::>oint.new:#$. 0$<. ,Most relationships see so transitory,

The drawTe4t method is used to draw the te+t.

0igure1 "rawing te+t In this part of the Ruby Qt programming tutorial$ we did some painting.

Custom widget
In this part of the Ruby Qt programming tutorial$ we will create a custom widget. Toolkits usually provide only the most common widgets like buttons$ te+t widgets$ sliders etc. >o toolkit can provide all possible widgets. Arogrammers must create such widgets by themselves. They do it by using the drawing tools provided by the toolkit. There are two possibilities. , programmer can modify or enhance an e+isting widget. %r he can create a custom widget from scratch.

The Burning widget


In the ne+t e+ample$ we will create a custom burning widget. This widget can be seen in applications like >ero or !2=. The widget will be created from scratch.
#!/usr/bin/ruby # ZetCode Ruby Qt tutorial # # # # # # 5n this pro+ra . we create a custo wid+et Qauthor Gan bodnar website zetcode.co last odi!ied July #$$P

)/

re&uire 'Qt' >(@8A=78527T 1 0$ 65"T(@C8 1 %P A5@8=*56T7 1 6535"5C@" 1 %$ KSAA=C(>(C5TL 1 I$$ M(Z=C(>(C5TL 1 I-$ class Burnin+ ) Qt::*id+et de! initialize:parent< super:parent< Qnu 1 X ,I-,. ,%-$,. ,##-,. ,0$$,. ,0I-,. ,E-$,. ,-#-,. ,H$$,. ,HI-, Y

QredColor 1 Qt::Color.new #--. %I-. %IQyellowColor 1 Qt::Color.new #--. #--. %?E Qparent 1 parent setMini u 7ei+ht >(@8A=78527T end de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw*id+et painter painter.end

end

de! draw*id+et painter w 1 width.to=! slid=width 1 Qparent.+etCurrent*idth step 1 :w / 6535"5C@"<.round.to=! till 1 ::w / M(Z=C(>(C5TL< W slid=width<.to=! !ull 1 ::w / M(Z=C(>(C5TL< W KSAA=C(>(C5TL<.to=! i! slid=width V KSAA=C(>(C5TL painter.set>en QyellowColor painter.setBrush Qt::Brush.new QyellowColor painter.drawRect Qt::RectK.new $. $. !ull. >(@8A=78527T painter.set>en QredColor painter.setBrush Qt::Brush.new QredColor painter.drawRect Qt::RectK.new !ullU%. $. till;!ull. >(@8A=78527T else i! slid=width V $ painter.set>en QyellowColor painter.setBrush Qt::Brush.new QyellowColor painter.drawRect Qt::RectK.new $. $. till. >(@8A=78527T end

)2

end painter.set>en Qt::Color.new P$. P$. P$ painter.setBrush Qt::@oBrush painter.drawRect $. $. w;%. >(@8A=78527T;% newKont 1 !ont newKont.set>oint"ize I painter.setKont newKont !or i in :%..Qnu .len+th< painter.drawAine Qt::AineK.new iWstep. %. iWstep. A5@8=*56T7 etrics 1 Qt::KontMetrics.new newKont w 1 etrics.width Qnu Xi;%Y painter.drawTe4t:Qt::>ointK.new:iWstep;w/#. 65"T(@C8<. Qnu Xi; end end end

%Y<

class Qt(pp ) Qt::*id+et slots 'onChan+ed:int<' de! initialize super set*indowTitle ,The Burnin+ *id+et, initS5 resize 0I$. #$$ o/e 0$$. 0$$ show end de! initS5 Qcur=width 1 $ Qslider 1 Qt::"lider.new Qt::7orizontal . sel! Qslider.setMa4i u M(Z=C(>(C5TL Qslider.set2eo etry -$. -$. %0$. 0$ connect:Qslider. "52@(A:,/alueChan+ed:int<,<. sel!. "ACT:,onChan+ed:int<,<< /bo4 1 Qt::3Bo4Aayout.new sel! hbo4 1 Qt::7Bo4Aayout.new /bo4.add"tretch % Qwid+et 1 Burnin+.new sel! hbo4.add*id+et Qwid+et. $ /bo4.addAayout hbo4 setAayout /bo4 end

)5

de! onChan+ed /al Qcur=width 1 /al Qwid+et.repaint end de! +etCurrent*idth return Qcur=width end

end

app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec

In this file$ we create the =urning widget.


class Burnin+ ) Qt::*id+et

The custom widget is based on the *id+et widget.


>(@8A=78527T 1 0$ 65"T(@C8 1 %P A5@8=*56T7 1 6535"5C@" 1 %$ KSAA=C(>(C5TL 1 I$$ M(Z=C(>(C5TL 1 I-$

These are important constants. The >(@8A=78527T defines the height for the custom widget. The 65"T(@C8 is the distance of the numbers on the scale from the top of their parent border. The A5@8=*56T7 is the vertical line width. The 6535"5C@" is the number of parts of the scale. The KSAA=C(>(C5TL is the ma+imum capacity of the media. ,fter it is reached$ overburning happens. This is visuali3ed by a red color. The M(Z=C(>(C5TL is the ma+imum capacity of a medium.
Qnu 1 X ,I-,. ,%-$,. ,##-,. ,0$$,. ,0I-,. ,E-$,. ,-#-,. ,H$$,. ,HI-, Y

-e use these numbers to build the scale of the =urning widget.


de! paint8/ent e/ent painter 1 Qt::>ainter.new sel! draw*id+et painter painter.end end

The drawing of the custom widget is delegated to the draw*id+et method.


slid=width 1 Qparent.+etCurrent*idth

-e use it to get the currently selected slider value.


w 1 width.to=!

))

-e get the width of the widget. The width of the custom widget is dynamic. It can be resi3ed by a user.
till 1 ::w / M(Z=C(>(C5TL< W slid=width<.to=! !ull 1 ::w / M(Z=C(>(C5TL< W KSAA=C(>(C5TL<.to=!

-e use the w variable to do the transformations. =etween the values of the scale and the custom widgetHs measures. >ote that we use floating point values. -e get greater precision in drawing.
painter.set>en QredColor painter.setBrush Qt::Brush.new QredColor painter.drawRect Qt::RectK.new !ullU%. $. till;!ull. >(@8A=78527T

These three lines draw the red rectangle$ indicating the overburning.
painter.drawRect $. $. w;%. >(@8A=78527T;%

This is the perimeter of the widget. The outside rectangle.


painter.drawAine Qt::AineK.new iWstep. %. iWstep. A5@8=*56T7

.ere we draw the small vertical lines.


w 1 etrics.width Qnu Xi;%Y painter.drawTe4t:Qt::>ointK.new:iWstep;w/#. 65"T(@C8<. Qnu Xi;%Y<

.ere we draw the numbers of the scale. To precisely position the numbers$ we must get the width of the string.
Qwid+et 1 Burnin+.new sel! hbo4.add*id+et Qwid+et. $

-e create the instance of the =urning widget and add it to the hori3ontal bo+.
de! onChan+ed /al Qcur=width 1 /al Qwid+et.repaint end

-hen the value of the slider changes$ we store it inside the Qcur=width variable and repaint the custom widget.
de! +etCurrent*idth return Qcur=width end

This method is called by the custom widget to get the actual slider value.

)8

0igure1 The =urning widget In this part of the Ruby Qt tutorial$ we have demonstrated how to create a custom widget.

Nibbles
In this part of the Ruby Qt programming tutorial$ we will create a >ibbles game clone. Nibbles is an older classic video game. It was first created in late ;:s. 6ater it was brought to A7s. In this game the player controls a snake. The ob*ective is to eat as many apples as possible. #ach time the snake eats an apple$ its body grows. The snake must avoid the walls and its own body.

&e(elopment
The si3e of each of the *oints of a snake is ':p+. The snake is controlled with the cursor keys. Initially$ the snake has three *oints. The game starts immediately. -hen the game is finished$ we display GGame %verG message in the center of the window. =oard.rb
*56T7 1 0$$ 78527T 1 0$$ 6CT="5Z8 1 %$ (AA=6CT" 1 *56T7 W 78527T / :6CT="5Z8 W 6CT="5Z8< R(@6=>C" 1 #P 68A(L 1 %E$ B4 1 X$Y W (AA=6CT" By 1 X$Y W (AA=6CT" class Board ) Qt::*id+et de! initialize:parent< super:parent< setKocus>olicy Qt::"tron+Kocus init2a e end

);

de! init2a e Qle!t 1 !alse Qri+ht 1 true Qup 1 !alse Qdown 1 !alse Qin2a e 1 true Qdots 1 0 be+in Qball 1 Qt::5 a+e.new ,dot.pn+, Qapple 1 Qt::5 a+e.new ,apple.pn+, Qhead 1 Qt::5 a+e.new ,head.pn+, rescue puts ,cannot load i a+es, end !or i in :$..Qdots< B4XiY 1 -$ ; i W %$ ByXiY 1 -$ end locate(pple set"tyle"heet ,Q*id+et D bac9+round;color: #$$$$$$ F, Qti er 1 Qt::BasicTi er.new Qti er.start:%E$. sel!< end de! paint8/ent e/ent painter 1 Qt::>ainter.new painter.be+in sel! i! Qin2a e drawCbGects painter else +a eC/er painter end end painter.end

de! drawCbGects painter painter.draw5 a+e Qapple=4. Qapple=y. Qapple !or z in :$..Qdots< i! z 11 $ painter.draw5 a+e B4XzY. ByXzY. Qhead else painter.draw5 a+e B4XzY. ByXzY. Qball end end end de! +a eC/er painter

)<

s+ 1 ,2a e C/er, s all 1 Qt::Kont.new ,7el/etica,. %#. Qt::Kont::Bold./alue etr 1 Qt::KontMetrics.new s all te4t*idth 1 h 1 hei+ht w 1 width etr.width s+

painter.set>en Qt::Color.new Qt::white painter.setKont s all painter.translate Qt::>oint.new w/#. h/# painter.drawTe4t ;te4t*idth/#. $. s+ end de! chec9(pple i! B4X$Y 11 Qapple=4 and ByX$Y 11 Qapple=y Qdots 1 Qdots U % locate(pple end o/e z 1 Qdots while z V B4XzY ByXzY z 1 z end $ 1 B4X:z ; %<Y 1 ByX:z ; %<Y ; %

end de!

i! Qle!t B4X$Y ;1 6CT="5Z8 end i! Qri+ht B4X$Y U1 6CT="5Z8 end i! Qup ByX$Y ;1 6CT="5Z8 end i! Qdown ByX$Y U1 6CT="5Z8 end end de! chec9Collision z 1 Qdots while z V $ i! z V E and B4X$Y 11 B4XzY and ByX$Y 11 ByXzY Qin2a e 1 !alse

)(

end z 1 z ; % end i! ByX$Y V 78527T Qin2a e 1 !alse end i! ByX$Y ) $ Qin2a e 1 !alse end i! B4X$Y V *56T7 Qin2a e 1 !alse end i! B4X$Y ) $ Qin2a e 1 !alse end end de! locate(pple r 1 rand Qapple=4 r 1 rand Qapple=y R(@6=>C" 1 r W 6CT="5Z8 R(@6=>C" 1 r W 6CT="5Z8

end

de! ti er8/ent e/ent i! Qin2a e chec9(pple chec9Collision o/e else Qti er.stop end repaint end de! 9ey>ress8/ent e/ent 9ey 1 e/ent.9ey i! 9ey 11 Qle!t Qup 1 Qdown end Qt::Jey=Ae!t./alue and not Qri+ht 1 true !alse 1 !alse

i! 9ey 11 Qt::Jey=Ri+ht./alue and not Qle!t Qri+ht 1 true Qup 1 !alse Qdown 1 !alse end i! 9ey 11 Qt::Jey=Sp./alue and not Qdown

8:

end

Qup 1 true Qri+ht 1 !alse Qle!t 1 !alse

i! 9ey 11 Qt::Jey=6own./alue and not Qup Qdown 1 true Qri+ht 1 !alse Qle!t 1 !alse end end end

0irst we will define some constants used in our game. The *56T7 and 78527T constants determine the si3e of the =oard. The 6CT="5Z8 is the si3e of the apple and the dot of the snake. The (AA=6CT" constant defines the ma+imum number of possible dots on the =oard. The R(@6=>C" constant is used to calculate a random position of an apple. The 68A(L constant determines the speed of the game.
B4 1 X$Y W (AA=6CT" By 1 X$Y W (AA=6CT"

These two arrays store +$ y coordinates of all possible *oints of a snake. The init2a e method initiali3es variables$ loads images and starts a timeout function.
i! Qin2a e drawCbGects painter else +a eC/er painter end

Inside the paint8/ent method$ we check the Qin2a e variable. If it is true$ we draw our ob*ects. The apple and the snake *oints. %therwise we display GGame overG te+t.
de! drawCbGects painter painter.draw5 a+e Qapple=4. Qapple=y. Qapple !or z in :$..Qdots< i! z 11 $ painter.draw5 a+e B4XzY. ByXzY. Qhead else painter.draw5 a+e B4XzY. ByXzY. Qball end end end

The drawCbGects method draws the apple and the *oints of the snake. The first *oint of a snake is its head$ which is represented by a red circle.
de! chec9(pple i! B4X$Y 11 Qapple=4 and ByX$Y 11 Qapple=y Qdots 1 Qdots U %

8'

end end

locate(pple

The chec9(pple method checks$ if the snake has hit the apple ob*ect. If so$ we add another snake *oint and call the locate(pple method$ which randomly places a new apple ob*ect. In the o/e method we have the key algorithm of the game. To understand it$ look at how the snake is moving. Bou control the head of the snake. Bou can change its direction with the cursor keys. The rest of the *oints move one position up the chain. The second *oint moves where the first was$ the third *oint where the second was etc.
while z V B4XzY ByXzY z 1 z end $ 1 B4X:z ; %<Y 1 ByX:z ; %<Y ; %

This code moves the *oints up the chain.


i! Qle!t B4X$Y ;1 6CT="5Z8 end

&ove the head to the left. In the chec9Collision method$ we determine if the snake has hit itself or one of the walls.
while z V $ i! z V E and B4X$Y 11 B4XzY and ByX$Y 11 ByXzY Qin2a e 1 !alse end z 1 z ; % end

0inish the game$ if the snake hits one of its *oints with the head.
i! ByX$Y V 78527T Qin2a e 1 !alse end

0inish the game$ if the snake hits the bottom of the =oard. The locate(pple method locates an apple randomly on the board.
r 1 rand R(@6=>C"

-e get a random number from : to R,>"JA% - '.


Qapple=4 1 r W 6CT="5Z8 ... Qapple=y 1 r W 6CT="5Z8

These line set the +$ y coordinates of the apple ob*ect. 8/

i! Qin2a e chec9(pple chec9Collision o/e else Qti er.stop end

#very '5: ms$ the ti er8/ent method is called. If we are in the game$ we call three methods$ that build the logic of the game. %therwise we stop the timer. In the 9ey>ress8/ent method of the =oard class$ we determine the keys that were pressed.
i! 9ey 11 Qle!t Qup 1 Qdown end Qt::Jey=Ae!t./alue and not Qri+ht 1 true !alse 1 !alse

If we hit the left cursor key$ we set Qle!t variable to true. This variable is used in the o/e method to change coordinates of the snake ob*ect. >otice also$ that when the snake is heading to the right$ we cannot turn immediately to the left. >ibbles.rb
#!/usr/bin/ruby # # # # # # # # ZetCode Ruby Qt tutorial 5n this pro+ra . we create a @ibbles +a e clone. author: Jan Bodnar website: www.zetcode.co last odi!ied: "epte ber #$%#

re&uire 'Qt' re&uire 'Board' class Qt(pp ) Qt::Main*indow de! initialize super set*indowTitle ,@ibbles, setCentral*id+et Board.new:sel!< resize 0%$. 0%$ o/e 0$$. 0$$ end end app 1 Qt::(pplication.new (R23 Qt(pp.new app.e4ec show

82

In the >ibbles.rb file$ we set up the >ibbles game.

0igure1 >ibbles This was the >ibbles computer game programmed with the Qt library and the Ruby programming language.

85