Литмир - Электронная Библиотека
Содержание  
A
A

На способы применения сигналов и слотов в Qt есть несколько ограничений, но они не слишком существенные:

□ сигналы и слоты должны быть функциями-методами класса-потомка

QObject
;

□ при использовании множественного наследования

QObject
должен быть первым в списке класса;

□ оператор

Q_OBJECT
должен появляться первым в объявлении класса;

□ сигналы нельзя применять в шаблонах;

□ указатели на функцию не могут использоваться как аргументы в сигналах и слотах;

□ сигналы и слоты не могут переопределяться или обновляться до статуса

public
(общедоступный).

Поскольку вы должны писать ваши сигналы и слоты как потомков объекта

QObject
, логично создавать ваш интерфейс, расширяя и настраивая виджет, начиная с
QWidget
, базового виджета Qt, потомка виджета
QObject
. В комплекте Qt вы почти всегда будете создавать интерфейсы, расширяя такие виджеты, как
QMainWindow
.

Типичное определение класса в файле MyWindow.h для вашего GUI будет напоминать приведенное далее:

class MyWindow : public QMainWindow {

 Q_OBJECT

public:

 MyWindow();

 virtual ~MyWindow();

signals:

 void aSignal();

private slots:

 void doSomething();

}

Ваш класс — наследник объекта

QMainWindow
, который определяет функциональные возможности главного окна в приложении. Аналогичным образом при создании диалогового окна вы определите подкласс
QDialog
. Первым указан оператор
Q_OBJECT
, действующий как метка для препроцессора, за которым следуют обычные объявления конструктора и деструктора. Далее даны определения сигнала и слота.

У вас есть один сигнал и один слот, оба без параметров. Для порождения сигнала

aSignal()
вам нужно всего лишь в любом месте программы вызвать функцию
emit
:

emit aSignal();

Это означает, что все остальное обрабатывается Qt. Вам даже не потребуется реализация

aSignal()
.

Для применения слотов их нужно связать с сигналом. Делается это соответствующим образом с помощью названного статического метода

connect
класса
QObject
:

<b>bool QObject::connect(const QObject * sender, const char* signal,</b>

<b> const QObject * receiver, const char * member);</b>

Просто передайте объект, владеющий сигналом (отправитель), функцию сигнала, объект, владеющий слотом (приемником), и в завершение укажите имя слота.

В примере MyWindow, если бы вы захотели связать сигнал

clicked
виджета
QPushButton
с вашим слотом
doSomething
, вы бы написали:

connect(button, SIGNAL(clicked()), this, SLOT(doSomething()));

Учтите, что необходимо применять макросы

SIGNAL
и
SLOT
для выделения функций сигналов и слотов. Как и в комплекте GTK+, вы можете связать ряд слотов с заданным сигналом и также связать слот с любым количеством сигналов с помощью множественных вызовов функции connect. Если она завершается аварийно, то возвращает
FALSE
.

Остается реализовать ваш слот в виде обычной функции-метода:

void MyWindow::doSomething() {

 // Код слота

}

Выполните упражнение 17.2.

Упражнение 17.2. Сигналы и слоты

Теперь, зная основы использования сигналов и слотов, применим их в примере. Усовершенствуйте

QMainWindow
, вставьте в него кнопку и свяжите сигнал кнопки
clicked
со слотом.

1. Введите следующее объявление класса и назовите файл ButtonWindow.h:

#include &lt;qmainwindow.h&gt;

class ButtonWindow : public QMainWindow {

 Q_OBJECT

public:

 ButtonWindow(QWidget *parent = 0, const char *name = 0);

 virtual ~ButtonWindow();

private slots:

 void Clicked();

};

2. Далее следует реализация класса в файле ButtonWindow.cpp:

#include &quot;ButtonWindow.moc&quot;

#include &lt;qpushbutton.h&gt;

#include &lt;qapplication.h&gt;

#include &lt;iostream&gt;

3. В конструкторе вы задаете заголовок окна, создаете кнопку и связываете сигнал нажатия кнопки с вашим слотом.

setCaption
— метод объектов типа
QMainWindow
, который, что неудивительно, задает заголовок окна:

ButtonWindow::ButtonWindow(QWidget *parent, const char* name) : QMainWindow(parent, name) {

 this-&gt;setCaption(&quot;This is the window Title&quot;);

 QPushButton *button = new QPushButton(&quot;Click Me!&quot;, this, &quot;Button1&quot;);

 button-&gt;setGeometry(50, 30, 70, 20);

 connect(button, SIGNAL(clicked()), this, SLOT(Clicked()));

}

4. Qt автоматически удаляет виджеты, поэтому ваш деструктор пуст:

ButtonWindow::~ButtonWindow() {}

5. Затем реализация слота:

void ButtonWindow::Clicked(void) {

 std::cout &lt;&lt; &quot;clicked!\n&quot;;

}

6. И наконец, в функции

main
вы просто создаете экземпляр типа
ButtonWindow
, делаете его главным окном вашего приложения и отображаете окно на экране:

int main(int argc, char **argv) {

 QApplication app(argc, argv);

 ButtonWindow *window = new ButtonWindow();

302
{"b":"285844","o":1}