Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

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: неразрешенная внешняя ссылка)

При появлении подобных сообщений снова выполните команду qmake для обновления файла makefile, затем заново постройте приложение.

Теперь выполните программу. Если клавиши быстрого доступа доступны на вашей платформе, убедитесь в правильной работе клавиш Alt+W, Alt+C, Alt+B и Alt+F. Для перехода с одного виджета на другой используйте клавишу табуляции Tab. По умолчанию последовательность таких переходов соответствует порядку создания виджетов. Эту последовательность можно изменить с помощью функции QWidget::setTabOrder.

Обеспечение осмысленного порядка переходов с одного виджета на другой с помощью клавиши табуляции и применение клавиш быстрого доступа позволяют использовать все возможности приложений тем пользователям, которые не хотят (или не могут) пользоваться мышкой. Тот, кто быстро работает с клавиатурой, также предпочитает иметь возможность полного управления приложением посредством клавиатуры.

В главе 3 диалоговое окно поиска будет использовано нами в реальном приложении и мы подключим сигналы findPrevious и findNext к некоторым слотам.

Подробное описание технологии сигналов и слотов

Механизм сигналов и слотов играет решающую роль в разработке программ Qt. Он позволяет прикладному программисту связывать различные объекты, которые ничего не знают друг о друге. Мы уже соединяли некоторые сигналы и слоты, объявляли наши собственные сигналы и слоты, реализовывали наши собственные слоты и генерировали наши собственные сигналы. Давайте рассмотрим этот механизм более подробно.

Слоты почти совпадают с обычными функциями, которые объявляются внутри классов С++ (функции—члены). Они могут быть виртуальными, они могут быть перегруженными, они могут быть открытыми (public), защищенными (protected) и закрытыми (private), они могут вызываться непосредственно, как и любые другие функции—члены С++, и их параметры могут быть любого типа. Однако слоты (в отличие от обычных функций—членов) могут подключаться к сигналам, и в результате они будут вызываться при каждом генерировании соответствующего сигнала.

Оператор connect выглядит следующим образом:

connect (отправитель, SIGNAL(сигнал), получатель, SLOT(слот));

где отправитель и получатель являются указателями на объекты QObject и где сигнал и слот являются сигнатурами функций без имен параметров. Макросы SIGNAL и SLOT фактически преобразуют свои аргументы в строковые

переменные.

В приводимых ранее примерах мы всегда подключали разные слоты к разным сигналам. Существует несколько вариантов подключения слотов к сигналам.

К одному сигналу можно подключать много слотов:

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 является расширение языка С++ механизмом создания независимых компонентов программного обеспечения, которые можно соединять вместе, несмотря на то что они могут ничего не знать друг о друге.

Этот механизм называется метаобъектной системой, и он обеспечивает две основные служебные функции: взаимодействие сигналов и слотов и анализ внутреннего состояния приложения (introspection). Анализ внутреннего состояния необходим для реализации сигналов и слотов и позволяет прикладным программистам получать «метаинформацию» о подклассах QObject во время выполнения программы, включая список поддерживаемых объектом сигналов и слотов и имена их классов. Этот механизм также поддерживает свойства (для Qt Designer) и перевод текстовых значений (для интернационализации приложений), а также создает основу для системы сценариев в Qt (Qt Script for Applications — QSA).

Поделиться с друзьями: