9.9.1. QTimer

[ fromfile: timers.xml id: timers ]

Section 9.9 shows an example that makes use of the QObject built-in timer. Qt also has the class QTimer, which provides a high-level interface for timers. A QTimer object is a countdown timer started with a time interval in milliseconds. When it reaches zero, it emits a timeout() signal.

A QTimer can be used to emit a timeout() signal at regular intervals or, if the singleShot property has been set to true, to emit a signal only once after a specified interval. QTimer has a static singleShot() function that calls a slot once after a given time interval. If the countdown interval is set to zero, the QTimer emits its timeout() signal as soon as all the events in the event queue have been processed.

The following example uses QTimer to write an application for training the user to read faster. The designers of this approach also claimed that it increases the user's reading comprehension. The idea is to briefly display a sequence of character strings, one at a time, and let the user try to type each string as soon as it is no longer visible. The user specifies the string length and the exposure time. The program compares the displayed string with the typed string and keeps score in some appropriate way. The user gradually increases the string length and decreases the exposure times to build a kind of strength in this realm which, presumably, translates into an enhanced ability to read text.

This application is relatively simple, as can be seen from the UML diagram Figure 9.25.

Figure 9.25. Speed-reader UML

Speed-reader UML

The class definition of MainWindow is shown in Example 9.17. You can see that several of its slots use naming conventions that enable QMetaObject::connectSlotsByName(MainWindow) to work properly. Those names were generated by QtCreator based on this convention – which is why you see no connect statements for them in the code.

Example 9.17. src/timer/speed-reader/mainwindow.h

[ . . . . ]
class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    explicit MainWindow(QWidget* parent = 0);
    ~MainWindow();
protected:
    void changeEvent(QEvent* e);
    void processTrial();
private:
    Ui::MainWindow* ui;
private slots:
    void on_nextButton_clicked();
    void on_responseString_returnPressed();
    void on_startButton_clicked();
    void on_lengthSlider_valueChanged(int value);
    void on_exposureSlider_valueChanged(int value);
    void timerDisplayRandStr();
private:
    int m_expInterval;
    RandomString m_randStr;
    int m_trials;
    int m_correctChars;
    int m_totTrials;
    int m_totCorrectChars;
};
[ . . . . ]

This application uses the static QTimer function singleShot() to control the exposure time for each random string. singleShot() sends a timeout() signal to the slot timerDisplayRandStr() after the slider-selected time interval elapses. processTrial(), shown in Example 9.18 shows the connect statements.

Example 9.18. src/timer/speed-reader/mainwindow.cpp

[ . . . . ]
void MainWindow::processTrial() {
    //clear response text editor
    ui->responseString->setText("");
    //display the random string
    ui->targetString->setText(m_randStr.generateString());
    ui->responseString->setEnabled(false);
    ui->nextButton->setEnabled(false);
    //count the number of trials
    m_trials++;
    m_totTrials++;
    ui->nextButton->setText(QString("String %1").arg(m_trials));
    //begin exposure
    QTimer::singleShot(m_expInterval, this, SLOT(timerDisplayRandStr()));
}


void MainWindow::timerDisplayRandStr() {
    ui->targetString->setText(QString(""));
    //enable the response line editor and next button
    ui->responseString->setEnabled(true);
    ui->responseString->setFocus();
    ui->nextButton->setEnabled(true);
}

[ . . . . ]

Figure 9.26 is a screenshot of the running program after the exposure time and string length have been selected.

Figure 9.26.  Speed Reader Screenshot

Speed Reader Screenshot