Главная · Все классы · Основные классы · Классы по группам · Модули · Функции

Портирование файлов .ui в Qt 4

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.

Вывод uic

В 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. И наоборот, все не имеющие отношения к ГПИ аспекты главного контейнера могут быть реализованы программистом в исходных кодах приложения без ссылки на форму.

Работа с uic3

Вместе с Qt 4 идёт инструмент uic3 для работы со старыми .ui-файлами. Его можно использовать двумя способами:

  1. Для генерации заголовков и исходных кодов для виджета, чтобы реализовать любые пользовательские сигналы и слоты добавленные используя Qt Designer 3.
  2. Чтобы генерировать новый .ui-файл, который может быть использован с Qt Designer 4.

Вы можете использовать оба эти метода в сочетании для получения .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
QButtonGroupQ3ButtonGroup
QDateEditQ3DateEdit
QDateTimeEditQ3DateTimeEdit
QGroupBoxQ3GroupBox
QListBoxQ3ListBox
QListViewQ3ListView
QMainWindowQ3MainWindow
QTextEditQ3TextEdit
QTextViewQ3TextView
QTimeEditQ3TimeEdit
QWidgetStackQ3WidgetStack
QWizardQ3Wizard

Ограничения uic3

Конвертирование .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 приводит к следующим шагам:

  1. Используйте uic3 -convert чтобы получить .ui-файл, понятный Qt Designer 4.
  2. Создайте файл .qrc со списком всех файлов пиктограмм.
  3. Добавьте файл ресурса в .pro файл.
  4. Откройте форму в Qt Designer 4 и добавьте файл ресурсов в редактор ресурсов формы.
  5. Установите свойства пиктограмм для соответствующих виджетов.

Пользовательские виджеты

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