Handling Interaction: Signals & Slots
You may find it useful to have The Qt Project documentation on Signals & Slots open in your browser while doing this exercise.
Using Built-in Signals & Slots
Create a directory for this exercise and download the archive
volume.zipinto it. Then unpack the archive. This should create a subdirectory calledvolume. In a terminal window,cdinto this subdirectory and spend a couple of minutes examining the files therein.These files simulate a volume control application. The required widget are present, but there is currently no code to handle user interaction.
Use CMake to build the application, then enter
./volumeto run it. You should see something like this:
Adjusting the dial will currently have no effect.
Edit
window.hppand find the comment that says ‘declare makeConnections method here’. Replace the comment with the following method prototype:void makeConnections();This method is where the code to connect signals to slots will go. Note that there is no requirement to do signal-slot connection within such a method; you could do it directly within the constructor, for example. However, you may find this approach helps to make your code better structured and easier to read.
Edit
window.cpp. Inside theVolumeControlconstructor, just after the call toarrangeWidgets(), add a call to themakeConnections()method. Then implement the method at the bottom of the file, like so:void VolumeControl::makeConnections() { connect(dial, SIGNAL(valueChanged(int)), number, SLOT(display(int))); }Here,
connect()is a method inherited fromQWidgetthat is used to connect signals to slots. This particular call will connect thevalueChanged(int)signal generated by theQDialwidget to thedisplay(int)slot provided by theQLCDNumberwidget.Rebuild the application and try running it again. If you have connected signal and slot correctly, you should find that adjusting the dial updates the number.
Custom Slots
Download the archive
dice.zipto the directory that you created for this exercise. In a terminal window,cdto that directory and unpack the archive with the commandunzip dice.zip. This should create a subdirectorydice, containing several files.Spend a few minutes examining the files
window.hpp,window.cppandmain.cpp. Then use CMake to build the application, in the usual way. When you run the application with./dice, you should see the GUI shown below.
Clicking on the ‘Roll Dice’ button will currently have no effect.
Edit
window.hpp. Add the textQ_OBJECTas the first item inside theDiceRollerclass definition, on a line by itself, just before thepublic:section header.Q_OBJECTis a preprocessor macro used in Qt to indicate that a class will define a custom slot.Then add a prototype for a
voidmethod namedmakeConnectionsto theprivatesection.Finally, add a new ‘slots’ section to the class definition, just after the
privatesection:private slots: void rollDice();Edit
window.cpp. Add the following definition of therollDice()method to the bottom of the file:void DiceRoller::rollDice() { int n = random->bounded(0, 6); die1->setPixmap(dieFaces[n]); n = random->bounded(0, 6); die2->setPixmap(dieFaces[n]); }This method will alter the images displayed by label widgets
die1anddie2, making its choices randomly from the images available in the arraydieFaces.Then find the two lines near the start of the
DiceRollerconstructor that callsetPixmap()on labelsdie1anddie2. Replace these two lines with a line that calls therollDice()method.Now define the
makeConnections()method to look like this:void DiceRoller::makeConnections() { connect(rollButton, SIGNAL(clicked()), this, SLOT(rollDice())); }The call to the
connect()method looks a little different from the earlier example. Here, the recipient is specified using thethispointer, meaning ‘thisDiceRollerobject’. The slot is the customrollDice()method defined in the previous step.CautionDon’t forget that you also need to add a line to the constructor that calls
makeConnections(). Put this immediately after the call toarrangeWidgets().Now enter
cmake --build .(or simplymake) to rebuild the application. Run the application again, with./dice. Clicking on the ‘Roll Dice’ button should now change the die face images in a random fashion.NoteBehind the scenes, Qt is checking whether it needs to run the Meta-Object Compiler (
moc) during the build process. This tool generates additional code for the custom slot that integrates it into Qt’s signals & slots mechanism.If you are using the older method for building Qt applications, based on the
qmaketool, then you may find that you need to run this tool again, to generate a new makefile, after adding any new custom signals or slots to your code.
Over To You…
Experiment some more with signals and slots.
Try modifying the volume control application so that it does something else in response to adjustment of the dial. For example, you could change the colour of the number if it exceeds a threshold.
Return to the currency converter application from the previous exercise. Connect up the widgets so that the appropriate conversion calculations are performed when a value or the currency is changed.