Назад Содержание Вперед

Обработка событий

Для связывания событий, происходящий с объектами, и функций, предназначенных для обработки этих событий, в библиотеке Qt используется интересный механизм сигналов и слотов. Сигнал -- это сообщение о том, что произошло какое-либо событие, например, нажатие на кнопку или выбор пункта меню. Вся информация о событии сохраняется в полях экземпляра соответствующего класса. У сигнала есть источник (например, кнопка) и приёмник (объект, метод которого будет обрабатывать это событие). Слот -- это сама функция-обработчик события. Связь между всеми четырьмя перечисленными элементами задаётся с помощью метода connect (соединить):
bool QObject::connect (
    const QObject *sender,    // Источник события.
    const char *signal,       // Сигнал.
    const QObject *receiver,  // Объект-приёмник сигнала.
    const char *method,       // Функция-обработчик.
    Qt::ConnectionType type = Qt::AutoConnection
    ) const
Последний параметр определяет режим обработки: Qt::DirectConnection -- событие обрабатывается сразу; Qt::QueuedConnection -- событие ставится в общую очередь и будет обработано только после всех сообщений, уже имеющихся в этой очереди; Qt::AutoConnection -- если источник события находится в том же потоке, что и приёмник, то будет использован режим Qt::DirectConnection, в противном случае -- Qt::QueuedConnection.

Для определения сигнала и слота используются макросы SIGNAL и SLOT. Например, мы хотим, чтобы текстовая метка label (экземпляр класса QLabel) отображала позицию полосы прокрутки scrollBar (экземпляр класса QScrollBar). В документации на библиотеку Qt (открыв doc/html/index.html или программу assistant) находим, что в классе QAbstractSlider, потомком которого является QScrollBar, определён сигнал

void QAbstractSlider::valueChanged ( int value )
оповещающий об изменении положения ползунка полосы прокрутки. Далее, в описании класса QLabel находим, что изменение текста надписи производится с помощью функции setText(строка) или setNum(число). Тогда вызов метода connect должен выглядеть следующим образом:
QObject::connect(
    scrollBar,                 // Источник события.
    SIGNAL(valueChanged(int)), // Сигнал.
    label,                     // Объект-приёмник сигнала.
    SLOT( setNum(int) ) );     // Функция-обработчик.
Заметим, что параметрами сигнала и слота являются типы, а не переменные.

Количество параметров слота всегда не больше количества параметров сигнала. Соответствие между ними, как обычно, позиционное: при выполнении программы значением i-го параметра слота становится значение i-го параметра сигнала.

В объявлении класса методы-слоты необходимо указывать в разделе public slots или private slots. Обычно в программе используются стандартные сигналы, но если требуется определить собственные, то их надо объявить в разделе signals. Например:

class MainWondow : public QMainWindow {
    Q_OBJECT
.............
signals:
    void mySignal();
private slots:
    void onMySignal();
.............

Сигнал может быть "соединён" с другим сигналом, например:

connect( myButton,
         SIGNAL( clicked() ),
         this,
         SIGNAL( buttonClicked() ) );

Один и тот же сигнал можно связать с несколькими слотами и/или другими сигналами. С одним и тем же слотом можно связать несколько сигналов. Можно указать несколько одинаковых "соединений": тогда одно событие вызовет генерацию нескольких сигналов.

Чтобы разорвать связь между сигналом и слотом, используется метод disconnect:

bool QObject::disconnect ( const QObject *sender,
                           const char *signal,
                           const QObject *receiver,
                           const char *method )  [static]

В листинге 5 приведён текст небольшой программы, иллюстрирующей принцип обработки нажатия на кнопку (экземпляр класса QPushButton), а на рис. показано, как выглядит окно программы в системе Windows.

Листинг 5 (файл examples-qt/01/01.cpp)

    1 // Сигналы и слоты: кнопка в окне
    2 
    3 #include <QApplication>
    4 #include <QPushButton>
    5 
    6 int main(int argc, char *argv[]) {
    7 
    8     QApplication app(argc, argv);
    9 
   10     QPushButton *button = new QPushButton(
   11         QString::fromLocal8Bit("&Выход") ); // Кнопка.
   12     button->setFont(QFont("Times", 16, QFont::Bold));
   13     QObject::connect(
   14         button,            // Источник сигнала.
   15         SIGNAL(clicked()), // Сигнал о нажатии кнопки.
   16         &app,              // Приёмник сигнала.
   17         SLOT( quit() ) );  // Функция-слот (обработчик события).
   18     button->show();
   19 
   20     return app.exec();
   21 }
Здесь мы разместили в окне обычную кнопку (10-11) с надписью "Выход" и связали её нажатие -- сигнал clicked (15) -- с функцией-обработчиком quit (17), которая завершает приложение app. Заметим, что мы не создаём главное окно для кнопки, это будет сделано автоматически (рис.).

Символ "&" перед буквой "В" в тексте надписи на кнопке (11) позволяет активировать её не только по щелчку левой кнопкой мыши или нажатием клавиши Enter, но также с помощью комбинации клавиш Alt+в (к сожалению, только в режиме ввода кириллицы).

Назад Содержание Вперед