Руководства, Инструкции, Бланки

Qt Designer руководство img-1

Qt Designer руководство

Рейтинг: 4.1/5.0 (1830 проголосовавших)

Категория: Руководства

Описание

Глава 3

Создание приложения Создание проекта Создание в KDevelop базовой структуры приложения

Базовую структуру приложения (т.е. главное окно) можно легко и быстро создать при помощи KDevelop. Запустите KDevelop и в меню Project (Проект) выберите New Project (Создать проект). Появится мастер создания приложения. Выберите C++ => KDE => Simple KDE Application. Введите имя проекта (SigCreate), ваше имя и e-mail (рис. 1).

Нажмите Next (Далее), обратите внимание на опцию CVS и на шаблоны заголовков (они вставляются в начало каждого файла с исходным кодом). В последнем окне нажмите Finish (Готово). KDevelop создаст все файлы, необходимые для компиляции проекта. Вы можете использовать закладку File Selector (слева) для выбора файлов. Откройте 3 файла: main.cpp. sigcreate.cpp и sigcreate.h (рис. 2).

Когда мастер создания приложений закончит работу, вы можете убедиться, что все в порядке, скомпилировав приложение. Для этого выберите Build (Сборка) -> Run automake & friends. затем Build (Сборка) -> Run configure. В окне Messages (Сообщения) должно появиться следующее:

Теперь вы можете выполнить команду Build (Сборка) -> Build Project (или просто нажмите F8 ). Затем выполните команды Build (Сборка) -> Install (Установить) и Build (Сборка) -> Execute program (Запустить программу) (или F9 ). Результат показан на рис. 3.

Рис. 3: Простое приложение для KDE

Теперь, когда мы создали основу, можно начать разработку приложения.

Если KDevelop не распознает автоматически переменные окружения QTDIR и KDEDIR, определите их значения вручную в диалоге Project (Проект) => Project Options. => Configure Options.

Рис. 6: Параметры проекта

Работа с Qt Designer

Qt Designer — это программа для разработки пользовательского интерфейса программы. Она помогает вам расположить на форме элементы управления и создать макет формы, чтобы при изменении ее размеров виджеты располагались должным образом. Рекомендую вам прочитать Руководство по Qt Designer. чтобы узнать все о Qt Designer.

Qt Designer включает в себя редактор кода, но для этой цели мы все-таки будем использовать KDevelop.

Итак, сейчас мы создадим интерфейс приложения, используя Qt Designer. В Qt Designer формы сохраняются с расширением .ui, потому что затем эти файлы будут обработаны программой uic для создания файлов .cpp и .h. KDevelop сделает это за вас, поэтому все, что нам нужно — просто создать форму.

Замечание

Всякий раз, когда вы добавляете или удаляете файлы из проекта (мы добавим файл пользовательского интерфейса с расширением .ui), требуется изменить файл Makefile.am. KDevelop сделает это, но вам нужно будет выполнить команду Build (Сборка) => Run automake & friends.

Выберите в окне KDevelop пункт меню File => New (Файл => Создать) и введите необходимую информацию в появившемся окне диалога. Сначала введите в качестве имени файла sigcreatedlg и выберите тип файла в выпадающем списке. Сейчас нам потребуется создать файл типа Widget (.ui). Обязательно проверьте, отмечен ли флажок "Add to project" (Добавить в проект), иначе файл Makefile.am не будет обновлен.

Нажмите кнопку OK. Появится диалог Automake manager.

Нажмите кнопку ОК.

Если только что созданный sigcreatedlg.ui не был автоматически открыт в Qt Designer, откройте Automake Manager (закладка в правой части главного окна), щелкните на файле правой кнопкой мыши и выберите Open With (Открыть с помощью), и в появившемся меню выберите пункт Qt Designer.

Замечание об именах файлов

К имени файла .ui принято добавлять "dlg", чтобы облегчить чтение кода другим людям. sigcreatedlg обозначает, что этот файл — это класс интерфейса. Обычно имена классов KDE начинаются с заглавной буквы K, и затем следует имя, наиболее полно описывающее вашу программу. Если бы это было настоящее приложение для KDE, мне нужно было бы назвать этот класс KSigCreate.

Окно программы Qt Designer поделено на три части. С левой стороны находится список элементов управления. Справа могут находиться несколько диалогов; я же оставляю только диалог свойств Property Editor (закрыв два остальных). Здесь вы можете настроить внешний вид и поведение виджетов. Можно выбрать размер, цвет виджета и т.д. Посередине находится форма — окно вашего приложения. Здесь вы и разрабатываете интерфейс программы.

Замечание

После добавления в проект файла sigcreatedlg.ui вам нужно выполнить команду Build (Сборка) => Run Automake & friends и Run Configure. Иначе при компиляции программы изменения в файле Makefile.am не будут учтены.

Другие статьи

Qt - руководство для новичков - Qt

Qt - руководство для новичков - C++ Qt

Пожелания по улучшению данной статьи пишите сюда

1. Предисловие
2. Руководство 2.1. Создаем пустое окно.
2.2. Добавляем виджеты и редактируем их свойства.
2.3. Изменяем свойства виджетов из кода.
2.4. Настраиваем поведение формы.
2.5. Создаем обработчики событий.
2.6. Создаем свои сигналы.
2.7. Используем менеджеры компоновки.
3. FAQ 3.1. Что такое Qt ?
3.2. Что такое слот ?
3.3. Что такое сигнал ?
3.4. Что такое виджет ?
3.5. Как связать сигнал со слотом ?
3.6. Что такое менеджер компоновки ?
3.7. Какие книжки можно почитать ?
3.8. Какую IDE выбрать ?
3.9. Какие еще существуют варианты связывания сигналов и слотов.
3.10. Что такое отправитель сигнала ?
3.11. Что такое получатель сигнала ?
3.12. Где скачать Qt SDK ?
3.13. Где хранится форма, созданная в Qt Designer ?
3.14. Откуда установить Qt Libraries для других IDE ?
3.15. Как скомпилировать исходник без IDE в LInux ?
3.16. Как скомпилировать исходник без IDE в Windows ?
3.17. Где мне найти Assistant, Designer и прочие программы для Qt, и зачем они нужны ?
3.18. На каких языках можно писать программы с Qt ?
4. Решения часто возникающих проблем 4.1. В пути к папке с исходникам не должно быть русских букв.
4.2. Не найдены dll файлы. (в Windows`е)
4.3. При компиляции проекта возникает ошибка. (в Linux`е)
4.4. В пути к библиотеке Qt не должно быть русских букв.

1. ПРЕДИСЛОВИЕ

Целью данной статьи является помощь в совершении самого первого шага написания приложений посредством библиотеки Qt. Мы не будем пытаться научить читателя программировать под Qt, а только опишем порядок действий при создании простейшего приложения. Обусловлено это тем, что работа с Qt выглядит немного не так, как работа в коммерческих средах разработки от Microsoft или Borland. После того, как читатель на практике "пощупает" процесс создания приложения, после этого будет проще воспринимать литературу по программированию под Qt. При помощи данной статьи новичок научится создавать новый проект, редактировать свойства компонентов на форме визуально и из кода. Научится настраивать поведение формы, и создавать собственные обработчики событий. Практическая часть данного руководства описывает только Qt Creator. Стоит заметить, что данное руководство могут изучать как пользователи Windows, так и пользователи Linux и Mac OS, и других операционных систем, на которые можно установить Qt Creator. Все примеры программ, приведенные в этом руководстве, тестировались на Qt версии 4.5.2.

Благодарен за помощь в создании статьи Evg, Phantom, RazorQ, odip, oxotnik, cristaloleg, mik-a-el


2.1. Создаем пустое окно.

Исходник этого и всех остальных проектов можно найти здесь manual.zip
В этом этапе научимся создавать проект.

1) Скачайте QT SDK отсюда если у вас Windows. Если у вас другая операционная система, то загляните в FAQ, в "3.12. Где скачать Qt SDK ?" .
2) Установите Qt в папку, путь к которой не содержит русских букв. Иначе при компиляции будут возникать ошибки.
3) Запустите Qt Creator. Если вы установили Qt в папку по умолчанию, то путь к Creator`у в Windows`е будет выглядеть так C:\Qt\2009.05\bin\qtcreator.exe.
4) Создайте проект. Для этого щелкните File(Файл) => New(Новый) => Qt4 Gui Application(GUI приложение Qt4)
5) В поле Name(Название) напишите имя папки с проектом, пусть будет first, пишите английскими буквами. иначе могут быть проблемы при компиляции
6) В поле Create in(Создать в) введите путь к папке, в которой будет создана папка с именем, которое вы ввели в поле Name.
Внимание. В пути к папке с проектом тоже не должно быть русских букв !
7) В Class name(Имя класса) пишем MyWidget, в Base Class(Базовый класс) выбираем QWidget.
8) Сохраните проект, для этого щелкните File(Файл)=>SaveAll(Сохранить все). После каждого этапа сохраняйтесь.
9) Скомпилируйте программу, для этого щелкните Build(Сборка)=>Build All(Собрать все), вместо этого можно нажать на круглую кнопку с молотком в левом нижнем углу окна Qt Creator`a, (смотрите

).
10) Запустите программу. для этого щелкните Build(Сборка)=>Run(Выполнить), вместо этого можно нажать на круглую кнопку с треугольником в левом нижнем углу окна Qt Creator`a, (смотрите

)
11) Любуемся на пустое окно.
Примечание: если в Windows`е при попытке запустить написанную программу двойным щелчком по файлу выходит окно с ошибкой, то загляните в раздел 4.2.

2.2. Добавляем виджеты и редактируем их свойства.

Исходник этого и всех остальных проектов можно найти здесь manual.zip

Виджеты - визуальные объекты на форме, например кнопки, поля, меню. В этом этапе, а также во всех последующих, будет использовать один и тот-же проект. Если вы уже успели закрыть проект, то его надо сначала открыть. Чтобы это сделать, щелкните File(Файл)->Open(Открыть), в появившемся окне откройте файл *.pro вашего проекта.

1) Отредактируем форму, для этого надо сначала перейти в режим редактирования проекта. чтобы это сделать щелкните кнопку Edit (см.

). после этого откроем файл mywidget.ui двойным щелчком в окне на


2) Добавим на форму два поля редактирования, для этого перетащим с палитры компонентов на форму два Line Edit`a (он находится на вкладке Input Widgets, см.

)
3) Добавим на форму две кнопки, для этого перетащим на с палитры компонентова на форму для Push Button`a (он находится на вкладке вкладке Buttons)
4) Отредактируем имена кнопок и текстовых полей. Для этого выделите кнопку, и в инспекторе объектов (см.

) отредактируйте свойство objectName, пусть оно будет MyPushButton1. Таким-же образом отредактируйте имя имя второй кнопки, пусть оно будет MyPushButton2.
Таким-же образом отредактируйте имена Line Edit`ов. Пусть они будут MyLineEdit1 и MyLineEdit2.
5) Отредактируем надписи на кнопках и полях редактирования. Для этого выделите кнопку MyPushButton1 и в инспекторе объектов измените свойство text, пусть оно будет Copy. Таким-же образом измените свойство text кнопки MyPushButton2 пусть оно будет Clear.
Таким-же образом отредактируйте свойство text поля MyLineEdit1, пусть оно будет Source. Таким-же образом отредактируйте свойство text поля MyLineEdit2, пусть оно будет Destination.
6) Убедитесь что все правильно сделали. Посмотрите на форму: на одной кнопке должна быть надпись Copy, на другой Clear. В одном поле редактирования должен быть текст Source, в другом Destination.
7) Компилируем программу и любуемся.

Мы научились изменять свойства компонентов при помощи object inspector`а. Научились переименовывать компоненты и менять надписи на них.
-----------------------------------------------------------------------------------

2.3. Изменяем свойства виджетов из кода.

Исходник этого и всех остальных проектов можно найти здесь manual.zip

1) Добавим на форму метку. Для этого из палитры компонентов перетащим на форму компонент Label (он находится на вкладке Display Widgets). Переименуем его, для этого в инспекторе объектов в свойство objectName напишем MyLabel.
2) Увеличим нашу метку, чтобы в нее влез текст. Для этого схватим ее край мышкой и потянем вправо или влево, чтобы она стала шире.
3) Изменим из кода надпись на MyLabel. Для этого откроем файл mywidget.cpp. Там, в конструкторе класса MyWidget, после ui->setupUi(this); добавим строчку

Если вам надо, чтобы какой-нибудь код выполнялся при запуске программы, можете добавить его в конструктор класса MyWidget
------------------------------------------------------------------------------


2.4. Настраиваем поведение формы.

Исходник этого и всех остальных проектов можно найти здесь manual.zip

1) Сделаем. чтобы при нажатии на кнопку с надписью Clear. очищались поля. Для этого откроем Signals and slots editor (см.

). нажмем на крестик и в образовавшейся записи, в поле Sender (отправитель сигнала) выберем MyPushButton2. В поле Signal (сигнал) выберем Clicked(). В поле Receiver (получатель сигнала) выберерем MyLineEdit1. В поле Slot (слот) выберем Clear().
Еще раз нажмем на крестик, сделаем так-же как написано выше, только в поле Receiver выберем MyLineEdit2.
2) Скомпилируйте программу
3) Запустите программу, нажмите на кнопку Clear. Оба поля должны очистится.

Мы научились в окне Signals and slots editor подключать стандартные сигналы к стандартным слотам. Этим способом можно настроить поведение формы, не написав ни одной строчки кода. Это выгодно отличает Qt от C++ Builder`a и Delphi. Например, чтобы очищать поля по нажатию кнопки (в Delphi или C++ Builder`e, нам бы пришлось создавать обработчик нажатия кнопки, а в нем писать код, который будет очищать текстовые поля. А в Qt мы можем это сделать не загромождая исходник лишними обработчиками событий.
---------------------------------------------------------------------------------


2.5. Создаем обработчики событий.

Исходник этого и всех остальных проектов можно найти здесь manual.zip

1) Создадим прототип своего слота, для этого откроем файл mywidget.h. В конец класса добавим:

3.6. Что такое менеджер компоновки ?

это объект, который устанавливает размер и положение виджетов, которые располагаются в зоне его действия. Qt имеет три основных класса менеджеров компоновки:

• QHBoxLayout размещает виджеты по горизонтали слева направо (или справа налево, в зависимости от культурных традиций);

• QVBoxLayout размещает виджеты по вертикали сверху вниз;

3.7. Какие книжки можно почитать ?

Если обнаружите нерабочую ссылку, пишите сюда

3.8. Какую IDE выбрать ?

Существует много IDE с возможностью использования библиотеки Qt. например Eclipse, KDevelop (для Линукса), QDevelop. Но новичку лучше выбрать Qt SDK (http://ru.wikipedia.org/wiki/Qt_Creator ) т.к. в нем уже все есть для начала работы. Qt Assistant. Qt Designer - все это уже включено.
-----------------------------------------------------------------------

3.9. Какие еще существуют варианты связывания сигналов и слотов ?


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

3.14. Откуда установить Qt Libraries для других IDE ?

3.15. Как скомпилировать исходник без IDE в LInux ?

В Linux можно скомпилировать исходник без IDE, достаточно Qt Libraries. Все действия выполняются в консоли.
1) Перейдите в папку с исходниками программы командой cd, например cd /home/rnt/Desktop/first
2) Если у вас есть файл проекта *.pro, переходите к этапу 3. Если его нет, введите qmake -project
3) qmake имя_файла.pro. Например qmake mywidget.pro. Если в каталоге всего один проект, то можно вести только qmake
4) Введите make
В папке с исходниками должен появится исполняемый файл.
-----------------------------------------------------------------------

3.16. Как скомпилировать исходник без IDE в Windows ?

В Windows можно скомпилировать исходник без IDE, достаточно Qt Libraries и Mingw. Прежде всего надо прописать в переменную окружения Path пути к библиотеке Qt и компилятору Mingw.
Делается это так(в Win XP): заходите в Панель Инструментов=>Система=>Дополнительно=>Переменные окружения. Там выберите переменную Path и
отредактируйте ее: добавьте, через знак "точка с запятой", C:\Qt\2009.03\qt\bin (у вас может
быть по другому), и C:\Qt\2009.03\mingw\bin. Сохраните. Далее открываете консоль и:

1) Перейдите в папку с исходниками программы командой cd, например cd C:\Documents and
Settings\RNT\Desktop\example
2) Если у вас есть файл проекта *.pro, переходите к этапу 3. Если его нет, введите qmake
-project
3) Подготовить к компиляции проект. Введите qmake имя_файла.pro. Например qmake
mywidget.pro. Если в каталоге всего один проект, то можно вести только qmake
4) Введите mingw32-make. Можете указать, собрать бинарник с отладочной информацией или без
нее, для этого введите mingw32-make debug или mingw32-make release .

Все эти команды можно сохранить в bat файле, класть его в папку с проектом и запускать для
сборки. Можете пользоваться bat файлом если вам не удалось прописать пути в переменную
окружения Path.
Содержимое bat файла может выглядеть вот так:

3.17. Где мне найти Assistant, Designer и прочие программы для Qt, и зачем они нужны ?

Все эти программы уже интегрированы в Qt Creator, но если вы хотите запустить их отдельно, то вы можете найти их в папке с Qt Libraries. В Windows`е это может быть C:\Qt\2009.03\qt\bin. В этой папке также находятся Qt Demo и Qt Linguist. Qt Creator может находиться в папке C:\Qt\2009.03\bin. В Linux`е Assistant и Designer могут находиться в папке /home/ваш_логин/qtsdk-2009.03/qt/bin или /opt/qtsdk-2009.03/qt/bin/. Qt Creator может находиться в папке /home/ваш_логин/qtsdk-2009.03/bin/ или /opt/qtsdk-2009.03/bin/.
Расскажу зачем нужны эти программы:
Qt Demo - программа, содержащая описание примеров исходников из папки C:\Qt\2009.03\qt\examples.
Qt Assistant - справочная система. Встроена в Qt Creator, но можно запустить отдельно.
Qt Linguist - программа для перевода интерфейса написанных в Qt программ на другие языки
-----------------------------------------------------------------------

3.18. На каких языках можно писать программы с Qt ?

Основная версия библиотеки Qt расчитана на C++, но есть также «привязки» ко многим другим языкам программирования, но не все из них достаточно развиты.
PHP-Qt - для PHP
PySide. PyQt - для Python
Qt Jambi - для Java
QtRuby - для Ruby
PerlQt - для Perl
Q# - для C#


4. Решения часто возникающих проблем


4.1. В пути к папке с исходникам не должно быть русских букв.

Иначе при компиляции можно получить примерно такое сообщение об ошибке:

4.2. Не найдены dll файлы. (в Windows`е)

Если в Windows`е попытаться запустить написанную программу двойным щелчком по файлу, то может выйти ошибка вроде этой:
"This application has failed to start because mingwm10.dll was not found. Re-installing the application may fix this problem."
Переводится это примерно так:
"Программа не может быть запущена, потому-что mingwm10.dll не найден. Переустановка программы может исправить эту ошибку."
Есть три варианта решения этой проблемы:
1) Надо просто найти все необходимые файлы(dll), и положить в папку с программой. Найти эти файлы можно в папке, в которую вы установили Qt(у меня C:\Qt\2009.03\qt\bin). Когда вы все необходимые dll будут в папке с вашей программой, она запустится.
2) Если вы запускаете программу на своем компьютере(с установленной Qt), то будет достаточно прописать путь (в переменной окружения Path) к папке со всеми dll. Заходим в Панель инструментов => Система => Дополнительно => Переменные среды. К переменной Path, через знак "точка с запятой" добавьте путь к папке /qt/bin, у меня например C:\Qt\2009.03\qt\bin. Сохраните. Ваши программы будут работать только на вашем компьютере. Если вы хотите запускать их на чужом компьютере, то используйте первый и третий вариант.
3) Собрать статическую сборку Qt и использовать ее для компиляции. Все необходимое для вашей программы будет включено в исполняемый файл. Рассмотрение это варианта выходит за рамки этого руководства. Приведу ссылки на сайты, где можно об этом почитать:
http://www.cyberforum.ru/cpp/thread55812.html
http://www.prog.org.ru/wiki/index.ph. BD%D0%B8%D0%B9
-----------------------------------------------------------------------

4.3. При компиляции проекта возникает ошибка. (в Linux`е)

Возможно ошибка в вашей программе. Но может быть такое, что библиотека Qt, которая установилась при установке Qt SDK, компилировалась на другом дистрибутиве Linux`а и для вашего дистрибутива не подходит. Если так, то при компиляции может выдаваться такая ошибка:

Чтобы проверить, так ли это, попробуйте скомпилировать какой нибудь исходник из папки /home/ваш_логин/qtsdk-2009.03/qt/examples/ или /opt/qtsdk-2009.03/qt/examples/. Если при компиляции возникает ошибка, то надо пересобрать библиотеку Qt. Для этого скачиваете отсюда http://qt.nokia.com/downloads/linux-x11-cpp исходники библиотеки Qt, компилируете, устанавливаете. Затем в Qt Creator`е заходите в Tools(Инструменты)=>Options(Параметры)=>Qt4=>Qt Versions. Там щелкаете на кнопку с плюсом и указываете путь к папке с библиотекой Qt, установленной из исходников. Если вы правильно указали путь, то увидите зеленую галочку. Теперь снова попробуйте скомпилировать исходник из папки /home/ваш_логин/qtsdk-2009.03/qt/examples/ или /opt/qtsdk-2009.03/qt/examples/.
Про решение этой проблемы можно почитать тут http://www.cyberforum.ru/cpp-linux/thread52436.html
-----------------------------------------------------------------------

4.4. В пути к библиотеке Qt не должно быть русских букв.

По умолчанию в Windows`е Qt устанавливается в папку C:\Qt\2009.05\. Если вы установите Qt в другую папку, путь к которой содержит русские буквы, то при компиляции исходников будет появляться такое сообщение об ошибке:

Собственные виджеты в Qt Designer Qt, C

Собственные виджеты в Qt Designer [Qt, C++]

В статье я расскажу как быстро и легко накидать интерфейс в Qt Designer. а также, как использовать при этом свои собственные виджеты.

В статье описано:

  • как создать в Qt Designer форму, а затем использовать ее в программе (есть несколько вариантов сделать это, я расскажу только про один);
  • как использовать свой собственный виджет в Qt Designer. П ри этом я хотел взять виджет из предыдущей статьи, но нашел его унылым, поэтому тут, также, описывается виджет типа двоичного счетчика.

Снимок окна программы, которая получилась при написании статьи приведен на рис. 1.

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

Раньше я никогда дизайнером не пользовался, т.к. думал, что он недостаточно гибок (это верно, отчасти), и позволяет использовать лишь станадртные элементы управления. Однако, недавно выполнял несколько заказов, в которых требовалось наклепать бешено много окошек, кнопочек и т.п. (все элементы управления были стандартными), поэтому я решил использовать Qt Designer. Я остался очень доволен дизайнером, но решил попробовать использовать в нем кастомные виджеты (есть несколько способов добиться такого результата, я расскажу лишь про один из них), и написать про это статью :).

1 Виджет счетчика

Наш счетчик отображает какое-либо значение в двоичном виде, при этом единице соответствует кружок красного цвета, а нулю – белого. Счетчик обладает разрядностью и периодичностью, с которой будет увеличиваться хранимое значение.

На листинг 1 приведен исходный код файла заголовка счетчика.

На листинг 1 все достаточно просто, я отмечу лишь один момент. Мы вынужденно написали метод set, для установки параметров счетчика, хотя, очевидно, что такую настройку можно было внести в конструктор. Дело в том, что конструктор классов, которые мы собираемся использовать в Qt Designer должны принимать лишь указатель на QWidget.

Реализация методов класса Counter дана на листинг 2, при этом, стоит отметить, что при создании таймера, в качестве родительского элемента передается 0, а не this (6 строка ) – это, также, связано с тем, что наш счетчик будет использоваться Qt Designer-ом (он не должен содержать дочерних элементов). В связи с этим, деструктор счетчика должен освобождать из под таймера память (автоматическая сборка мусора не сработает).

Теперь у нас есть счетчик, который мы встроим в форму, созданную Qt Designer.

2 Qt Designer

Процесс создания формы очень прост – мы создаем чистую форму (при этом, даем ей имя), перетаскиваем на нее 2 кнопки и QWidget, устанавливаем их на нужных нам позициях, устанавливаем размеры и, главное, имена (objectName).

Если мы назовем форму MainUI – то будет автоматически создан файл с именем ui_mainui.h, содержащий класс MainUI. В свою очередь, класс будет содержать поля, имена которых совпадают с заданными в Qt DesigneroojectName.

Теперь необходимо сообщить дизайнеру, что вместо виджета в окошке должен отображаться счетчик, для этого надо в настройках виджета выбрать “преобразовать в…”. в появившемся окне добавить виджет Counter (как показано на рис.2 ), при этом, окно будет автоматически связано с файлом counter.h.

Теперь у нас есть форма, содержащая нужный нам интерфейс, остается только использовать ее…

3 Использование формы, созданной в Qt Designer

Я дал своей форме имя MainUI, виджету – имя m_counter, а кнопка – m_start и m_stop, соответственно. При этом, рядом с файлом проекта появился файл ui_mainui.h, в пространстве имен Ui которого расположен класс MainUI. Есть 2варианта использовать этот класс:

  • наследование. При этом, должно использоваться множественное наследование (например, от классов QWidget и Ui::MainUI). Наследование от Ui::MainUI должно быть закрытым для решения проблемы ромбовидного наследования;
  • агрегация. Класс агрегат хранит указатель на форму, созданную в QtDesigner. Мне этот вариант кажется более естественным, хотя, обращаться к элементам формы приходится через указатель (в отличии от варианта с наследованием).

Файл заголовка формы, используемой в программе приведен на листинг 3. реализация – на листинг 4 .

В 6 строке реализации форма, созданная дизайнером устанавливается для текущего диалога (this) при помощи метода setupUI.

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

Программирование в Qt 4

Программирование графического интерфейса с помощью Qt 4, Часть 3 Qt Designer, Arthur и Scribe

Если в двух предыдущих частях этого цикла было многовато абстрактных понятий, то теперь мы займемся вещами конкретными и красивыми. До сих пор наши программы-примеры обходились без одной важной вещи, без которой ни одна серьезная программа обойтись не может без главного окна. На этот раз мы создадим главное окно и для этого заново познакомимся с Qt Designer.

Qt Designer старый новый друг

Вы наверняка обратили внимание, что в Qt версии 3 Qt Designer выступал в роли своего рода полу-IDE. Помимо самого визуального редактора в нем присутствовал генератор проектов и собственный редактор кода, который позволял, например, редактировать текст методов-слотов. В Qt 4 разработчики решительно пересмотрели функции Qt Designer. Теперь этот инструмент предназначен исключительно для визуального редактирования. Редактор текста и генератор проектов из нового Qt Designer удалены. Объясняется это тем, что, по мнению разработчиков, генерация проектов и редактирование текстов программ должны целиком переместиться в IDE, такие, например, как KDevelop или Microsoft Visual Studio, а Qt Designer (который интегрируется c указанными IDE) будет выполнять функцию вспомогательного инструмента. Впрочем, версия KDevelop, поддерживающая Qt Designer 4, есть пока далеко не у всех, а продукт Microsoft нас и вовсе не касается, поэтому мы рассмотрим работу с Qt Designer 4, как с самостоятельным средством. Лично мне в новом дизайнере не понравилось то, что он представляет собой набор независимых друг от друга окон (наподобие Glade). Возможно, такая структура упрощает встраивание Qt Designer в другие программные среды, но при работе с самим дизайнером постоянно переключаться между окнами не очень удобно.

При запуске Qt Designer 4 нас встречает диалоговое окно выбора заготовки для формы, которую мы будем редактировать. Можно создать новую форму или открыть уже существующую. В списке заготовок форм всего 4 пункта, из которых мы выбираем пункт Main Window (рис. 1).

Рисунок 1. Окно выбора формы Qt Designer

Само главное окно Qt-приложения (класс QMainWindow) также претерпело немало изменений. Теперь панели инструментов (объекты класса QToolBar) и стыкуемые окна (объекты класса QDockWidget) реализованы независимо друг от друга. Принципы работы с главным меню тоже несколько изменились (мы рассмотрим все это ниже). Пока что выберем в приветственном окне Qt Designer форму главного окна и щелкнем кнопку Create. Появится форма с заготовкой меню и строки состояния. Мы добавим в эту форму компонент QFrame, сделаем так, чтобы соответствующий объект заполнял всю форму (команда Lay Out Vertically контекстного меню) и сохраним форму в файле mainform.ui.

Для нашей первой программы с полноценным главным окном нам, разумеется, понадобится функция main(). Вот она:

Эта простенькая функция демонстрирует много не очень заметных, но существенных отличий Qt 4 от Qt 3. Мы начнем разбирать ее с заголовочных файлов. Включение заголовочных файлов QApplication и QMainWindow не должно вызывать вопросов. А вот откуда взялся файл ui_mainform.h? Этот файл должен описывать форму, созданную нами в визуальном редакторе, на языке C++. Иначе говоря, файл ui_mainform.h генерируется на основе данных, содержащихся в файле mainform.ui. Но чем его генерировать? В Qt3 нечто подобное создавалось автоматически программой Qt Designer (в Qt 3 этот файл назывался бы mainform.ui.h), но Qt Designer 4 не генерирует сам никаких исходных текстов. Мы можем возложить эту задачу на утилиту qmake. Тут возникает одна неуклюжесть. Обычно мы сначала пишем функцию main(), а затем вызываем такие инструменты как qmake. Но функция main() нуждается в файле ui_mainform.h, который только будет создан qmake. Я включил ссылку на файл ui_mainform.h в текст файла main.cpp, поскольку знал, что такой файл у нас появится (схему построения имен файлов с объявлением класса формы разгадать нетрудно имя состоит из префикса ui_, имени файла, в котором вы сохранили форму, и расширения .h). Если вы не уверены в том, как будет называться созданный автоматически заголовочный файл, можете сначала запустить qmake, а потом редактировать файл main.cpp. После этого qmake, конечно, придется запускать еще раз.

В файле ui_mainform.h определено пространство имен Ui, а в нем класс MainWindow (так по умолчанию назван класс, соответствующий форме главного окна). В функции main() мы создаем (статически) объект этого класса. Если вы думаете, что класс MainWindow происходит от QMainWindow, то ошибаетесь. На самом деле этот класс, описывающий интерфейс нашей программы, вообще не является потомком QWidget. Можно сказать, что класс MainWindow содержит инструкции по построению интерфейса, предназначенные для объекта класса QMainWindow. Объект этого класса мы и создаем далее в нашей программе. Метод mainWindow.setupUi() настраивает внешний вид объекта QMainWindow, в том числе, создает и настраивает дочерние элементы главного окна, которые мы определили в процессе редактирования формы.

Выполнив команды qmake project и qmake, мы можем собрать нашу программу с помощью make. В результате у нас получается главное окно с пустой формой в клиентской области. Конечно, на этом этапе наша программа выглядит не очень привлекательно, но она послужит холстом, на котором мы будем творить шедевры.

Графическая система Arthur

Хотя изменения графической системы Qt 4 по сравнению с Qt 3 не очень заметны на первый взгляд, новая система предоставляет весьма широкие возможности. Напомню, что основные функции работы с графикой в Qt 3 были реализованы в классе QPainter, который изначально предназначался для вывода графики в растровые массивы. Для поддержки подсистем вывода, не основанных на растровых массивах (например, принтеров PostScript) специальные объекты-потомки класса QPaintDevice эмулировали растровое устройство. В Qt 4 разработчики пошли более простым и логичным путем. Классы QPainter и QPaintDevice остались, но к ним добавился абстрактный класс QPaintEngine. Теперь все функции, реализующие специфику графического вывода на разных устройствах, собраны в классах-потомках QPaintEngine, соответствующих этим устройствам. Классы QPainter и QPaintDevice используют методы QPaintEngine для доступа к графическим устройствам, а не обращаются к этим устройствам напрямую, как раньше. Вам же, наоборот, не придется иметь дела с потомками QPaintEngine, если только вы не захотите расширить функциональность Qt 4, реализовав графический вывод на каком-нибудь неподдерживаемом устройстве. На практике это означает, что сладкая парочка QPainter и QPaintDevice теперь может рисовать практически на всех графических устройствах, доступных на данной платформе, причем работа с разными устройствами, будь то принтер или окно OpenGL, в значительной степени унифицирована. Еще одно преимущество новой системы заключается в том, что многие графические операции, которые раньше были реализованы чисто программными средствами, теперь могут использовать аппаратное ускорение и другие функции, поддерживаемые железом (раньше это было невозможно потому, что между QPainter и устройством лежала прослойка эмулятора растрового массива).

Посмотрим, как все это работает на практике. В качестве примера рассмотрим визуальный компонент QGLWidget. Благодаря новой архитектуре мы можем создавать изображения средствами QPainter в рабочем окне QGLWidget точно так же, как и на поверхности любого другого виджета. Не могу не отметить некоторую диалектичность процесса: когда-то я демонстрировал, как выводить графику OpenGL на поверхности объекта-потомка QWidget. Теперь мы воспользуемся QGLWidget для вывода обычных изображений, которые не являются частью трехмерных сцен. Такое использование OpenGL не по назначению отражает популярную в последнее время тенденцию задействовать мощь 3D-ускорителей в традиционно не-трехмерных задачах, например при отрисовке окон или работе с растровыми картинками.

Вернемся к программе с главным окном. Для того чтобы заставить наше главное окно что-то делать, нам следует создать его потомка. Посмотрим на объявление класса OGLWindow, который представляет собой главное окно программы arthur-demo (полный текст программы вы, как всегда, найдетепо ссылке в коце страницы).

Класс OGLWindow наследует сразу двум классам QMainWindow и Ui::MainWindow (второй из этих классов объявлен в файле ui_mainform.h. Что дает нам двойное наследование? Вернемся к функции main(), приведенной выше. Нам пришлось создать объект класса Ui::MainWindow для того, чтобы настроить внешний вид объекта QMainWindow. Для объекта класса OGLWindow дополнительных объектов создавать не придется, так как этот объект уже знает все, что нужно для построения его графического интерфейса. Ниже приводится текст конструктора OGLWindow:

Поскольку класс OGLWindow наследует классу Ui::MainWindow, метод setupUi() становится доступен в конструкторе OGLWindow. Мы вызываем этот метод и передаем ему в качестве параметра указатель this. Таким образом, объект класса OGLWindow сам настраивает свой интерфейс, а программисту, который захочет работать с нашим классом, не придется беспокоиться о вызове setupUi(). С классом GLWidget, производным от QGLWidget, мы познакомимся ниже. Объект frame представляет собой панель QFrame, которую мы добавили в форму главного окна в процессе визуального редактирования. Мы делаем объект класса GLWidget дочерним объектом этой панели.

Как вы, конечно, догадались, объект glWidget это визуальный компонент, предназначенный для вывода графики средствами OpenGL. Мы хотим, чтобы он занимал все пространство панели frame. Для этого мы создаем новый объект-менеджер компоновки класса QHBoxLayout, назначаем его в качестве текущего менеджера компоновки объекту frame (с помощью метода setLayout()) и добавляем в коллекцию менеджера объект glWidget. Самый простой способ заставить виджет QGLWidget выводить графическое изображение заключается в том, чтобы перекрыть метод paintEvent() в классе потомке QGLWidget. Именно для этого нам и нужен класс GLWidget. Наш вариант метода paintEvent() приводится ниже:

Рисование начинается с вызова метода begin() объекта painter() класса QPainter. Аргументом этого метода должен быть указатель на объект QPaintDevice, к каковому типу теперь приводится и объект класса QGLWidget (и, естественно, его потомки). Останавливаться на каждой инструкции вывода графики мы не будем. Обращу внимание читателей на поддержку сглаживания контуров, которую мы включаем с помощью вызова метода setRenderHint() и смешивания цветов alpha blending (обратите внимание на четвертый аргумент конструктора QColor()). Сглаживание и смешивание являются новыми возможностями QPainter и могут выполняться с использованием аппаратной поддержки (например, поддержки 3D-ускорителя), если аппаратная поддержка включена в вашей системе.

В приведенном выше примере я специально не использовал функции OpenGL (например, воспользовался методом eraseRect() вместо glClearColor()), чтобы показать, что в графической системе Arthur можно задействовать возможности OpenGL, не используя сами команды OpenGL. В результате один и тот же код может использоваться для вывода графики в окне с помощью 3D-ускорителя, для записи графики в растровое изображения или для вывода изображений на принтер PostScript.

Рассмотрим теперь функцию main() нашей программы. Наследование класса главного окна сразу от двух предков (QMainWindow и UI::MainWindow) позволило упростить код и этой функции:

Для того чтобы собрать программу успешно, в файле pro нужно включить поддержку модуля QtOpenGL:

Наиболее полно мощь OpenGL проявляется (помимо собственно 3D-графики), в тех приложениях, которым приходится выполнять различные преобразования изображений на экране. Возможность работы с QGLWidget как с обычным компонентом для вывода графики, позволяет, например, создать программу просмотра электронных фотографий, которая будет использовать аппаратно-ускоренные спецэффекты при показе изображений. При этом тот же самый код может быть использован, например, для сохранения результатов преобразований в растровом формате.

Рисунок 2. Arthur: не-трехмерная графика с помощью OpenGL

В заключение обзора этой программы (первой нашей программы, использующей главное окно) позволю себе дать вам один совет. Готовьтесь к тому, что при работе с главным окном (и другими окнами, спроектированными в Qt Designer 4) вам все время придется создавать их потомков. В Qt Designer 3 мы могли редактировать код обработчиков сигналов в процессе визуального редактирования. Qt Designer 4 тоже позволяет нам связывать сигналы и слоты и даже определять новые слоты, но, поскольку редактировать код в дизайнере все равно нельзя, лучше определять все новые слоты и связывать их с сигналами в классе-потомке того класса, который сгенерирован Qt Designer 4.

Пишем красиво

Система вывода форматированного текста претерпела в Qt 4 не меньше, а, пожалуй, даже больше изменений, чем система вывода графики. Основой для работы с текстовыми документами в новой системе вывода текста, получившей название Scribe, служит класс QTextDocument. Объект этого класса хранит всю информацию о структуре форматированного документа, а также предоставляет функции для его редактирования. Вы можете использовать класс QTextEdit для ручного редактирования текста, содержащегося в QTextDocument, и класс QTextBrowser для просмотра. Любопытно отметить, что хотя в документации к Qt 4 разработчики советуют использовать повсеместно объекты QTextDocument (а не QTextString) для хранения текста, у класса QTextEdit нет конструктора, которому можно было бы передать ссылку на объект QTextDocument, а вот конструктор со ссылкой на объект QString - есть. Для того чтобы назначить объекту класса QTextEdit объект класса QTextDocument, необходимо вызвать метод setDocument().

Важную роль в редактировании содержимого QTextDocument играет класс QTextCursor. Объекты QTextCursor используются как для указания текущей позиции в документе, так и для обозначения выбранных фрагментов текста. Кроме этого объекты QTextCursor предоставляют в распоряжение программиста ряд методов, предназначенных для редактирования текста и изменения форматирования, начиная с выбранной позиции.

Высшей единицей логической структуры документа QTextDocument является фрейм, представленный классом QTextFrame. Весь документ содержится в корневом фрейме (получить доступ к корневому фрейму можно с помощью метода rootFrame()). Перейти от корневого фрейма к дочерним фреймам можно с помощью метода childFrames() объекта QTextFrame (собственные фреймы положены таким элементам документа как таблица или изображение). На более низком уровне элементы документа представлены текстовыми блоками (объекты класса QTextBlock). Текстовым блоком в форматированном документе является любой массив текста, к символам которого применены одинаковые элементы форматирования (это может быть абзац, фраза или отдельное слово). Обычно программа получает доступ к текстовым блокам тогда, когда пользователь выделяет фрагмент текст или когда сама программа выделяет текстовый фрагмент по какому-либо признаку.

Работа со сложными документами не единственный козырь Scribe. Помимо прочего эта система позволяет выполнять фигурный вывод текста. Если вы хотите, чтобы вместо ровных полей слева и права выводимый вами текст был выровнен по контуру какой-нибудь сложной фигуры, воспользуйтесь классом QTextLayout. Класс QTextLayout управляет компоновкой неформатированного текста, то есть, текста, который выводится одним шрифтом. Объекты класса QTextLayout позволяют нам сделать две вещи: разбить текст на строки с учетом параметров выбранного шрифта и ширины каждой строки и задать расположение каждой строки относительно левого края виртуального листа. После этого вывести фигурно расположенный текст на экран (на принтер, или на другое устройство) можно одной командой.

В качестве демонстрации сложного расположения текста мы рассмотрим программу scribe-demo, полный исходный текст которой вы найдете на диске. Как и программа arthur-demo, наша новая программа добавляет в главное окно свой собственный виджет. На этот раз наш фирменный виджет реализуется классом Label. Класс Label происходит не от класса QLabel, а непосредственно от класса QWidget, ведь мы собираемся выводить текст нашими собственными средствами и функциональность класса QLabel нам ни к чему. Объявление класса Label выглядит просто:

В классе Label, как и в классе GLWidget, мы перекрываем метод paintEvent() класса-предка. Кроме того мы водим вспомогательный метод makeLayout(). Рассмотрим определения всех трех методов класса Label (конструктора, makeLayout() и paintEvent()).

В конструкторе Label мы создаем объект класса QTextLayout. Конструктору объекта textLayout передаются два аргумента ссылка на строку теста и ссылка на объект QFont, который определяет используемый шрифт. Все самое интересное сосредоточено в методе makeLayout(). Мы начинаем работу с компоновщиком текста с вызова метода beginLayout(). Для каждой строки выводимого текста мы создаем объект класса QTextLine с помощью метода createLine() объекта textLayout. Этот метод будет возвращать объекты QTextLine со значением isValid(), равным true, до тех пор, пока весь текст не будет распределен на строки (общее количество строк, разумеется, зависит от размеров шрифта и ширины каждой строки). Ширина строки устанавливается с помощью метода setLineWidth(), а ее позиция методом setPosition(). Для того, чтобы строки не наезжали друг на друга, мы смещаем отступ очередной строки от верхнего края на значение, равное высоте строки. В этом нам помогает метод height() объекта класса QTextLine. После того как создание и расположение строк закончены, мы вызываем метод endLayout().

Метод makeLayout создает своего рода шаблон, содержащий текст. Для вывода этого текста в виджет достаточно вызвать метод draw() объекта textLayout. Первым аргументом метода draw() должна быть ссылка на объект класса QPainter, вторым аргументом ссылка на объект QPoint, определяющий расположение левого верхнего угла той области, в которой выводится текст (фактическое расположение строк, заданное в методе makeLayout(), при выводе текста будет отсчитываться относительно этой точки).

Рисунок 3. Текст с полями в форме треугольника.

Обратите внимание на важную особенность QTextLayout. Каждый раз, когда мы вызываем метод beginLayout() информация о предыдущей компоновке текста (и всех созданных объектах QTextLine) теряется. Эта особенность может стать источником труднообъяснимых ошибок для новичка, но нам на позволяет создать объект класса QTextLayout один раз (в конструкторе Label), а затем использовать его многократно для генерации компоновок текста, зависящих от ширины виджета, в методе makeLayout(). В связи с этим любопытно отметь, что в релизе Qt 4.4 (на момент написания статьи он находился на стадии бета) у класса QTextLayout появился метод clearLayout (), который очищает список строк компоновщика текста. Лично я большой пользы от этого метода не вижу (разве что кому-то понадобится обнулить список строк между вызовами beginLayout() и endLayout()), а, учитывая то, что этот метод поддерживается не всеми релизами Qt 4, пользоваться им не советую.

На этом наше знакомство с изобразительными средствами Qt 4 не закончилось. В следующий раз мы познакомимся с системой Graphics View, которая появилась в Qt 4.2 и была серьезно дополнена и переработана в Qt 4.3 и Qt 4.4.

Статья впервые опубликована в журнале Linux Format

© 2008 Андрей Боровский <anb @ symmetrica.net>