![]() |
Главная · Все классы · Основные классы · Классы по группам · Модули · Функции | ![]() |
Qt Designer значительно изменился в выпуске Qt 4. Мы изменили точку зрения о Qt Designer как об IDE и сосредоточились на создании надёжного построителя форм, который может быть расширен и встроен в существующие IDE. Наши усилия не прекращаются и включают Visual Studio Integration, а также интеграцию Designer с KDevelop и возможно другими IDE.
Наиболее важные изменения в Qt Designer 4, которые оказывают воздействие на .ui-файлы подытожены ниже:
Остальная часть этого документа объясняет, как рассматривать основные отличия между Qt Designer 3 и Qt Designer 4:
Для получения дополнительной информации о портировании с Qt 3 на Qt 4 смотрите Портирование на Qt 4 и qt3to4 - Инструмент портирования с Qt 3 на Qt 4. Смотрите также Руководство по Qt Designer.
В Qt 3 uic генерирует заголовочный файл и реализацию класса, которые унаследованы от одного из виджетов Qt. Чтобы использовать форму, программист включает сгенерированные исходные коды в приложение и создаёт экземпляр класса.
В Qt 4 uic создаёт заголовочный файл, содержащий POD класса. Имя этого класса - имя объекта главного контейнера, уточнённого с пространством имён Ui (например, Ui::MyForm). Класс, реализованный с использованием inline-функции, устраняет необходимость в отдельном файле .cpp. Как и в Qt 3 этот класс содержит указатели на все виджеты внутри формы как открытые члены. Кроме того, сгенерированный класс предоставляет открытый метод setupUi().
Класс, сгенерированный uic, не является QWidget; фактически, это даже не QObject. Взамен, это класс, который знает как заполнить экземпляр главного контейнера с содержимым формы. Программист создаёт сам главный контейнер, затем передаёт его setupUi().
Например, здесь вывод uic для простой формы helloworld.ui (некоторые детали были удалены для простоты):
namespace Ui { class HelloWorld { public: QVBoxLayout *vboxLayout; QPushButton *pushButton; void setupUi(QWidget *HelloWorld) { HelloWorld->setObjectName(QString::fromUtf8("HelloWorld")); vboxLayout = new QVBoxLayout(HelloWorld); vboxLayout->setObjectName(QString::fromUtf8("vboxLayout")); pushButton = new QPushButton(HelloWorld); pushButton->setObjectName(QString::fromUtf8("pushButton")); vboxLayout->addWidget(pushButton); retranslateUi(HelloWorld); } }; }
В этом случае, главным контейнером был задан QWidget (или любой подкласс QWidget). Мы начали с шаблона QMainWindow в Qt Designer, тип параметра setupUi()'а будет QMainWindow.
Имеется два способа создания экземпляра нашей формы. Один подход - создать экземпляр класса Ui::HelloWorld, экземпляр главного контейнера (простой QWidget) и вызвать setupUi():
#include <QApplication>
#include <QWidget>
#include "ui_helloworld.h" // defines Ui::HelloWorld
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget w;
Ui::HelloWorld ui;
ui.setupUi(&w);
w.show();
return app.exec();
}
Второй подход - унаследовать и от класса Ui::HelloWorld и от главного контейнера, а также вызвать setupUi() в конструкторе подкласса. В этом случае, QWidget (или один из его подклассов, например, QDialog) должен появиться сначала в списке базовых классов, поэтому moc примет его правильно. Например:
#include <QApplication>
#include <QWidget>
#include "ui_helloworld.h" // defines Ui::HelloWorld
class HelloWorldWidget : public QWidget, public Ui::HelloWorld
{
Q_OBJECT
public:
HelloWorldWidget(QWidget *parent = 0)
: QWidget(parent)
{ setupUi(this); }
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
HelloWorldWidget w;
w.show();
return app.exec();
}
Этот второй метод полезен при портировании форм Qt 3 на Qt 4. HelloWorldWidget - класс, чей экземпляр является действительной формой и который содержит открытые указатели на все виджеты. По этой причине он имеет интерфейс, идентичный имеющемуся в классе, сгенерированном uic в Qt 3.
Создание классов POD из .ui-файлов - более гибкий и общий способ, чем старый подход создания виджетов. Qt Designer не нужно знать что-либо о главном контейнере отдельно от базового класса виджета, от которого он унаследован. Действительно, Ui::HelloWorld может использоваться для заполнения любого контейнера, который унаследован от QWidget. И наоборот, все не имеющие отношения к ГПИ аспекты главного контейнера могут быть реализованы программистом в исходных кодах приложения без ссылки на форму.
Вместе с Qt 4 идёт инструмент uic3 для работы со старыми .ui-файлами. Его можно использовать двумя способами:
Вы можете использовать оба эти метода в сочетании для получения .ui, заголовочные файлы и файлы исходного кода, которые вы можете использовать в качестве отправной точки при портировании вашего пользовательского интерфейса Qt 4.
Первый метод генерирует заголовок в стиле Qt 3 и реализацию, которая использует виджеты Qt 4 (это включает классы совместимости с Qt 3 в библиотеке Qt3Support). Этот процесс легко узнаваем для всех, использующих для работы Qt Designer 3:
uic3 myform.ui > myform.h uic3 -impl myform.h myform.ui > myform.cpp
Получившиеся файлы myform.h и myform.cpp реализуют форму в Qt 4, используя QWidget, который включает в себя пользовательские сигналы, слоты и соединения заданные в .ui-файле. Тем не менее, смотрите ниже ограничения этого метода.
Второй метод - использовать uic3 для конвертации .ui-файла Qt Designer 3 в формат Qt Designer 4:
uic3 -convert myform3.ui > myform4.ui
Получившийся файл myform4.ui можно редактировать в Qt Designer 4. Заголовочный файл для формы генерируется uic Qt 4. Смотрите главу Использование компонентов в вашем приложении Руководства по Qt Designer для информации о предпочтительных способах использования форм, созданных с помощью Qt Designer 4.
uic3 старается отобразить классы Qt 3 и их свойства на Qt 4. Однако, в Qt 4 поведение некоторых классов значительно изменилось. Чтобы сохранить форму работающей, некоторые классы Qt 3 отображаются на классы в библиотеке Qt3Support. Таблица 1 показывает список классов, на которые это распространяется.
Класс в Qt 3 | Класс в Qt 4 |
---|---|
QButtonGroup | Q3ButtonGroup |
QDateEdit | Q3DateEdit |
QDateTimeEdit | Q3DateTimeEdit |
QGroupBox | Q3GroupBox |
QListBox | Q3ListBox |
QListView | Q3ListView |
QMainWindow | Q3MainWindow |
QTextEdit | Q3TextEdit |
QTextView | Q3TextView |
QTimeEdit | Q3TimeEdit |
QWidgetStack | Q3WidgetStack |
QWizard | Q3Wizard |
Конвертирование .ui-файлов Qt 3 на Qt 4 имеет некоторые ограничения. Большинство достойных внимания ограничений фактически заключаются в том, что так как uic больше не генерирует QObject, то невозможно определить пользовательские сигналы или слоты для формы. Взамен, программист должен определить эти сигналы и слоты в главном контейнере и соединить их с виджетами на форме после вызова setupUi(). Например:
class HelloWorldWidget : public QWidget, public Ui::HelloWorld { Q_OBJECT public: HelloWorldWidget(QWidget *parent = 0); public slots: void mySlot(); }; HelloWorldWidget::HelloWorldWidget(QWidget *parent) : QWidget(parent) { setupUi(this); QObject::connect(pushButton, SIGNAL(clicked()), this, SLOT(mySlot())); } void HelloWorldWidget::mySlot() { ... }
Небрежный способ портирования форм, содержащих пользовательские сигналы и слоты, - генерация кода используя uic3, а не uic. Так как uic3 генерирует QWidget, он заполняет его пользовательским сигналам, слотам и соединениям указанным в .ui-файле. Однако uic3 может генерировать только код из .ui-файлов Qt 3, которые подразумевают что .ui-файлы никогда не получают перевод и нужно редактировать используя Qt Designer 3.
Обратите также внимание на то, что можно создать скрытые соединения между виджетами в форме и главном контейнере. После заполнения setupUi() главного контейнера с дочерними виджетами она просматривает список слотов главного контейнера в поисках имён с формой on_objectName_signalName().
Если форма содержит виджет, чьё имя объекта - objectName, и если этот виджет имеет сигнал с именем signalName, тогда этот сигнал будет соединён со слотом главного контейнера. Например:
class HelloWorldWidget : public QWidget, public Ui::HelloWorld { Q_OBJECT public: HelloWorldWidget(QWidget *parent = 0); public slots: void on_pushButton_clicked(); }; HelloWorldWidget::HelloWorldWidget(QWidget *parent) : QWidget(parent) { setupUi(this); } void HelloWorldWidget::on_pushButton_clicked() { ... }
Из-за соглашения об именовании setupUi() автоматически соединяет сигнал pushButton'а, clicked(), со слотом HelloWorldWidget'а, on_pushButton_clicked().
В Qt 3 двоичные данные для пиктограмм используются в форме сохраняются в .ui-файл. В Qt 4 пиктограммы и любые другие внешние файлы могут быть скомпилированы в приложение перечислив их в файле ресурсов (.qrc). Этот файл преобразовывается в файл исходных кодов C++ используя компилятор ресурсов Qt (rcc). После этого данные в файлах доступны для любого класса Qt, который получает аргумент с именем файла.
Представьте себе, что у нас есть две пиктограммы, yes.png и no.png. Мы создаём файл ресурсов с именем icons.qrc со следующим содержимым:
<RCC version="1.0"> <qresource prefix="/icons"> <file>yes.png</file> <file>no.png</file> </qresource> </RCC>
Далее, мы добавляем файл ресурса в наш .pro-файл:
RESOURCES += icons.qrc
Когда запущен qmake, он создаст соответствующие правила Make-файла для вызова rcc с файлом ресурсов, и компилирует и линкует результат в приложение. Доступ к пиктограммам можно получить как изложено ниже:
QFile file(":/icons/yes.png"); QIcon icon(":/icons/no.png"); QPixmap pixmap(":/icons/no.png");
В каждом подобном случае, ведущее двоеточие сообщает Qt искать файл в виртуальном дереве файлов, описанном набором файлов ресурсов, скомпилированных в приложение вместо файловой системы.
В файле .qrc, атрибут тега qresource, prefix, используется для размещения файлов по категориям и установки виртуального пути, по которому будут доступны файлы.
Предупреждение: Если файл ресурса не был слинкован непосредственно в приложение, а вместо этого в динамическую или статическую библиотеку, которая позднее линкуется с приложением, его виртуальное дерево файлов не будет доступно для QFile и его друзей, пока не вызван макрос Q_INIT_RESOURCE(). Этот макрос принимает один аргумент, которым является имя файла .qrc, без пути или расширения файла. Удобным местом для инициализации ресурсов является верхняя часть функции main() приложения.
В Qt Designer 4 мы можем связать любое количество файлов ресурсов с формой, используя инструмент редактора ресурсов. Виджеты в форме могут получить доступ ко всем пиктограммам, указанным в соответствующих файлах ресурсов.
Вкратце, портирование пиктограмм из Qt 3 на форму Qt 4 приводит к следующим шагам:
Qt Designer 3 поддерживает определение пользовательских виджетов указанием их имён, заголовочного файла и методов. В Qt Designer 4 пользовательский виджет всегда создаётся "продвигая" существующий виджет Qt в пользовательский класс. Qt Designer 4 принимает, что пользовательский виджет будет унаследован от виджета, который был продвинут. В редакторе форм, пользовательский виджет будет помнить внешний вид, поведение, свойства, сигналы и слоты базового виджета. В настоящее время невозможно сообщить Qt Designer 4 о том, что пользовательский виджет будет иметь дополнительные сигналы и слоты.
uic3 -convert обрабатывает преобразование пользовательских виджетов в новый формат .ui, тем не менее все пользовательские сигналы и слоты будут потеряны. Кроме того, так как Qt Designer 3 никогда не знает о базовом классе пользовательского виджета, он берёт QWidget. Этого часто достаточно. Если нет, пользовательские виджеты вставляются в форму вручную.
Подключаемые модули пользовательских виджетов, которые содержат пользовательские виджеты, используемые в Qt Designer, сами должны быть портированы перед тем, как они могут быть использованы в формах, портированных с помощью uic3. Документ Портирование на Qt 4 содержит информацию об основных проблемах портирования, которые могут быть применены к коду самого пользовательского виджета, а глава Создание пользовательских виджетов для Qt Designer Руководства по Qt Designer описывает как можно собрать портированный виджет, чтобы он работал в Qt Designer 4.
Copyright © 2008 Trolltech | Торговые марки | Qt 4.3.5 |