Monday, April 30, 2012

Programming in Qt 2 - The core

 Function definition
 Connecting the slot
Finishing things up

In the first tutorial I taught you how to basically create a "hello world" program in QT and change the value of a button. However, explicitly defining everything in that method is not the purpose of a GUI. User interaction is a key feature of any user interface, so in this tutorial I will show you how to create a button that toggles its text. To do so I will use signals and slots. Before we delve into the code, I will explain what those two things are.

During the execution of a Qt application there is a main loop until the user commands the program to stop or there is a serious exception. Signals are Qt constructs that are emitted when a certain action has occurred. You can create your own signals with the emit keyword, but for now we will only worry about custom slots.

Slots are the code executed when a signal has been emitted. These slots are connected to the signals of a certain object within the application. For instance, the slot we will make will be connected to the clicked() signal of the PushButton.

 Function Definition
Create a toggling button
Open Qt creator and open the .pro file that you created in the last exercise. .pro files, or project files are what tell qmake to include that particular file in compilation.

You should already have an application complete with a PushButton in the center. If not, follow the steps in the first tutorial to get to that point. Our first step is to create a prototype for toggleVal() in MainWindow.h. Go to MainWindow.h in Qt creator. The file is located under the "headers" tab which may be collapsed.

I usually append the class after private: since that is the end of the generated code, but you can place these next two lines wherever you want. Some prefer to do it after public:.You need to add this code:

public slots:
void toggleVal();

As you probably already know from studying C++ this creates a prototype, or undefined declaration, of the function toggleVal(), which we will define in MainWindow.cpp.

Navigate to MainWindow.cpp and after the definition of the MainWindow deconstructor add the following lines:

void MainWindow::toggleVal(){
    QString val1="Value 1";
    QString val2="Value 2";
    if(ui->pushButton->text()=="Value 1")
        ui->pushButton->setText("Value 2");
    else if(ui->pushButton->text()=="Value 2")
        ui->pushButton->setText("Value 1");

This is the slot for the PushButton. There are a few new things here. QString is used instead of std::string for Qt text. std::strings can be converted using the fromStdString() function of QString.

text() for pushButton returns the displayed text and setText() sets the text.

Why were the ifs so strict? I find it to be in good style to explicitly define my conditions in my graphical interfaces since other functions could possibly change the value and you may not want it changing at that point. You can define it however you wish, though. The main parts of this code to take are text() and setText().

 Connecting the slot

So far the only thing we have accomplished is making a function that checks the value of a button and changes the text accordingly. This can be called explicitly, but again, that does not give the user enough control. We will connect the slot in the MainWindow constructor of MainWindow.cpp.

After the code 
add these two lines:
ui->pushButton->setText("Value 1"); QObject::connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(toggleVal()));

The first line explicitly sets the text of the button to "Value 1" so that the function can work properly. The second line is a bit trickier.

We call the connect function of QObject which has 4 parameters. The first is the sender, which in this case is the pushButton. Then, the signal  to act on. The signal is placed inside SIGNAL(). If you typed this yourself rather than copy-pasting, you would have seen the list of signals available for use with PushButton. Next is the member, which in this case is the MainWindow. Then, the slot. Like SIGNAL() slots must also go within SLOT(). We supplied our toggleVal() function, but you will see a list of predefined slots if you type that code yourself.

Multiple slots can be connected to a single signal, and multiple signals to a single slot. This becomes an important concept once you have multiple ways to quit or to initiate an action.

This power is immense. You can define toggleVal() to do anything you want. Close the application, parse, move the application wildly around the desktop, draw squares with OpenGL... Anything that Qt and C++ are capable of can be done in slots.

Finishing things up
In this tutorial you learned how to define and connect signals and slots. In the next few tutorials, you will learn about some other parts of the Qt library like QString and QPainter in depth. The next tutorial will be on a slight delay as I still have Qt related learning to do before I am able to write it. Other resources do an alright job of explaining things, but the purpose of these tutorials is to provide a very straightforward approach to Qt. 

No comments:

Post a Comment