Showing posts with label Qt. Show all posts
Showing posts with label Qt. Show all posts

Callback for a multithreaded GUI

In a previous post I showed a brilliant little multithreaded application where two threads, driven by two buttons, were competing on the same resource, a label displaying a number that changed accordingly to the requests of the competing threads.

That application was kind of elegant, using the Qt slot mechanism to connect the working threads with the main window GUI. Alas it was wrong, too. You could not see the error in such a simple application that apparently works correctly, but the point is that simply using "emit" in a thread to connect to another function is not enough to make this other function to run in the same thread. What happened there was that the called function was running in the same thread (the main application thread) whatever was the calling thread. Not exactely what was expected.

So far about the bad news. Good news is that is not a big issue rewriting the code so that it works as I wanted. Here we see how to do it using the good old C++ callback mechanism for classes. By the way, if you need to call just a free function from different threads, you could have a look at another post, that shows exactely that.

The basic idea is that our increasers should know how to call from their run() function - the actual function that runs in an own specific thread - the function in MainWindow that modifies the label. We can easily get this passing to the class a pointer to the MainWindow object itself:
#ifndef INCREASER_H
#define INCREASER_H

#include <QThread>

class MainWindow; // 1.

class Increaser : public QThread
{
public:
Increaser(int step);
void run();
void stop();
void restart();

static void setCallback(MainWindow* that); // 2.
private:
bool isRunnable_;
int step_;

static MainWindow* that_; // 3.
};

#endif // INCREASER_H

1. We don't need to know all the MainWindow class details at this point, we just need to know that we are talking about a class.
2. I assume that we want all the increasers working on the same instance of MainWindow (quite reasonable in this case), so the setCallback() method is static, it has to be called just once for all the increasers.
3. As said above, all the increasers share a reference to the same MainWindow object.

The implementation code for the Increaser class does not change much, but I report it here all of it, just fof clarity sake:
#include "increaser.h"
#include "mainwindow.h" // 1.
#include <iostream>

MainWindow* Increaser::that_ = NULL; // 2.

void Increaser::setCallback(MainWindow* that) { that_ = that; } // 3.

Increaser::Increaser(int step) : isRunnable_(true), step_(step) {}

void Increaser::run()
{
while(true)
{
std::cout << "Step: " << step_ << " in "
<< this->currentThreadId() << std::endl;
msleep(500);
if(!isRunnable_)
break;
if(that_) // 4.
that_->changeValue(step_);
}
}

void Increaser::stop()
{
isRunnable_ = false;
wait();
}

void Increaser::restart()
{
isRunnable_ = true;
QThread::start();
}

1. Here we need the class details, so that the compiler could actually check that really MainWindow has a public method as the one we claim that we want to use.
2. that_ is a static member of the Increaser class, so we have to define it somewhere in the code. Here is a good place. Notice that we explicitely initialize it to NULL: no MainWindows object is available if not set by someone else.
3. And here is the static method that initialize the Increaser static member.
4. The MainWindow changeValue() method is called only if we actually have a valid reference to an object of that type.

The changes in the MainWindow class are even lighter ones.

In the class declaration the method changeValue() is not anymore defined as a slot, but as a "normal" public member:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

// ...

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
// ...

void changeValue(int);

private slots:
// ...
};

#endif // MAINWINDOW_H

The class constructor now sets the callback for the increasers:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow),
increaser_(2), decreaser_(-3), curValue_(100)
{
ui->setupUi(this);
ui->lbValue->setText(QString::number(curValue_));

Increaser::setCallback(this);
}

And here is again the function called by the incresers:
void MainWindow::changeValue(int step)
{
QMutexLocker ml(&mCV_);

std::cout << "change value in " << QThread::currentThreadId() << std::endl;
ui->lbValue->setText(QString::number(curValue_ += step));
}

Running the application we can now see how the thread id is the one of the calling thread. So we can finally say that we have got what we wanted.

Go to the full post

Callback for multithreading

The basic Qt multithreading we have seen before was a bit too basic. Its extensions for showing how and why to use QMutex, and then QMutexLocker do not change much of its substance. Let's complicate it a bit to make it a tad more interesting.

In the original example we have a class, Writer, that extends QThread and that in its run() method writes something. But what if we would like that all the Writer object would run a function that could be set at runtime? A possible solution to this requirement is based on function pointers.

In my main file I have written this function:

namespace
{
static QMutex mio; // 1.

void doSomething(const char* msg, int i)
{
QMutexLocker qml(&mio); // 2.
std::cout << msg << ", thread id " << QThread::currentThreadId() // 3.
<< " value " << i << std::endl;
}
}

1. Since we are about to work in a multithreaded environment, and since we'll have many threads competing on the output console, we'll use a mutex to avoid mixups.
2. Using a lock on the mutex we ensure it would be correctly released at the end of the block.
3. We print the thread id and the data passed by the caller.

We want all the object instantiating Writer calling this doSomething() function (and possibly other functions having the same prototype). To do that, I have refactored the Writer class definition in this way:
#ifndef WRITER_H
#define WRITER_H

#include <QThread>

typedef void(*MY_FUN)(const char*, int); // 1.

class Writer : public QThread
{
public:
explicit Writer(int value);
void run();

static void setCallback(MY_FUN fun); // 2.
private:
static MY_FUN callback_; // 3.
};

#endif // WRITER_H

1. MY_FUN has been typedeffed as pointer to a function returning void and having two input parameters, a pointer to const char, and an integer.
2. using this static method we could set the callback function available to all Writer objects.
3. the callback_ function pointer is static: all the Writer object refer to the same one.

The static data members have to be defined in the source code, so in writer.cpp I added the callback_ definition:
MY_FUN Writer::callback_ = NULL;
Initially there is no callback function pointer defined.

And here is the Writer functions:
void Writer::setCallback(MY_FUN fun)
{
callback_ = fun;
}

Writer::Writer(int value)
{
if(callback_) // 1.
callback_("ctor", value);
}

void Writer::run()
{
for(int i = 0; i < 20; ++i)
{
if(callback_)
callback_("Running", i); // 2.

msleep(200);
}
}

1. As always when working with pointers, it is a good idea to check them before trying to use them.
2. Being called from run(), we ensure that our callback function is called in the new thread.

Not a big change in the main function:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

Writer::setCallback(&doSomething);

Writer w1(1);
Writer w2(2);
Writer w3(3);

w1.start();
w2.start();
w3.start();

w1.wait();
w2.wait();
w3.wait();

// terminates in a couple of seconds
QTimer::singleShot(12000, &a, SLOT(quit()));

return a.exec();
}

What we have done, basically, has been externalizing the job done by each sub-thread, so that it could be easily changed even at runtime.

Go to the full post

Multithreading with a GUI

Have you ever dreamt of a tiny Qt window-based application showing a number that could be continuously increased or decreased pushing on a couple of buttons? Well, that is what we are about to do in this post.

OK, it's a pretty silly application, but it has a few good points to show. Through it we could easily show how the user could stop and start other threads from the main one, and we could see the connect mechanism as a way to allow us to easily establish a communication between different threads.

I leave out the creation of the application graphical part, think of it as a preparatory exercise. As a hint, I tell you that I created by Qt Creator a Qt Gui Application with a QMainWindow. Then, in design mode, I put in the window a QLabel (named lbValue), and a couple of QPushButton objects, btnIncrease and btnDecrease. I have even embellished a bit the mainWindow, adding another QLabel saying "Current value:" and other few details that here have no primary interest (an Exit button, a few menu items ...).

Then I created a connection from each of the two buttons to a slot, right clicking on each of them and selecting the "Go to slot..." item in the popup window, selecting clicked() as signal. In response to that, Qt created a couple of private slots in the MainWindow class declaration, named on_btnDecrease_clicked() and on_btnIncrease_clicked() that are connected as expected to the proper button.

Now the fun stuff.

Actually, what we are going to see here is a Qt antipattern. Using a QThread derived class in this way is attractive but wrong. A working alternative is shown in another post, where I use a callback mechanism in multithreading environment that works right.

We want that clicking on a button a thread starts and modify the label value adding (or subtracting) a specific amount. To do that we can create a class like this:
#ifndef INCREASER_H
#define INCREASER_H

#include <QThread>

class Increaser : public QThread // 1
{
Q_OBJECT // 2
public:
  Increaser(int step); // 3
  void run(); // 4
  void stop(); // 5
  void restart(); // 6
signals:
  void increase(int); // 7
private:
  bool isRunnable_; // 8
  int step_;
};

#endif // INCREASER_H
1. We are extending QThread, as we have already seen previously.
2. We need the Q_OBJECT macro, since we want to use the signal-slot connection mechanism.
3. The ctor requires a step, that we'll use to increment the label value
4. Override of run(), virtual function defined in QThread.
5. Terminates the execution of the current thread.
6. When we want to restart an Increaser that has already been started, we should call this specific method.
7. When the current thread wants the label to be changed emits this signal. If this signal is not connected to any slot, nothing happens.
8. Flag that we use to gracefully stop (and restart) the current thread.

Here its implementation:
Increaser::Increaser(int step) : isRunnable_(true), step_(step) {}

void Increaser::run()
{
  while(true) // 1
  {
    msleep(500); // 2
    if(!isRunnable_) // 3
      break;
    emit increase(step_); // 4
  }
}

void Increaser::stop() // 5
{
  isRunnable_ = false;
  wait();
}

void Increaser::restart()
{
  isRunnable_ = true; // 6
  QThread::start();
}
1. When the current thread runs, it executes this infinite loop.
2. It sleeps for half a second.
3. If a request to stop the thread has been issued, the loop breaks - so the run terminates.
4. If the run is still active, an increase signal is emitted. [Dammit, this does not work as expected - at least, as expected by me. The connect mechanism does not let this code being executed by the current thread, but transfer the request to the main thread. If what you need to call at this point is just a free function, you could have a look at this other post where I use a function pointer as a callback. A more general solution is showed in another post, using a C++ class callback mechanism].
5. The stop() call is synchronous. The run flag is set to false, then we wait till run() terminates, before returning to the caller.
6. If we don't reset the run flag to true, run() would immediately terminate.

Now we are ready to extend our MainWindow:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMutex>
#include "increaser.h"

namespace Ui
{
  class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();

  void closeEvent(QCloseEvent *); // 1
private slots:
  void on_btnDecrease_clicked(); // 2
  void on_btnIncrease_clicked();
  void changeValue(int); // 3
private:
  Ui::MainWindow *ui;
  Increaser increaser_; // 4
  Increaser decreaser_;

  int curValue_; // 5
  QMutex mCV_; // 6
};

#endif // MAINWINDOW_H
1. We don't want to leave the execution when secondary threads are still running, so we ensure here they are terminated.
2. The two slots created by Designer accordingly to our request.
3. The slot we create to connect to the Increaser signal (notice that this would lead to troubles).
4. A couple of Increaser objects.
5. The current value that is displayed in the label.
6. We'll have two threads competing for changing curValue_, so we should rule its access using a QMutex.

Here is the ctor definition:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow),
increaser_(2), decreaser_(-3), curValue_(100)
{
  ui->setupUi(this);
  ui->lbValue->setText(QString::number(curValue_)); // 1

  connect(&increaser_, SIGNAL(increase(int)), this, SLOT(changeValue(int))); // 2
  connect(&decreaser_, SIGNAL(increase(int)), this, SLOT(changeValue(int)));
}
1. The label text is set using the starting value given to curValue_.
2. We connect the signal of both Increaser objects to the local slot. They are competing on the same resource. [This looks quite cool, but it does not work as I expected. The connection reside in the current (main) thread, and not in the one managed by the Increaser objects. An alternative approach could be using function pointers. Or we can modify this code using C++ class callback instead.]

I show just one on_xxx_clicked() slot, since they are essentially the same. The difference is that one refers to increaser_ and btnIncrease, the other to decreaser_ and btnDecrease:
void MainWindow::on_btnIncrease_clicked()
{
  if(increaser_.isRunning()) // 1
  { // the thread is running, stop it
    ui->btnIncrease->setText("Start +");
    increaser_.stop();
  }
  else // 2
  { // start (or restart) the thread
    ui->btnIncrease->setText("Stop +");
    increaser_.restart();
  }
}
1. If the thread is already running, clicking the button we ask to stop it.
2. Otherwise we (re)start it. Notice that I just call restart() without caring much of the difference. It would make sense calling explicitly start() only when we wanted to assign a specific priority to the thread.

When a request to close the main window is issued, we ensure the Increaser thread are stopped before terminating:
void MainWindow::closeEvent(QCloseEvent *)
{
  increaser_.stop();
  decreaser_.stop();
}
Here is the slot that lets the Increasers modify the label value:
void MainWindow::changeValue(int step)
{
  QMutexLocker ml(&mCV_);
  ui->lbValue->setText(QString::number(curValue_ += step));
}
Here the code is quite simple, and we shouldn't have much harm even if both thread would try to run it concurrently. Worst case scenario is that both increase on curValue_ happen before the label is actually displayed, so we could lose to see a number that was doomed to disappear in moment. In any case, using a QMutexLocker we ensure it working correctly, without losing anything at all. [Actually, currently here the mutex has no use at all, since this function is not called by different threads, as I expected. See an alternative using function pointers and another, more to the point, that uses C++ object callback]

Go to the full post

RAII for QMutex by QMutexLocker

When more than a thread is competing on a shared resource, we are bound to have problems. Using a QMutex is the most common answer in Qt for this issue.

Still, we should design the code carefully - if it is not trivial as the one I am using for these examples - to ensure that all the calls to lock()/unlock() match correctly, an we should pay extra care on the possible exceptions that could break that matching.

RAII (Resouce Acquisition Is Initialization) paradigm helps us to solve this concern, keeping our code even more readable. And QMutexLocker is the Qt class designed to do that.

The RAII idea is that when we need to acquire a resource we should think of this as a initialization, so, in our case we should think to acquiring a lock on the mutex as the creation of an object (of type QMutexLocker) that accept the mutex as initialization parameter. Doing that we save ourselves the hassle of remembering to unlock() the mutex, since that would be automatically done by the QMutexLocker dtor.

And what if an exception happens just after the QMutexLocker object is allocated? No problem at all. The C++ mechanism of stack unwinding ensures that all objects on the stack are correctly disposed.

All this safety is achieved rewriting the run() function from the previous post in this way:
void Writer::run()
{
for(int i = 0; i < 20; ++i)
{
{
QMutexLocker qml(&mio_);
std::cout << '[' << qPrintable(mark_) << value_ << ']';
}

msleep(200);
}
}

If you are wondering why I have put the QMutexLocker object and the print statements in a block of their own, you should remember that we want the locking on the mutex to be effective in the shortest possible region of the code. Since we are using a QMutexLocker object to rule it, we create an artificial block, just to get the effect of making that object exiting of its scope as soon as possible, unlocking the mutex.

Go to the full post

QMutex for shared resources

It is almost an everyday experience seeing a problem rising from the fact that two or more guys competes on a resource available to both.

The resource could be a door, wide enough just to let pass a single person. How to decide who should wait and who could pass? In computer sciences we could use a mutex (short for MUTual EXclusion) to take that decision, and Qt implements this concept in the QMutex class.

In a multithreading environment, the standard output console is a good example of a shared resource for which different threads competes. To let this issue emerge, I have slightly modified the example of the previous post, where we played with a simple multithreading Qt application. I have made the class Writer moderately more complex, adding a private integer member, named value_, and I changed accordingly its ctor, to let the user code a way to set the new data member:
explicit Writer(const QString& mark, int value = 42) : mark_(mark), value_(value) {}
Besides, I changed the printing line in the Writer::run() method in this way:
std::cout << '[' << qPrintable(mark_) << value_ << ']';
Actually, I have also changed the main, passing 1, 2, and 3 as second parameter to the ctor for each Writer object, and this was the first output line I have got running the application:
[One[Three3]1][Two2][Three3][One1][Two2][Three3][One1][Two2][Three[One1]3][Two2]
As you can see, we have an issue. Often nothing bad happens, and we have the print just as we exptected: "[One1]". But sometimes we get funny results, like the very first chunk of characters: "[One[Three3]1]". What happened there is quite clear, Thread 1 was happily executing its printing line, had already sent the first part of it, "[One", to the standard output console, when Thread 3 jumped in, printed all its stuff, "[Three3]", before giving back the control to Thread 1 that, completely unaware of the interruption, sent the final part, "1]", to the console.

This is usually bad, as you can imagine. And the worst part is that the unexpected behaviour happens randomly, making it a possible nightmarish debugging issue.

Luckly we have ways to avoid this scenario. Using QMutex we could redesign our Writer class in this way:
#ifndef WRITER_H
#define WRITER_H

#include <QThread>
#include <QString>
#include <QMutex>

class Writer : public QThread
{
public:
explicit Writer(const QString& mark, int value = 42) : mark_(mark), value_(value) {}

void run();
private:
QString mark_;
int value_;

static QMutex mio_;
};

#endif // WRITER_H

The focal point is that we added a unique QMutex object available to all the class instances - that is the sense of making it static - so that it would be the access ruler to the IO. Its name should suggest its raison d'être: mio_ as mutex for I/O.

Being a static variable it has to be defined somewhere in the source code, I put it in the writer.cpp file, just before the run() definition:
QMutex Writer::mio_;

void Writer::run()
{
for(int i = 0; i < 20; ++i)
{
mio_.lock(); // 1.
std::cout << '[' << qPrintable(mark_) << value_ << ']';
mio_.unlock(); // 2.

msleep(200);
}
}

1. Any thread executing the run() code, before printing - using the shared resource std::cout - tries to acquire a lock on the mutex. If another thread has locked the mutex, the current one patiently sits waiting for it.
2. As soon as the thread has finished using the shared resource, it should release the lock on the mutex, giving a chance to the other threads to access it.

As we can see running this new version of the application, this approach works fine, and it is ok in such a simple case, but it is far from being perfect. We rely too heavily on the programmer to match correctly lock()/unlock() on a mutex and we are not considering the risk of an exception happening just after we locked a mutex and before we could unlock it. In the next post we'll see a more robust solution.

Go to the full post

Basic multithreading with Qt

Qt provides a class, QThread, that helps us creating multithreading applications. The basic idea is that you create a your own class derived from QThread, implement its run() method to do what you expect it doing and then use it instantiating an object of that class for each thread you want to be available, and explicitely starting it.

As an example, think to a writer class that simply outputs a few times a string:
#ifndef WRITER_H
#define WRITER_H

#include <QThread>
#include <QString>

class Writer : public QThread
{
public:
explicit Writer(const QString& mark) : mark_(mark) {}

void run();
private:
QString mark_;
};

#endif // WRITER_H

As said, we redefine run(), virtual QThread function to let it performs a specific task:
void Writer::run()
{
for(int i = 0; i < 20; ++i)
{
std::cout << qPrintable(mark_);
msleep(200);
}
}

The QThread::msleep() function is used to put the current thread to sleep for the passed millisecs.

Here is the main function for this first approach to Qt multithreading:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include "writer.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv); // 1.

Writer w1("One");
Writer w2("Two");
Writer w3("Three"); // 2.

w1.start();
w2.start();
w3.start(); // 3.

w1.wait();
w2.wait();
w3.wait(); // 4.

QTimer::singleShot(12000, &a, SLOT(quit())); // 5.

return a.exec();
}

1. To keep the code as simple as possible, I choose a Qt console application as target.
2. Three objects of the customized QThread subclass have been created.
3. And started. Once started, a thread is on its own till its run() method terminates.
4. We wait till all three sub-threads complete their job.
5. Then we send an event to the application loop, for asking to terminate in a dozen of seconds.

Go to the full post

From QDialog to statusBar

In the previous post I have used a dialog in modeless way. Here we see a modal dialog in action.

I want to let the user input a message he wants to display on the main window status bar, specifying also how long he'd like such a message being visible.

To do that I have slightly modified the dialog of the previous post, adding a QLineEdit element, named lineEdit, to let the user input the message to be displayed, and a QSpinBox, spinBox, to let him specify the requested time. There is not much to say about doing this stuff with the Qt Creator Design module, maybe it has some interest saying that I have set the spinBox property maximum to 10, so that the interval is now [0..10].

I have changed the DlgHello class declaration adding a couple of public methods like this:
class DlgHello : public QDialog
{
Q_OBJECT
public:
explicit DlgHello(QWidget *parent = 0);
QString getMessage();
int getDelay();
// ...
};

And here is their definition:
QString DlgHello::getMessage()
{
return ui->lineEdit->text();
}

int DlgHello::getDelay()
{
return ui->spinBox->value() * 1000;
}

Not much to say about getMessage(), but getDelay() is a bit more interesting since it returns the spinBox value multiplied by one thousand. The reason for that is that the status bar expects the time expressed in milliseconds, while in the spin box I expressed the value in seconds.

Here is the change in the main window:
void MainWindow::sayHello()
{
DlgHello dlg(this);
if(dlg.exec())
ui->statusBar->showMessage(dlg.getMessage(), dlg.getDelay());
}

Now we work on a DlgHello local variable defined in the method called as slot when the triggered() signal is emitted for the Say Hello action. Calling exec() on it makes us checking if the user click the OK button or not. In case of OK we show the message in the status bar with the specified delay. Notice that if user specifies 0 as delay, the message is shown as long as possible, until another element in the window requires to change the message on the status bar.

Go to the full post

Connecting Ui action to window function

A key feature to understand in Qt is the signal-slot relation. It could useful to get how it works thinking to an example like this one: Say that we have a MainWindow class created with Qt Creator in design mode, with a menu item for actionSayHello. We want that when the user call the related action, a dialog pops up saying hello to him.

One way to do that requires us to add to our MainWindow class a slot and the definition of a pointer to our dialog class:
class MainWindow : public QMainWindow
{
Q_OBJECT

// ...

private slots:
void sayHello();

// ...
private:
// ...
DlgHello* dlgHello;
};


The class ctor would now initialize to NULL the pointer to the dialog and provide a connection from the Ui action to the slot in the main window class:
MainWindow::MainWindow() : QMainWindow(NULL), ui(new Ui::MainWindow),
dlgHello(NULL)
{
ui->setupUi(this);
connect(ui->actionSayHello, SIGNAL(triggered()), this, SLOT(sayHello()));
}

We say that the signal triggered() for the ui actionSayHello object is connected to this sayHello() slot. Now, when the user click on the Say Hallo menu item, the triggered() signal is emitted and, through this connection, the MainWindow::sayHello() slot for this object is called.

Our definition for the sayHello function would be something as:
void MainWindow::sayHello()
{
if(dlgHello == NULL) // 1.
dlgHello = new DlgHello(this);

dlgHello->show(); // 2.
dlgHello->raise();
dlgHello->activateWindow();
}

1. Lazy initilization for the dialog - the first time the function is called, the object is created. This is a modeless dialog, so we just create it once and show/hide it accordingly to user requests.
2. Actually, calling all three these functions on the dialog is a bit an overkilling. It would be cleaner to call just show() if the dialog is hidden, and otherwise raise() and activateWindow(). But if the dialog is not hidden, show() does nothing, so writing the code in this way save us to some extra-typing that wouldn't add any value to our function.

Go to the full post

QApplication and QMainWindow

Even though is possible using Qt in console mode, typically a Qt application has a graphic user interface.

That means that the event loop is managed by a QApplication instance, and the user interact with the application through widgets. As startup widget we could use any reasonable class derived from QWidget, but the normal choice fall on QMainWindow or, better, on a subclass of it that we create in our application.

Here we are going to see how it's easy to generate a main window for our application using Qt Creator.

Large part of the job is done by Qt Creator itself as we specify that we want to create a new project - Qt Gui Application, and specify that we want our MainWindow has QMainWindow as base class. Other possible alternatives here are QWidget and QDialog.

The standard main file generated by Qt Creator in this case is something like this:

#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

A QApplication object is instantiated, passing to it the arguments coming from the command line; and then a MainWindow object is created and showed. Finally the QApplication::exec() method is called, that would run the event loop manager.

This is already a working Qt GUI application, but let's add to it some minimal customization.
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <memory>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(); // 1.

private:
MainWindow(const MainWindow&); // 2.
MainWindow& operator=(const MainWindow&);

void closeEvent(QCloseEvent* event); // 3.
std::auto_ptr<Ui::MainWindow> ui; // 4.
};

#endif // MAINWINDOW_H

1. I want MainWindow having always no ancestor, so I give no chance of passing to it a parent.
2. I don't want MainWindow to be copied, so I explicitely make unusable its copy ctor and assignment operator.
3. Let's add a check on the application end.
4. And let's be smart on the UI pointer, using an auto_ptr (no need for a more advanced smart pointer). In this way there is no need anymore for dtor in this class.

And here are the changes in the class implementation:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QCloseEvent>

MainWindow::MainWindow() : QMainWindow(NULL), ui(new Ui::MainWindow) // 1.
{
ui->setupUi(this);
}

void MainWindow::closeEvent(QCloseEvent* event) // 2.
{
int res = QMessageBox::warning(this, windowTitle(), "Are you sure?",
QMessageBox::Yes|QMessageBox::No);
if(res == QMessageBox::Yes)
event->accept(); // 3.
else
event->ignore(); // 4.
}

1. The QMainWindow ctor is called passing always NULL as parameter: no ancestor ever for objects of this class.
2. It's a virtual function defined in QWidget used to give the subclasses a chance to do so something when the user ask to close a window.
3. If the user confirms he wants to close the window, we mark the event as to be accepted.
4. The user changed his mind, we mark the event as to be ignored - the window won't be closed.

Besides this changes in the code, I made also a few changes in the GUI, using the internal Design Editor.

Firstly, I wanted "Simple App" be the title of my window. To do that, I selected MainWindow as current object in the Object Inspector (if you can't find it, check it in the menu Window - submenu View) and then, in the Property Editor I put the name I choose in the windowTitle field.

Secondly, I added a Menu, named File, with two items: Say Hello (currently doing nothing) and Exit (to close the window in an alternative way with respect to clicking on the 'X' on the window right top). This is done easily acting directly on the window as showed by the desing editor.

Thirdly, I wanted to associate a shortcut, Alt-X, to the Exit action. This could be done through the Action Editor window (if you don't see this windows, check the menu Window - submenu Views - Action Editor item). Double click on the item actionExit, it has been created for me by the Design Editor when I created the menu item Exit (by the way, I entered it as "E&xit" so that its x is interpreted as a shortcut in the menu) and you have access to all the details for the action. I was interested in adding a shortcut to it, so I entered it in the relative input line.

One more thing I wanted to do, was adding a connection between the Exit action and the window closing, so that clicking on the Exit menu item, or entering Alt-X, would actually close my window. I did that in the Signals & Slots Editor that should be accessible as a tabbed window besides the Action Editor. If you can't see it go in the menu Window - submenu Views - and check the relative item. I clicked on the big green plus to add a new connection, then I specified: actionExit as sender, triggered() as signal, MainWindow as receiver, and close() as slot.

If I get back to the Edit view (clicking on the Edit icon on the left in the Qt Creator window) I see the form as an XML file, in my case named mainwindow.ui, and I can check how the changes I made are reflected here.

Go to the full post

Ftp with Qt

As a better example of usage for QCoreApplication, we can see how to use QFtp, the Qt class that provides an implementation for an FTP client.

I wrote this post after reading the part relative to the same argument in chapter 15 of C++ GUI Programming with Qt4, 2nd Edition by Jasmin Blanchette and Mark Summerfield - Prentice Hall. And I suggest you to read it too for more details on the matter.

Since our project is going to use network features, we should ensure that our .pro file contains a line like this:
QT       += core network
Then, we create a class for managing the FTP access:
#ifndef FTPGETTER_H
#define FTPGETTER_H

#include <QObject>
#include <QFtp>
#include <QFile>
#include <QUrl>

class FtpGetter : public QObject
{
Q_OBJECT
public:
explicit FtpGetter(QObject *parent = 0);

bool getFile(const QUrl& url); // 1.
signals:
void done(); // 2.
private slots:
void ftpDone(bool); // 3.
private:
QFtp ftp;
QFile file;
};
#endif // FTPGETTER_H

1. We'll call getFile() to connect and retrieve a file from a FTP server.
2. This signal would be connected to the job to be done when the FtpGetter job is completed.
3. We'll make this slot be called when the QFtp object signals that its job is done.

In the relative .cpp file we are going to implements the FtpGetter methods in this way:
FtpGetter::FtpGetter(QObject *parent) : QObject(parent)
{
connect(&ftp, SIGNAL(done(bool)), this, SLOT(ftpDone(bool)));
}

The constructor connects the signal done() for the ftp object owned by the class to the ftpDone() slot of this instance.

Large part of the job is done in getFile():
bool FtpGetter::getFile(const QUrl &url)
{
if (!url.isValid())
{
std::cerr << "Error: Invalid URL." << std::endl;
return false;
}

if(url.scheme() != "ftp")
{
std::cerr << "Error: not an ftp address." << std::endl;
return false;
}

if(url.path().isEmpty())
{
std::cerr << "Error: URL has no path." << std::endl;
return false;
}

QString localFileName = QFileInfo(url.path()).fileName();
if(localFileName.isEmpty())
localFileName = "file.out";

file.setFileName(localFileName);
if(!file.open(QIODevice::WriteOnly))
{
std::cerr << "Error: Cannot write file "
<< qPrintable(file.fileName()) << ": "
<< qPrintable(file.errorString()) << std::endl;
return false;
}

ftp.connectToHost(url.host(), url.port(21));
ftp.login();
ftp.get(url.path(), &file);
ftp.close();

return true;
}

After checking that the user passed a good URL, we create a local file name (if possible, we keep the same name of the original file), we open it in write only mode, then we ask our FTP object to perform a connection, login, getting the file, and then close the connection. Notice that all these operation are done asynchronously, so we don't actually know if they succeeded or not at the end of this function call. We return sort of "tentatively" success, waiting for more feedback from FTP.

As we have seen in the ctor, ftpDone() is called in connection to ftp::done(), so it is here that we check if actually the FTP operation has succeeded or not:
void FtpGetter::ftpDone(bool error)
{
if(error)
std::cerr << "Error: " << qPrintable(ftp.errorString()) << std::endl;
else
std::cerr << "File downloaded to " << qPrintable(file.fileName()) << std::endl;
file.close();
emit done();
}

After writing some feedback, this method emits the done() signal.

The main function of our application would take care of instantiating a FptGetter object, calling it with a suitable URL (here I ask for a file on the trolltech server containing the list of mirrors), and connecting the FtpGetter::done() signal to the QCoreApplication::quit() slot for our current application object. That would mean that we quit the application when the FTP transfer has been completed:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

FtpGetter getter;
QUrl url("ftp://ftp.trolltech.com/mirrors");
std::cout << "Getting file " << qPrintable(url.path())
<< " from " << qPrintable(url.authority());
if(!getter.getFile(url))
{
std::cout << " failed." << std::endl;
return 1;
}

QObject::connect(&getter, SIGNAL(done()), &a, SLOT(quit()));
return a.exec();
}

Notice that in case FtpGetter::getFile() returns failure we don't even care of entering the main loop in the core application object, and just terminating the application instead.

Go to the full post

QCoreApplication says hello

Usually we use Qt to develop a GUI application, but that is not mandatory. We could be interested in developing an application using a feature made available by Qt, like the network or XML support, without any explicit need for a graphical interface.

In this case we can develop a console application, that rely on QCoreApplication, instead of the usual QApplication, to provide an even loop for the application.

As an example, here is a trivial application, that says hello and then terminates. To make the code slightly more interesting, I create a class, Greeter, that provides a slot, sayHello(), to be called to greet the user:
#ifndef GREETER_H
#define GREETER_H

#include <QObject>
#include <iostream>

class Greeter : public QObject
{
Q_OBJECT
public:
explicit Greeter(QObject *parent = 0) : QObject(parent) {}

signals:

public slots:
void sayHello() { std::cout << "Hello" << std::endl; }
};
#endif // GREETER_H

And here is the main:
#include <QtCore/QCoreApplication>
#include <QTimer>
#include "greeter.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

Greeter g;
QTimer::singleShot(2000, &g, SLOT(sayHello())); // 1.
QTimer::singleShot(5000, &a, SLOT(quit())); // 2.

g.sayHello(); // 3.
return a.exec(); // 4.
}

1. We use QTimer to do a delayed call (by 2 secs) to g.sayHello().
2. After 5 secs we'll call the quit() method for our QCoreApplication object, that will have the effect of terminating the call to exec().
3. We call immediately g.sayHello().
4. The Qt application enters the main event loop - that will be interrupted by the delayed call to quit().

Go to the full post

Accessing file as resource

It is a common requirement having a file associated to an application, typically containing properties for its setup.

Let's see how adding and using such a resource file to a Qt C++ application when working with Qt Creator.

Qt stores the information for accessing resources in ancillary XML files identified by the qrc extension. Create a new resource file in Qt Creator is just a matter of creating a new file in the current project, of "Qt" type and "Qt Resource file" specification. Once a resource file is created, we see it in the Resources section of the project.

In the XML file the resources are organized in a structure where is kept the prefix, mimicking the file system structure with the application home directory identified by "/", and the actual file name.

I create a text file named "input.txt" in the home directory for my application, and then I create a textFinder.qrc resource file in my application, and I add, under the home prefix "/" the file "input.txt" I just created. If I open the file with a text editor I see it now contains this XML:
<RCC>
<qresource prefix="/">
<file>input.txt</file>
</qresource>
</RCC>

If I check the project file for my application, I'll see that Qt Creator has added a new section for resources:
RESOURCES += \
textFinder.qrc

Here is a function that uses this resource file:
void MainWindow::loadTextFile()
{
QFile fInput(":/input.txt"); // 1.
fInput.open(QIODevice::ReadOnly); // 2.

QTextStream sin(&fInput); // 3.
QString line = sin.readAll(); // 4.
fInput.close(); // 5.

ui->textEdit->setPlainText(line); // 6.
}

1. QFile ctor accepts as input the file name to be accessed. In this case we want to access a resource, to let it know that to QFile, we prefix the name with a colon ':'.
2. A file could be opened in a few different modes. Here we choose to open it only for reading.
3. We create a textual stream referring to our file handler, and we use it to read from it in memory.
4. Since our file is small, it makes sense to read it all and putting its content in a single string. QTextStream provides another function, readLine(), that gets just one line.
5. It is a good idea to explicitly close a file when we are done with it. In any case, the QFile dtor close it implicitly.
6. This is a GUI application, with form created by Qt Creator. Here I am accessing the textEdit component I have previously put in the form associated to this (main) window. This component is of type QTextEdit, we call on it a method, setPlainText(), to reset its content.

This post is based on the article Creating a Qt C++ Application from the official Qt Reference Documentation for Qt Creator 2.1.

Go to the full post

Qt vs. Comodo

Qt and Comodo don't get along together smoothly. Not a big surprise after all, since one strive to have control of the machine, and the other would like to stop anyone to do anything that looks even just a bit suspicious to it.

I have got a lot of complaining from Comodo while installing the new Qt SDK 1.1 (still a Release Candidate, currently) but nothing terrible.

The real issue came up when I tried to debug a little silly application of mine: I couldn't even reach the main(), and I got was a segmentation fault instead.

After a while of messing around, I got the feeling that it could be caused by a conflict at system level with some other smart guy on my machine. Comodo was the first suspect, and luckily it was also the culprit. Instead of getting in the dirty details, I'll pass you a link to a discussion in the Comodo forum, GDB problem solved!, where you could find a solution, and probably ask for more info, if you need them.

Go to the full post

Showing a table with a foreign key

Let's say we have a database table with a foreign key, like the department table I've described in this post.

Hardly what we really want is showing to the user the foreign key value. That makes little o no sense at all to him. In the current case, instead of seeing the numeric value representing the id of the location where the department insist, it would be better to see the name of the that location.

Luckly it is easy to do that with Qt: instead of using a QSqlTableModel we have to refer to the QSqlRelationalTableModel. Besides, we can do even something more interesting: giving the user the chance to see all the available choices for that field in a drop down list. Especially useful when we want to give the user to change the foreign key value.

Let's see the code for showing the department table to the user:

QSqlRelationalTableModel* departmentModel = new QSqlRelationalTableModel(this);
departmentModel->setTable("department");
departmentModel->setRelation(Department_LocationId, QSqlRelation("location", "id", "name")); // 1.
departmentModel->setSort(Department_Name, Qt::AscendingOrder);
departmentModel->setHeaderData(Department_Name, Qt::Horizontal, tr("Dept."));
departmentModel->setHeaderData(Department_LocationId, Qt::Horizontal, tr("Location"));
departmentModel->select();

ui->viewDept->setModel(departmentModel); // 2.
ui->viewDept->setItemDelegate(new QSqlRelationalDelegate(this)); // 3.
ui->viewDept->setSelectionMode(QAbstractItemView::SingleSelection);
ui->viewDept->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->viewDept->setColumnHidden(Department_Id, true);
ui->viewDept->resizeColumnsToContents();
ui->viewDept->horizontalHeader()->setStretchLastSection(true);
1. calling setRelation() we specify how to manage the foreign key. We are telling the model that instead of the location id we should go to the location table, using its id column as index and name as the actual field we want displaying.
2. viewDept is the QTableView where we are about to display the department table. Here we specify that we should use the departmentModel just created as source for the data.
3. specifying the usage of a new QSqlRelationalDelegate we are saying to the view that we want show to the user a drop down list with available choices for that field.

I wrote this post while reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield.

Go to the full post

The application icon

For windows this is what you have to do for having an icon associated with your application:

1. put your icon file, called something like myappico.ico, in your project source folder.

2. create a resource file, named something like myapp.rc, in the source folder.

That would be a plain text file containing just one line, something like this:

IDI_ICON1 ICON DISCARDABLE "myappico.ico"

3. in your myapp.pro, or whatever is its name, file add a line stating that it has to refer to the just created .rc file:

RC_FILE = myapp.rc

Recompile, and now your application should be associated to your new icon.

Go to the full post

Three tables for employees

As preparation for a few examples we are about to explore in the Qt database support area, I had to create three MySql tables that could be worthy to examine with a certain details.

The idea is that we are storing data for managing employees' information. We just need to keep track of the guy name, extension phone number, email, start working date, and department id.

The department id would be the foreign key that gives us access to the department table, where, besides its id, a couple of other information are stored for the department, that is its name and the location id.

This location id would be, again, a foreign key to another table, the location one, where we are about to store the id and the name od the location.

This structure will allow us to manage the employees of a firm having a few departments in different locations.

Let's see how I implemented that for MySql.

The location table is quite simple:
CREATE TABLE test.location
(
 id INTEGER PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(40) NOT NULL UNIQUE
);
The location should be specified and can't be duplicated, the id has not to be necessary provided by the user, if not specified would be MySql to take care to generate a valid value for it, by auto incrementation.

A bit more interesting the department table:
CREATE TABLE test.department 
(
  id            INTEGER PRIMARY KEY AUTO_INCREMENT,
  name          VARCHAR(40) NOT NULL UNIQUE,
  location_id   INTEGER NOT NULL,
  CONSTRAINT fk_loc_id FOREIGN KEY(location_id) REFERENCES test.location (id)
);
The point of interest here is that the location id has a constraint, a foreign key that estabilish a connection to the location id. That means that the department location_id value should match the value of an existing location id.

The other way round, the fact that location id is a foreign key for the department location_id implies that we can't change it if this would result in a broken connection between tables.

The employee table has a bit more meat, but there is not much to say more about it:
CREATE TABLE test.employee 
(
  id              INTEGER PRIMARY KEY AUTO_INCREMENT,
  name            VARCHAR(40) NOT NULL,
  department_id   INTEGER NOT NULL,
  extension       INTEGER NOT NULL,
  email           VARCHAR(40) NOT NULL UNIQUE,
  startdate       DATE NOT NULL,
  CONSTRAINT fk_dep_id FOREIGN KEY(department_id) REFERENCES test.department (id)
);
Here is department_id that is connected to the id of the department table by a foreign key relation. It is assumed that could exist more than an employee with the same name, but in any case the email should be unique.

I wrote this post while reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield. They create their tables for SQLite 3 that uses a SQL dialect that has a few difference with the one used by MySql 5.

Go to the full post

QSqlQuery and QSqlTableModel

Once we have established a connection to a database is quite easy to perform operations on its tables.

Qt let us do it in two ways: through QSqlQuery and QSqlTableModel.

The first way makes direct usage of SQL statements: we create a QSqlQuery object, execute a SQL query on it, and check the result.

For instance, to perform a select we could do something like that:
QSqlQuery query;
query.exec("SELECT sku, name, price FROM products WHERE price < 3");

if(query.isActive() == false) // 1.
    qDebug("Database error: %s", query.lastError().text().toStdString().c_str());

while(query.next()) // 2.
{
    QString sku = query.value(0).toString();
    QString name = query.value(1).toString();
    double price = query.value(2).toDouble();

    qDebug("%s %s: %f", sku.toStdString().c_str(), name.toStdString().c_str(), price);
}
1. the flag active is set to false in case of error
2. the result of performing a select is populating the query resultset. Its next() method allows us to navigate in it.

To perform an insert we write code like this:
QSqlQuery query;
query.exec("INSERT INTO products (id, sku, name, price) "
            "VALUES (42, 'X42', 'Something wierd', 2.02)");
if(query.numRowsAffected() == -1)
{
    qDebug("Database error: %s", query.lastError().text().toStdString().c_str());
}
If the number of affected rows is -1 that means an error occurred.

It is possible to prepare a query and then binding the values on the prepared statement, using both the Oracle and the ODBC syntax.

Using QSqlTableModel we can avoid the direct usage of raw SQL statements, letting Qt to generate the actual SQL code accordingly to the database we are using.

For instance, to execute the same select as above we can write something like this:
QSqlTableModel model;
model.setTable("products");
model.setFilter("price < 3");
model.select();

for(int i = 0; i < model.rowCount(); ++i)
{
    QSqlRecord record = model.record(i);

    int id = record.value(0).toInt();
    QString sku = record.value(1).toString();
    QString name = record.value(2).toString();
    double price = record.value(3).toDouble();

    qDebug("%d %s %s: %f", id, sku.toStdString().c_str(), name.toStdString().c_str(), price);
}

I wrote this post while reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield.

Go to the full post

Qt and MySql

I have to use Qt and MySql. This is not exactely a piece of cake, expecially the first time you do that, because there is a number of prerequisite to be filled out before actually start programming.

You should have Qt and MySql installed and working on your machine - but, well, this is quite a natural requirement.

Then you have to build the plugin for MySql. This has to be done for any database you want to use with Qt but SQLite, that is provided by default with Qt.

Building a database plugin is not difficult, but imply a different procedure for each database and platform. Luckly it is well described in the official documentation.

I found that compiling and using a database plugin is a sensitive process, probabily the fact is that we have to work with specific concepts for an operating system, a compiler, a database, all of these viewed from the point of view of the Qt framework. An inerently complex environment, I reckon. So, I was not surprised my plugin did not working at first try. The Qt framework is not very helpful in let you know which is the actual problem, and why it does not like our beautiful plugin, but after a while you should usually get the point and make it working properly.

A few suggestions if you are stuck somewhere in the process: check if the database is properly installed and the required files are available to your compiler. Check if the plugin was correctly created (in the Qt plugins/sqldrivers folder). Check if the dependecies for the generated DLL are available. For Windows-Visual C++ you could use the utility depends.exe (Dependency Walker) to find that out. If you have a problem of this kind, usually is LibMySql.ddl that is not in a PATH visible from your environment.
Another DLL that is often reported missing, IESHIMS.DLL, actually is not a mandatory one, so you don't usually have to pay attention to it.

Done that, you are ready for writing code for accessing your database from Qt.

Fist thing: you have to tell to your project you are actually using the Qt database facility. This is done in the project (.pro) file, adding the word "sql" to the QT property, that should look something like that:

QT += core gui sql

If our mysql database is not up and running, well, it is better to start it up. If you are on Windows and you want do that by shell command remember you need to have the administrator rights to do that. So open your cmd shell window as administrator before giving the "net start mysql" command.

At this point, opening a connection to the database is not anymore a big issue.

Accordingly to Jasmin and Mark, this is typically done in the application main function. I wouldn't stress much this point, and I just would say that is good enough for us to do that there.

It's only a toy connection, so we don't pay much attention to security, reusability and other issues like those, and so we just write this simple function:

bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setDatabaseName("test");
db.setUserName("root");
db.setPassword("password");
if(db.open() == false)
{
QMessageBox::critical(0, QObject::tr("Database Error"), db.lastError().databaseText());
return false;
}
return true;
}

It is worth noting that we specify the database brand calling the QSqlDatabase::addDatabase() static function, and then, after setting the usual parameters required for estabilishing a connection, we try to open it.

This function is used in this way:

#include <QtGui/QApplication>
#include <QtGui/QMessageBox>
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlError>

#include "MainWindow.h"

namespace
{
bool createConnection()
{
// ...
}
}

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

if(createConnection() == false)
return 1;

MainWindow mw;
mw.show();

return app.exec();
}

I wrote this post while reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield.

Go to the full post

Item views

The chapter 10 of C++ GUI Programming with Qt 4, Second Edition is dedicated to the classes used for displaying data in Qt.

Basically, there are two families of classes that couls be used for this task, the *Widget (QListWidget, QTableWidget, QTreeWidget) ones are simpler, and require to be feeded with the items we want to show to the user. The data are owned directly by the class.

The *View classes (QListView, QTableView, QTreeView) use a more modern approach. It's a sort of Model-View-Controller (MVC) schema slightly modified to make lighter the Controller module - here called "Delegate". The Model takes care of the data management, the View is responsible for making the data available to the user, the Delegate make possible a custom control on the View using the Model. Usually, if our client require a "normal" behavior, we don't need to mess about with the delegate, since a default one would suffice.

I suggest you reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield for more details on the matter.

Go to the full post

Ticker: timer event

In the chapter seven of C++ GUI Programming with Qt 4, Second Edition is described a custom widget, named Ticker, used for showing how to use timer events.

I have used it as central widget in my simple test application, where originally I put a QLabel and, well, it works fine.

Its idea is that it contains a text, and the id of a timer. The timer is started and stopped when the ticker is showed and hidden. Any time a Timer event, for the current ticker timer, reach the ticker itself the text is scrolled on the left.

To use the ticker as central widget in my application I used this piece of code:
Ticker* pTicker = new Ticker(this);
pTicker->setText(hello);
QMainWindow::setCentralWidget(pTicker);
And this is the Ticker class definition:
#ifndef TICKER_H
#define TICKER_H

#include <QWidget>

class Ticker : public QWidget
{
Q_OBJECT
public:
  explicit Ticker(QWidget* parent = 0);

  void setText(const QString& text);
  QString text() const { return text_; }

protected:
  void paintEvent(QPaintEvent*);
  void timerEvent(QTimerEvent* event);
  void showEvent(QShowEvent*);
  void hideEvent(QHideEvent*);

private:
  QString text_;
  int offset_;
  int timerId_;
};

#endif // TICKER_H

Notice that we have reimplemented four event handlers: show and hide will be used to start and stop the timer; timer for doing the actual job any ticked time; paint to redesign the widget any time is required.

Here is the implementation code for the class:
#include <QtGui>
#include "Ticker.h"

Ticker::Ticker(QWidget *parent) : QWidget(parent),
offset_(0), timerId_(0) // 1
{}

void Ticker::setText(const QString& text) // 2
{
  text_ = text;
  update();
  updateGeometry();
}

void Ticker::paintEvent(QPaintEvent*) // 3
{
  QPainter painter(this);

  int textWidth = fontMetrics().width(text_);
  if (textWidth < 1)
    return;
  int x = -offset_;
  while (x < width())
  {
    painter.drawText(x, 0, textWidth, height(), Qt::AlignLeft | Qt::AlignVCenter, text_);
    x += textWidth;
  }
}

void Ticker::showEvent(QShowEvent *) // 4
{
  timerId_ = startTimer(30);
}

void Ticker::timerEvent(QTimerEvent *event) // 5
{
  if(event->timerId() == timerId_)
  {
    ++offset_;
    if(offset_ >= fontMetrics().width(text_))
      offset_ = 0;
    update();
  }
  else
    QWidget::timerEvent(event);
}

void Ticker::hideEvent(QHideEvent*) // 6
{
  killTimer(timerId_);
  timerId_ = 0;
}

1. the offset is going to change to draw the text any time in a different position, giving the impression of a scrolling text; the timer id is set initially to zero because this means "no timer", that is exactely what we want.
2. when the user sets a text in the ticker we call update(), that is going to generate a repaint event, and updateGeometry(), to ensure the text is displayed as correctly as possible.
3. the handler for Paint event uses a QPainter object to put in the widget as many copy of the Ticker's text as required to fill its width. Notice that anytime it starts too much on the left (-offset_) giving the idea that the text is scrolling.
4. when the Ticker widget becomes visible, the timer is started, with a period of 30 milliseconds.
5. since there could be many active timer, before doing anything in the timeEvent() we should ensure that the timer id for the current event is the same of the stored timer for the Ticker. If this is the case, we increase the current offset - but when it reaches the size of the text, we reset it to zero - and then call update() to notify that we require the widget to be repainted. This will generate a Paint event, and so the scrolling of the text using the new offset.
6. when the Ticker is not visible we kill the timer. Notice that the timer functionality are part of the QObject interface.

I suggest you reading "C++ GUI Programming with Qt 4, Second Edition" by Jasmin Blanchette and Mark Summerfield for more details on the matter.

Go to the full post