Портирование файлов UI в Qt 4Qt 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-файлами. Его можно использовать двумя способами:
Вы можете использовать оба эти метода в сочетании для получения 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. Смотрите главу Использование UI-файла в вашем приложении Руководства по Qt Designer для информации о предпочтительных способах использования форм, созданных с помощью Qt Designer 4. uic3 старается отобразить классы Qt 3 и их свойства на Qt 4. Однако, в Qt 4 поведение некоторых классов значительно изменилось. Чтобы сохранить форму работающей, некоторые классы Qt 3 отображаются на классы в библиотеке Qt3Support. Таблица 1 показывает список классов, на которые это распространяется.
Ограничения 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 приводит к следующим шагам:
Пользовательские виджеты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. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |