Слот
Эти два слота завершают написание программы диалогового окна. Теперь мы можем создать файл
01 #include <QApplication>
02 #include "finddialog.h"
03 int main(int argc, char *argv[])
04 {
05 QApplication app(argc, argv);
06 FindDialog *dialog = new FindDialog;
07 dialog->show();
08 return app.exec();
09 }
Для компиляции этой программы выполните обычную команду
Для правильной работы
Классы с макросом
finddialog.o(.text+0x28): undefined reference to
'FindDialog::QPaintDevice virtual table'
(не определена ссылка на «виртуальную таблицу
FindDialog::QPaintDevice»)
finddialog.o: In function 'FindDialog::tr(char const*. char const*)':
/usr/lib/qt/src/corelib/global/qglobal.h:1430: undefined reference to
'FindDialog::staticMetaObject'
(В функции 'FindDialog::tr(…)' не определена ссылка на
'FindDialog::staticMetaObject')
Сообщения в Visual С++ выглядят следующим образом:
finddialog.obj : error LNK2001: unresolved external symbol
"public:~virtual int __thiscall MyClass::qt_metacall(enum QMetaObject::Call,int,void * *)"
(ошибка LNK2001: неразрешенная внешняя ссылка)
При появлении подобных сообщений снова выполните команду
Теперь выполните программу. Если клавиши быстрого доступа доступны на вашей платформе, убедитесь в правильной работе клавиш Alt+W, Alt+C, Alt+B и Alt+F. Для перехода с одного виджета на другой используйте клавишу табуляции Tab. По умолчанию последовательность таких переходов соответствует порядку создания виджетов. Эту последовательность можно изменить с помощью функции
Обеспечение осмысленного порядка переходов с одного виджета на другой с помощью клавиши табуляции и применение клавиш быстрого доступа позволяют использовать все возможности приложений тем пользователям, которые не хотят (или не могут) пользоваться мышкой. Тот, кто быстро работает с клавиатурой, также предпочитает иметь возможность полного управления приложением посредством клавиатуры.
В главе 3 диалоговое окно поиска будет использовано нами в реальном приложении и мы подключим сигналы
Подробное описание технологии сигналов и слотов
Механизм сигналов и слотов играет решающую роль в разработке программ Qt. Он позволяет прикладному программисту связывать различные объекты, которые ничего не знают друг о друге. Мы уже соединяли некоторые сигналы и слоты, объявляли наши собственные сигналы и слоты, реализовывали наши собственные слоты и генерировали наши собственные сигналы. Давайте рассмотрим этот механизм более подробно.
Слоты почти совпадают с обычными функциями, которые объявляются внутри классов С++ (функции—члены). Они могут быть виртуальными, они могут быть перегруженными, они могут быть открытыми (public), защищенными (protected) и закрытыми (private), они могут вызываться непосредственно, как и любые другие функции—члены С++, и их параметры могут быть любого типа. Однако слоты (в отличие от обычных функций—членов) могут подключаться к сигналам, и в результате они будут вызываться при каждом генерировании соответствующего сигнала.
• Оператор connect() выглядит следующим образом:
connect (
где
В приводимых ранее примерах мы всегда подключали разные слоты к разным сигналам. Существует несколько вариантов подключения слотов к сигналам.
• К одному сигналу можно подключать много слотов:
connect(slider, SIGNAL(valueChanged(int)),
spinBox, SLOT(setValue(int)));
connect(slider, SIGNAL(valueChanged(int)),
this, SLOT(updateStatusBarIndicator(int)));
При генерировании сигнала последовательно вызываются все слоты, причем порядок их вызова неопределен.
• Один слот можно подключать ко многим сигналам:
connect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));
connect(calculator, SIGNAL(divisionByZero()),
this, SLOT(handleMathError()));
Данный слот будет вызываться при генерировании любого сигнала.
• Один сигнал может соединяться с другим сигналом:
connect(lineEdit, SIGNAL(textChanged(const QString &)),
this, SIGNAL(updateRecord(const QString &)));
При генерировании первого сигнала будет также генерироваться второй сигнал. В остальном связь «сигнал — сигнал» не отличается от связи «сигнал — слот».
• Связь можно аннулировать:
disconnect(lcd, SIGNAL(overflow()),
this, SLOT(handleMathError()));
Это редко приходится делать, поскольку Qt автоматически убирает все связи при удалении объекта.
• При успешном соединении сигнала со слотом (или с другим сигналом) их параметры должны задаваться в одинаковом порядке и иметь одинаковый тип:
connect(ftp, SIGNAL(rawCommandReply(int, const QString &)),
this, SLOT(processReply(int, const QString &)));
• Имеется одно исключение, а именно: если у сигнала больше параметров, чем у подключенного слота, то дополнительные параметры просто игнорируются:
connect(ftp, SIGNAL(rawCommandReply(int, const QString &),
this, SLOT(checkErrorCode(int)));
Если параметры имеют несовместимые типы либо будет отсутствовать сигнал или слот, то Qt выдаст предупреждение во время выполнения программы, если сборка программы проводилась в отладочном режиме. Аналогично Qt выдаст предупреждение, если в сигнатуре сигнала или слота будут указаны имена параметров.
Метаобъектная система Qt
Одним из главных преимуществ средств разработки Qt является расширение языка С++ механизмом создания независимых компонентов программного обеспечения, которые можно соединять вместе, несмотря на то что они могут ничего не знать друг о друге.
Этот механизм называется
В стандартном языке С++ не предусмотрена динамическая поддержка метаданных, необходимых системе метаобъектов Qt. В Qt эта проблема решена за счет применения специального инструментального средства компилятора
Этот механизм работает следующим образом:
• макрос
• компилятор
• такие функции—члены класса
Все это выполняется автоматически при работе
До сих пор мы использовали сигналы и слоты только при работе с виджетами. Но сам по себе этот механизм реализован в классе
01 class Employee : public QObject
02 {
03 Q_OBJECT
04 public:
05 Employee() { mySalary = 0; }
06 int salary() const { return mySalary; }
07 public slots:
08 void setSalary(int newSalary);
09 signals:
10 void salaryChanged(int newSalary);
11 private:
12 int mySalary;
13 };
14 void Employee::setSalary(int newSalary)
15 {
16 if (newSalary != mySalary) {
17 mySalary = newSalary;
18 emit salaryChanged(mySalary);
19 }
20 }
Обратите внимание на реализацию слота
Быстрое проектирование диалоговых окон
Средства разработки Qt спроектированы таким образом, чтобы было приятно программировать «вручную» и чтобы этот процесс был интуитивно понятен; и нет ничего необычного в разработке всего приложения Qt на «чистом» языке С++. Все же многие программисты предпочитают применять визуальные средства проектирования форм, поскольку этот метод представляется более естественным и позволяет получать конечный результат быстрее, чем при программировании «вручную», и такой подход дает возможность программистам быстрее и легче экспериментировать и изменять дизайн.