GettingStartedWithQtRussian: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=Начало работы с Qt=
[toc align_right="yes" depth="2"]


Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (''toolkit'') для разработки графического интерфейса пользователя (''<span class="caps">GUI</span>''). В данном руководстве мы изучим основы Qt, написав простое приложение “Блокнот”. После прочтения этого руководства вы сможете лучше ориентироваться в документации и найти там всю необходимую информацию для разработки своих приложений.
= Начало работы с Qt =


==Привет, Блокнот!==
Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (''toolkit'') для разработки графического интерфейса пользователя (''GUI''). В данном руководстве мы изучим основы Qt, написав простое приложение &quot;Блокнот&amp;quot;. После прочтения этого руководства вы сможете лучше ориентироваться в документации и найти там всю необходимую информацию для разработки своих приложений.


В качестве первого примера создадим и отобразим текстовый редактор ([http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]''). Это, пожалуй, самая простая программа на Qt с графическим интерфейсом пользователя, которая только может существовать.
== Привет, Блокнот! ==


[[Image:gs1.png|Самое простое приложение на Qt]]
В качестве первого примера создадим и отобразим текстовый редактор (&quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qtextedit.html). Это, пожалуй, самая простая программа на Qt с графическим интерфейсом пользователя, которая только может существовать.


Исходный код:<br /> Давайте рассмотрим каждую строку кода. На первых двух строках мы подключаем заголовочные файлы для [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' и [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]'' – двух классов которые потребуются для этого примера. Для каждого класса Qt есть заголовочный файл с соответствующим именем.
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Самое простое приложение на Qt]]


На строке 6 создается экземпляр [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]''. Этот объект управляет ресурсами уровня приложения и необходим для запуска любой программы на Qt с графическим интерфейсом. Ему необходимо передать ''argv'' и ''args'', так как Qt может принимать некоторые параметры командной строки.
Исходный код:<br /><code><br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;


На строке 8 создаётся экземпляр текстового редактора [http://doc.qt.nokia.com/4.7/qtextedit.html QTextEdit] ''[doc.qt.nokia.com]''. Текстовый редактор – это графический элемент интерфейса пользователя. В Qt мы называем такие элементы виджетами. Примерами других виджетов являются полосы прокрутки (''scroll bars''), метки (''labels'') и переключатели (''radio buttons''). Виджет также может быть контейнером для других виджетов, например, диалог или главное окно приложения.
int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);


На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'', у которого есть панели инструментов (''toolbars''), меню, строка состояния (''status bar'') и другие виджеты), то можно показать отдельный виджет как полноценное окно. По умолчанию виджеты скрыты; метод [http://doc.qt.nokia.com/4.7/qwidget.html#show show()] ''[doc.qt.nokia.com]'' делает их видимыми.
QTextEdit textEdit;<br /> textEdit.show();


На строке 11 [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'' входит в цикл событий (''eventloop''). Во время работы приложения на Qt события генерируются и отправляются виджетам. Примерами событий могут служить нажатия кнопок мыши или ввод с клавиатуры. Когда пользователь вводит текст в текстовый редактор, этот виджет получает события нажатий клавиш и отображает набранный текст на экране.
return app.exec&amp;amp;#40;&amp;#41;;;<br />}<br /></code><br />Давайте рассмотрим каждую строку кода. На первых двух строках мы подключаем заголовочные файлы для &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html и &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qtextedit.html – двух классов которые потребуются для этого примера. Для каждого класса Qt есть заголовочный файл с соответствующим именем.


Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды:<br />
На строке 6 создается экземпляр &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html. Этот объект управляет ресурсами уровня приложения и необходим для запуска любой программы на Qt с графическим интерфейсом. Ему необходимо передать ''argv'' и ''args'', так как Qt может принимать некоторые параметры командной строки.


Так как утилита qmake может работать в двух режимах – для создания Makefile или для создания .pro файла, мы должны импользовать ее два раза.
На строке 8 создаётся экземпляр текстового редактора &quot;QTextEdit&amp;quot;:http://doc.qt.nokia.com/4.7/qtextedit.html. Текстовый редактор – это графический элемент интерфейса пользователя. В Qt мы называем такие элементы виджетами. Примерами других виджетов являются полосы прокрутки (''scroll bars''), метки (''labels'') и переключатели (''radio buttons''). Виджет также может быть контейнером для других виджетов, например, диалог или главное окно приложения.


После этого в каталоге появится исполняемый файл (обратите внимание, что в Windows вместо ''make'' необходимо выполнить ''nmake'' и исполняемый файл будет в подкаталоге ''debug'' или ''release''). ''qmake'' – это инструмент Qt для сборки приложения, использующий конфигурационный файл, который создается при запуске ''qmake'' с ключом -project. Используя заданный конфигурационный файл (файл с расширением .pro), ''qmake'' создаёт файл для утилиты ''make'', которая будет собирать ваше приложение. Мы рассмотрим написание собственных .pro файлов позже.
На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть панели инструментов (''toolbars''), меню, строка состояния (''status bar'') и другие виджеты), то можно показать отдельный виджет как полноценное окно. По умолчанию виджеты скрыты; метод &quot;show()&quot;:http://doc.qt.nokia.com/4.7/qwidget.html#show делает их видимыми.


===Дополнительная информация===
На строке 11 &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html входит в цикл событий (''eventloop''). Во время работы приложения на Qt события генерируются и отправляются виджетам. Примерами событий могут служить нажатия кнопок мыши или ввод с клавиатуры. Когда пользователь вводит текст в текстовый редактор, этот виджет получает события нажатий клавиш и отображает набранный текст на экране.


{| class="infotable line"
Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды:<br /><code><br />qmake <s>project<br />qmake<br />make<br /></code>
| Тема
<br />Так как утилита qmake может работать в двух режимах</s> для создания Makefile или для создания .pro файла, мы должны импользовать ее два раза.
| Статья
|-
| Виджеты и геометрия окна
|
[http://doc.qt.nokia.com/4.7/application-windows.html Window and Dialog Widgets] ''[doc.qt.nokia.com]''
|-
| События и их обработка
|
[http://doc.qt.nokia.com/4.7/eventsandfilters.html The Event System] ''[doc.qt.nokia.com]''
|}
 
==Добавление кнопки выхода==
 
В настоящем приложении обычно требуется более одного виджета. Добавим кнопку ([http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] ''[doc.qt.nokia.com]'') под текстовым редактором. Кнопка будет закрывать Блокнот при нажатии на неё.
 
[[Image:gs2.png|Кнопка выход]]
 
Давайте взглянем на код.<br />
 
На первой строке мы включаем [http://doc.qt.nokia.com/4.7/qtgui.html QtGui] ''[doc.qt.nokia.com]'' – заголовочный файл, содержащий все классы графического интерфейса пользователя Qt.
 
На строке 10 используется механизм сигналов и слотов Qt для выхода из приложения при нажатии кнопки '''Quit'''. Слот это функция, которая может быть вызвана во время выполнения программы (''runtime'') с помощью её имени (в виде строки). Сигнал это функция, которая вызывает связанные с ней слоты; мы называем это подключением слота к сигналу (''connect'') и отправкой сигнала (''emit'').
 
[http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit quit()] ''[doc.qt.nokia.com]'' — это слот [http://doc.qt.nokia.com/4.7/qapplication.html QApplication] ''[doc.qt.nokia.com]'', который закрывает приложение. [http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked clicked()] ''[doc.qt.nokia.com]'' – это сигнал, посылаемый кнопкой ([http://doc.qt.nokia.com/4.7/qpushbutton.html QPushButton] ''[doc.qt.nokia.com]'') при нажатии. Статическая функция [http://doc.qt.nokia.com/4.7/qobject.html#connect QObject::connect()] ''[doc.qt.nokia.com]'' соединяет сигнал со слотом. ''<span class="caps">SIGNAL</span>'' и ''<span class="caps">SLOT</span>'' это два макроса, которые принимают сигнатуры соединяемых функций сигнала и слота. Также необходимо передать указатели на соединяемые объекты.
 
На строке 12 создаётся вертикальный компоновщик ([http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] ''[doc.qt.nokia.com]''). Как было сказано выше, виджеты могут содержать другие виджеты. Можно явно указать границы (расположение и размер) дочерних виджетов, но удобнее использовать компоновщик (''layout''). Компоновщик управляет границами дочерних виджетов. [http://doc.qt.nokia.com/4.7/qvboxlayout.html QVBoxLayout] ''[doc.qt.nokia.com]'', например, размещает дочерние виджеты вертикально.
 
На строках 13 и 14 текстовый редактор и кнопка добавляются в компоновщик. На строке 17 компоновщик устанавливается на виджет.
 
===Дополнительная информация===
 
{| class="infotable line"
| Тема
| Статья
|-
| Сигналы и слоты
|
[http://doc.qt.nokia.com/4.7/signalsandslots.html Signals &amp; Slots] ''[doc.qt.nokia.com]''
|-
| Компоновки
|
[http://doc.qt.nokia.com/4.7/layout.html Layout Management] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/widgets-and-layouts.html Widgets and Layouts] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-layouts.html Layout Examples] ''[doc.qt.nokia.com]''
|-
| Виджеты Qt
|
[http://doc.qt.nokia.com/4.7/gallery.html Qt Widget Gallery] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-widgets.html Widget Examples] ''[doc.qt.nokia.com]''
|}
 
==Наследование QWidget==
 
Представим, что при выходе пользователя из приложения нам надо показать диалог для подтверждения выхода. В этом примере мы наследуем [http://doc.qt.nokia.com/4.7/qwidget.html QWidget] ''[doc.qt.nokia.com]'' и добавим слот, который соединим с кнопкой выхода '''Quit'''.
 
[[Image:gs3.png|Наследуемся от QWidget]]
 
Давайте взглянем на код:<br />
 
Макрос ''Q_OBJECT'' должен быть первой инструкцией в объявлении класса. Этот макрос объявляет наш класс как [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' (естественно, класс должен быть унаследован от [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]''). [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' добавляет несколько возможностей обычным классам C++. Например, имя класса и имена его слотов могут быть запрошены во время выполнения программы. Также можно вызывать слоты и узнавать типы их параметров.
 
Строка 13 объявляет слот ''quit()''. Для объявления слотов используется макрос ''slots''. Теперь этот слот может быть подключен к сигналам с подходящей сигнатурой (то есть к сигналам без параметров).
 
Вместо настройки графического интерфейса пользователя и соединения слота в функции ''main()'' мы используем конструктор класса Notepad.<br />
 
Как видно из определения класса, используются указатели на экземпляры [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' (''textEdit'' и ''quitButton''). Как правило, вы всегда должны создавать наследников [http://doc.qt.nokia.com/4.7/qobject.html QObject] ''[doc.qt.nokia.com]'' в динамической памяти (''heap'') и никогда не копировать их.
 
Также мы используем функцию [http://doc.qt.nokia.com/4.7/qobject.html#tr tr()] ''[doc.qt.nokia.com]'' для видимых пользователю строк. Эта функция нужна когда приложение должно быть более чем на одном языке (например, на китайском и английском). Мы не будем углубляться в детали, но все подробности можно посмотреть по ссылке о Qt Linguist в дополнительной информации.
 
===Дополнительная информация===
 
{| class="infotable line"
| Тема
| Статья
|-
| tr() и интернационализация
|
[http://doc.qt.nokia.com/4.7/linguist-manual.html Qt Linguist Manual] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/i18n-source-translation.html Writing Source Code for Translation] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/linguist-hellotr.html Hello tr() Example] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/internationalization.html Internationalization with Qt] ''[doc.qt.nokia.com]''
|-
|
[http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects QObject] ''[doc.qt.nokia.com]'' и объектная модель Qt (необходимо для понимания Qt)
|
[http://doc.qt.nokia.com/4.7/object.html Object Model] ''[doc.qt.nokia.com]''
|-
| qmake и система сборки Qt
|
[http://doc.qt.nokia.com/4.7/qmake-manual.html qmake Manual] ''[doc.qt.nokia.com]''
|}
 
===Создание .pro файла===
 
Для этого примера мы напишем собственный .pro файл вместо использования опции ''qmake -project''.<br />
 
Соберем приложение:<br />
 
==Использование QMainWindow==
 
Многие приложения могут выиграть от использования [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'', у которого есть собственный компоновщик куда вы можете добавить меню, прикрепляемые виджеты (''dock widgets''), панель инструментов (''tool bars'') и строку состояния (''status bar''). У [http://doc.qt.nokia.com/4.7/qmainwindow.html QMainWindow] ''[doc.qt.nokia.com]'' есть центральная область где можно разместить любой виджет. В нашем случае мы разместим там наш текстовый редактор.
 
[[Image:gs4.png|Используем QMainWindow]]
 
Давайте взглянем на новое определение класса Notepad.<br />
 
Здесь появились еще два слота для сохранения и загрузки файла. Они будут реализованы в следующем разделе.
 
Часто в главном окне один и тот же слот должен быть вызван сразу несколькими виджетами. Например, элементами меню и кнопками на панели инструментов. Для упрощения подобных вещей в Qt есть [http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]'', который может быть использован несколькими виджетами и который может быть соединён со слотом. Например, и [http://doc.qt.nokia.com/4.7/qmenu.html QMenu] ''[doc.qt.nokia.com]'', и [http://doc.qt.nokia.com/4.7/qtoolbar.html QToolBar] ''[doc.qt.nokia.com]'' могут создавать элементы меню и кнопки инструментов из одного [http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]''. Мы скоро увидим как это работает.<br /> Как и ранее, для настройки графического интерфейса пользователя мы используем конструктор Notepad.<br />
 
Экземпляры [http://doc.qt.nokia.com/4.7/qaction.html QAction] ''[doc.qt.nokia.com]'' создаются с указанием текста, который будет отображен на виджетах (в нашем случае, на элементах меню). Если мы хотим добавить их на панель инструментов, то нам может потребоваться задать ещё и [http://doc.qt.nokia.com/4.7/qicon.html иконки] ''[doc.qt.nokia.com]''.
 
Теперь, когда будет выбран пункт меню, он активирует действие и вызовется соответствующий слот.
 
===Дополнительная информация===
 
{| class="infotable line"
| Тема
| Статья
|-
| Главные окна и классы главного окна
|
[http://doc.qt.nokia.com/4.7/mainwindow.html Application Main Window] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/examples-mainwindow.html Main Window Examples] ''[doc.qt.nokia.com]''
|-
| Приложения с многодокументным интерфейсом (<span class="caps">MDI</span>)
|
[http://doc.qt.nokia.com/4.7/qmdiarea.html QMdiArea] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/mainwindows-mdi.html <span class="caps">MDI</span> Example] ''[doc.qt.nokia.com]''
|}
 
==Сохранение и загрузка==
 
В этом примере мы реализуем слоты ''open()'' и ''save()'', которые были добавлены в предыдущем примере.
 
[[Image:gs5.png|Открытие файла в Kubuntu]]
 
Начнем со слота ''open()'':<br />
 
Сначала у пользователя запрашивается имя открываемого файла. В Qt есть класс [http://doc.qt.nokia.com/4.7/qfiledialog.html QFileDialog] ''[doc.qt.nokia.com]'', который является диалогом выбора файла. Выше показан такой диалог в Kubuntu. Статический метод [http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName getOpenFileName()] ''[doc.qt.nokia.com]'' отображает модальный диалог выбора файла и не завершается, пока пользователь не выберет файл. Он возвращает путь к выбранному файлу или пустую строку, если пользователь отменил диалог.
 
Если пользователь выбрал файл, то попробуем его открыть с помощью метода [http://doc.qt.nokia.com/4.7/qiodevice.html#open open()] ''[doc.qt.nokia.com]'', который возвращает истину в случае успеха. Мы не будем углубляться в обработку ошибок (подробнее про них можно почитать в дополнительной информации). Если не удалось открыть файл, то отображается диалог [http://doc.qt.nokia.com/4.7/qmessagebox.html QMessageBox] ''[doc.qt.nokia.com]'' с сообщением об ошибке.


Фактически, чтение данных выполняется с помощью одного метода [http://doc.qt.nokia.com/4.7/qiodevice.html#readAll readAll()] ''[doc.qt.nokia.com]'', который возвращает все содержимое файла в [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray] ''[doc.qt.nokia.com]''. Метод [http://doc.qt.nokia.com/4.7/qbytearray.html#constData constData()] ''[doc.qt.nokia.com]'' возвращает содержимое [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray] ''[doc.qt.nokia.com]'' в виде const char *, для которого у [http://doc.qt.nokia.com/4.7/qstring.html QString] ''[doc.qt.nokia.com]'' есть конструктор. Затем содержимое файла отображается в текстовом редакторе. В конце работы вызывается метод [http://doc.qt.nokia.com/4.7/qiodevice.html#close close()] ''[doc.qt.nokia.com]'' который закроет файл и вернет файловый дескриптор операционной системе.
После этого в каталоге появится исполняемый файл (обратите внимание, что в Windows вместо ''make'' необходимо выполнить ''nmake'' и исполняемый файл будет в подкаталоге ''debug'' или ''release''). ''qmake'' – это инструмент Qt для сборки приложения, использующий конфигурационный файл, который создается при запуске ''qmake'' с ключом <s>project. Используя заданный конфигурационный файл (файл с расширением .pro), ''qmake'' создаёт файл для утилиты ''make'', которая будет собирать ваше приложение. Мы рассмотрим написание собственных .pro файлов позже.
<br />h3. Дополнительная информация
<br />|Тема|Статья|<br />|Виджеты и геометрия окна|&quot;Window and Dialog Widgets&amp;quot;:http://doc.qt.nokia.com/4.7/application-windows.html|<br />|События и их обработка|&quot;The Event System&amp;quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html|


Рассмотрим слот ''save()'':<br />
<br />h2. Добавление кнопки выхода
<br />В настоящем приложении обычно требуется более одного виджета. Добавим кнопку (&quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html) под текстовым редактором. Кнопка будет закрывать Блокнот при нажатии на неё.
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Кнопка выход]]
<br />Давайте взглянем на код.<br /><code><br />#include &lt;QtGui&amp;gt;
<br />int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);
<br /> QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br /> QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);
<br /> QWidget window;<br /> window.setLayout(&amp;layout);
<br /> window.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br /></code>
<br />На первой строке мы включаем &quot;QtGui&amp;quot;:http://doc.qt.nokia.com/4.7/qtgui.html – заголовочный файл, содержащий все классы графического интерфейса пользователя Qt.
<br />На строке 10 используется механизм сигналов и слотов Qt для выхода из приложения при нажатии кнопки '''Quit'''. Слот это функция, которая может быть вызвана во время выполнения программы (''runtime'') с помощью её имени (в виде строки). Сигнал это функция, которая вызывает связанные с ней слоты; мы называем это подключением слота к сигналу (''connect'') и отправкой сигнала (''emit'').
<br />&quot;quit()&quot;:http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit — это слот &quot;QApplication&amp;quot;:http://doc.qt.nokia.com/4.7/qapplication.html, который закрывает приложение. &quot;clicked()&quot;:http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked – это сигнал, посылаемый кнопкой (&quot;QPushButton&amp;quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html) при нажатии. Статическая функция &quot;QObject::connect()&quot;:http://doc.qt.nokia.com/4.7/qobject.html#connect соединяет сигнал со слотом. ''SIGNAL'' и ''SLOT'' это два макроса, которые принимают сигнатуры соединяемых функций сигнала и слота. Также необходимо передать указатели на соединяемые объекты.
<br />На строке 12 создаётся вертикальный компоновщик (&quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html). Как было сказано выше, виджеты могут содержать другие виджеты. Можно явно указать границы (расположение и размер) дочерних виджетов, но удобнее использовать компоновщик (''layout''). Компоновщик управляет границами дочерних виджетов. &quot;QVBoxLayout&amp;quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html, например, размещает дочерние виджеты вертикально.
<br />На строках 13 и 14 текстовый редактор и кнопка добавляются в компоновщик. На строке 17 компоновщик устанавливается на виджет.
<br />h3. Дополнительная информация
<br />|Тема|Статья|<br />|Сигналы и слоты|&quot;Signals &amp; Slots&amp;quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html|<br />|Компоновки|&quot;Layout Management&amp;quot;:http://doc.qt.nokia.com/4.7/layout.html, &quot;Widgets and Layouts&amp;quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, &quot;Layout Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html|<br />|Виджеты Qt|&quot;Qt Widget Gallery&amp;quot;:http://doc.qt.nokia.com/4.7/gallery.html, &quot;Widget Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html|
<br />h2. Наследование QWidget
<br />Представим, что при выходе пользователя из приложения нам надо показать диалог для подтверждения выхода. В этом примере мы наследуем &quot;QWidget&amp;quot;:http://doc.qt.nokia.com/4.7/qwidget.html и добавим слот, который соединим с кнопкой выхода '''Quit'''.
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|Наследуемся от QWidget]]
<br />Давайте взглянем на код:<br /><code><br />class Notepad : public QWidget<br />{<br /> Q_OBJECT
<br />public:<br /> Notepad();
<br />private slots:<br /> void quit();
<br />private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br /></code>
<br />Макрос ''Q_OBJECT'' должен быть первой инструкцией в объявлении класса. Этот макрос объявляет наш класс как &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html (естественно, класс должен быть унаследован от &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html). &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html добавляет несколько возможностей обычным классам C++. Например, имя класса и имена его слотов могут быть запрошены во время выполнения программы. Также можно вызывать слоты и узнавать типы их параметров.
<br />Строка 13 объявляет слот ''quit()''. Для объявления слотов используется макрос ''slots''. Теперь этот слот может быть подключен к сигналам с подходящей сигнатурой (то есть к сигналам без параметров).
<br />Вместо настройки графического интерфейса пользователя и соединения слота в функции ''main()'' мы используем конструктор класса Notepad.<br /><code><br />Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));
<br /> connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
<br /> QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br />}<br /></code>
<br />Как видно из определения класса, используются указатели на экземпляры &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html (''textEdit'' и ''quitButton''). Как правило, вы всегда должны создавать наследников &quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qobject.html в динамической памяти (''heap'') и никогда не копировать их.
<br />Также мы используем функцию &quot;tr()&quot;:http://doc.qt.nokia.com/4.7/qobject.html#tr для видимых пользователю строк. Эта функция нужна когда приложение должно быть более чем на одном языке (например, на китайском и английском). Мы не будем углубляться в детали, но все подробности можно посмотреть по ссылке о Qt Linguist в дополнительной информации.
<br />h3. Дополнительная информация
<br />|Тема|Статья|<br />|tr() и интернационализация|&quot;Qt Linguist Manual&amp;quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, &quot;Writing Source Code for Translation&amp;quot;:http://doc.qt.nokia.com/4.7/i18n-source-translation.html, &quot;Hello tr() Example&amp;quot;:http://doc.qt.nokia.com/4.7/linguist-hellotr.html, &quot;Internationalization with Qt&amp;quot;:http://doc.qt.nokia.com/4.7/internationalization.html|<br />|&quot;QObject&amp;quot;:http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects и объектная модель Qt (необходимо для понимания Qt)|&quot;Object Model&amp;quot;:http://doc.qt.nokia.com/4.7/object.html|<br />|qmake и система сборки Qt|&quot;qmake Manual&amp;quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html|
<br />h3. Создание .pro файла
<br />Для этого примера мы напишем собственный .pro файл вместо использования опции _qmake <s>project_.<br /><code><br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br /></code>
<br />Соберем приложение:<br /><code><br />qmake<br />make<br /></code>
<br />h2. Использование QMainWindow
<br />Многие приложения могут выиграть от использования &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть собственный компоновщик куда вы можете добавить меню, прикрепляемые виджеты (''dock widgets''), панель инструментов (''tool bars'') и строку состояния (''status bar''). У &quot;QMainWindow&amp;quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html есть центральная область где можно разместить любой виджет. В нашем случае мы разместим там наш текстовый редактор.
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Используем QMainWindow]]
<br />Давайте взглянем на новое определение класса Notepad.<br /><code><br />#include &lt;QtGui&amp;gt;
<br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT
<br />public:<br /> Notepad();
<br />private slots:<br /> void open();<br /> void save();<br /> void quit();
<br />private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br />};<br /></code>
<br />Здесь появились еще два слота для сохранения и загрузки файла. Они будут реализованы в следующем разделе.
<br />Часто в главном окне один и тот же слот должен быть вызван сразу несколькими виджетами. Например, элементами меню и кнопками на панели инструментов. Для упрощения подобных вещей в Qt есть &quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html, который может быть использован несколькими виджетами и который может быть соединён со слотом. Например, и &quot;QMenu&amp;quot;:http://doc.qt.nokia.com/4.7/qmenu.html, и &quot;QToolBar&amp;quot;:http://doc.qt.nokia.com/4.7/qtoolbar.html могут создавать элементы меню и кнопки инструментов из одного &quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html. Мы скоро увидим как это работает.<br />Как и ранее, для настройки графического интерфейса пользователя мы используем конструктор Notepad.<br /><code><br />Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br />}<br /></code>
<br />Экземпляры &quot;QAction&amp;quot;:http://doc.qt.nokia.com/4.7/qaction.html создаются с указанием текста, который будет отображен на виджетах (в нашем случае, на элементах меню). Если мы хотим добавить их на панель инструментов, то нам может потребоваться задать ещё и &quot;иконки&amp;quot;:http://doc.qt.nokia.com/4.7/qicon.html.
<br />Теперь, когда будет выбран пункт меню, он активирует действие и вызовется соответствующий слот.
<br />h3. Дополнительная информация
<br />|Тема|Статья|<br />|Главные окна и классы главного окна|&quot;Application Main Window&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, &quot;Main Window Examples&amp;quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html|<br />|Приложения с многодокументным интерфейсом (MDI)|&quot;QMdiArea&amp;quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, &quot;MDI Example&amp;quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html|
<br />h2. Сохранение и загрузка
<br />В этом примере мы реализуем слоты ''open()'' и ''save()'', которые были добавлены в предыдущем примере.
<br />p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|Открытие файла в Kubuntu]]
<br />Начнем со слота ''open()'':<br /><code><br />QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp'''.h)&quot;));
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit</s>&gt;setPlainText(contents);<br /> file.close();<br />}<br /></code>
<br />Сначала у пользователя запрашивается имя открываемого файла. В Qt есть класс &quot;QFileDialog&amp;quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html, который является диалогом выбора файла. Выше показан такой диалог в Kubuntu. Статический метод &quot;getOpenFileName()&quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName отображает модальный диалог выбора файла и не завершается, пока пользователь не выберет файл. Он возвращает путь к выбранному файлу или пустую строку, если пользователь отменил диалог.
<br />Если пользователь выбрал файл, то попробуем его открыть с помощью метода &quot;open()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#open, который возвращает истину в случае успеха. Мы не будем углубляться в обработку ошибок (подробнее про них можно почитать в дополнительной информации). Если не удалось открыть файл, то отображается диалог &quot;QMessageBox&amp;quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html с сообщением об ошибке.
<br />Фактически, чтение данных выполняется с помощью одного метода &quot;readAll()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, который возвращает все содержимое файла в &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/4.7/qbytearray.html. Метод &quot;constData()&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html#constData возвращает содержимое &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/4.7/qbytearray.html в виде const char''', для которого у &quot;QString&amp;quot;:http://doc.qt.nokia.com/4.7/qstring.html есть конструктор. Затем содержимое файла отображается в текстовом редакторе. В конце работы вызывается метод &quot;close()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#close который закроет файл и вернет файловый дескриптор операционной системе.
<br />Рассмотрим слот ''save()'':<br /><code><br />QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp *.h)&quot;));
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit</s>&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br />}<br /></code>


Для записи данных в файл воспользуемся классом [http://doc.qt.nokia.com/4.7/qtextstream.html QTextStream] ''[doc.qt.nokia.com]'' (текстовый поток), который в нашем случае будет оберткой над экземпляром [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]''. Текстовый поток может записывать [http://doc.qt.nokia.com/4.7/qstring.html QString] ''[doc.qt.nokia.com]'' непосредственно в файл; [http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'' же принимает лишь сырые данные (''char*'') или [http://doc.qt.nokia.com/4.7/qbytearray.html QByteArray] ''[doc.qt.nokia.com]'' с помощью методов [http://doc.qt.nokia.com/4.7/qiodevice.html#write write()] ''[doc.qt.nokia.com]'' класса-предка [http://doc.qt.nokia.com/4.7/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]''.
Для записи данных в файл воспользуемся классом &quot;QTextStream&amp;quot;:http://doc.qt.nokia.com/4.7/qtextstream.html (текстовый поток), который в нашем случае будет оберткой над экземпляром &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html. Текстовый поток может записывать &quot;QString&amp;quot;:http://doc.qt.nokia.com/4.7/qstring.html непосредственно в файл; &quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html же принимает лишь сырые данные (''char*'') или &quot;QByteArray&amp;quot;:http://doc.qt.nokia.com/4.7/qbytearray.html с помощью методов &quot;write()&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html#write класса-предка &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/4.7/qiodevice.html.


===Дополнительная информация===
=== Дополнительная информация ===


{| class="infotable line"
{|
| Тема
|Тема
| Статья
|Статья
|-
|-
| Файлы и устройства ввода-вывода
|Файлы и устройства ввода-вывода
|
|&quot;QFile&amp;quot;:http://doc.qt.nokia.com/4.7/qfile.html, &quot;QIODevice&amp;quot;:http://doc.qt.nokia.com/4.7/qiodevice.html
[http://doc.qt.nokia.com/4.7/qfile.html QFile] ''[doc.qt.nokia.com]'', [http://doc.qt.nokia.com/4.7/qiodevice.html <span class="caps">QIOD</span>evice] ''[doc.qt.nokia.com]''
|}
|}

Revision as of 14:45, 23 February 2015

[toc align_right="yes&quot; depth="2&quot;]

Начало работы с Qt

Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (toolkit) для разработки графического интерфейса пользователя (GUI). В данном руководстве мы изучим основы Qt, написав простое приложение "Блокнот&quot;. После прочтения этого руководства вы сможете лучше ориентироваться в документации и найти там всю необходимую информацию для разработки своих приложений.

Привет, Блокнот!

В качестве первого примера создадим и отобразим текстовый редактор ("QTextEdit&quot;:http://doc.qt.nokia.com/4.7/qtextedit.html). Это, пожалуй, самая простая программа на Qt с графическим интерфейсом пользователя, которая только может существовать.

p=. Самое простое приложение на Qt

Исходный код:

<br />#include &lt;QApplication&amp;gt;<br />#include &lt;QTextEdit&amp;gt;

int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);

QTextEdit textEdit;<br /> textEdit.show();

return app.exec&amp;amp;#40;&amp;#41;;;<br />}<br />


Давайте рассмотрим каждую строку кода. На первых двух строках мы подключаем заголовочные файлы для "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html и "QTextEdit&quot;:http://doc.qt.nokia.com/4.7/qtextedit.html – двух классов которые потребуются для этого примера. Для каждого класса Qt есть заголовочный файл с соответствующим именем.

На строке 6 создается экземпляр "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html. Этот объект управляет ресурсами уровня приложения и необходим для запуска любой программы на Qt с графическим интерфейсом. Ему необходимо передать argv и args, так как Qt может принимать некоторые параметры командной строки.

На строке 8 создаётся экземпляр текстового редактора "QTextEdit&quot;:http://doc.qt.nokia.com/4.7/qtextedit.html. Текстовый редактор – это графический элемент интерфейса пользователя. В Qt мы называем такие элементы виджетами. Примерами других виджетов являются полосы прокрутки (scroll bars), метки (labels) и переключатели (radio buttons). Виджет также может быть контейнером для других виджетов, например, диалог или главное окно приложения.

На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, "QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть панели инструментов (toolbars), меню, строка состояния (status bar) и другие виджеты), то можно показать отдельный виджет как полноценное окно. По умолчанию виджеты скрыты; метод "show()":http://doc.qt.nokia.com/4.7/qwidget.html#show делает их видимыми.

На строке 11 "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html входит в цикл событий (eventloop). Во время работы приложения на Qt события генерируются и отправляются виджетам. Примерами событий могут служить нажатия кнопок мыши или ввод с клавиатуры. Когда пользователь вводит текст в текстовый редактор, этот виджет получает события нажатий клавиш и отображает набранный текст на экране.

Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды:

<br />qmake <s>project<br />qmake<br />make<br />


Так как утилита qmake может работать в двух режимах для создания Makefile или для создания .pro файла, мы должны импользовать ее два раза.

После этого в каталоге появится исполняемый файл (обратите внимание, что в Windows вместо make необходимо выполнить nmake и исполняемый файл будет в подкаталоге debug или release). qmake – это инструмент Qt для сборки приложения, использующий конфигурационный файл, который создается при запуске qmake с ключом project. Используя заданный конфигурационный файл (файл с расширением .pro), qmake создаёт файл для утилиты make, которая будет собирать ваше приложение. Мы рассмотрим написание собственных .pro файлов позже.
h3. Дополнительная информация
|Тема|Статья|
|Виджеты и геометрия окна|"Window and Dialog Widgets&quot;:http://doc.qt.nokia.com/4.7/application-windows.html%7C
|События и их обработка|"The Event System&quot;:http://doc.qt.nokia.com/4.7/eventsandfilters.html%7C


h2. Добавление кнопки выхода
В настоящем приложении обычно требуется более одного виджета. Добавим кнопку ("QPushButton&quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html) под текстовым редактором. Кнопка будет закрывать Блокнот при нажатии на неё.
p=. Кнопка выход


Давайте взглянем на код.

<br />#include &lt;QtGui&amp;gt;
<br />int main(int argv, char **args)<br />{<br /> QApplication app(argv, args);
<br /> QTextEdit textEdit;<br /> QPushButton quitButton(&quot;Quit&amp;quot;);
<br /> QObject::connect(&amp;quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
<br /> QVBoxLayout layout;<br /> layout.addWidget(&amp;textEdit);<br /> layout.addWidget(&amp;quitButton);
<br /> QWidget window;<br /> window.setLayout(&amp;layout);
<br /> window.show();
<br /> return app.exec&amp;amp;#40;&amp;#41;;<br />}<br />


На первой строке мы включаем "QtGui&quot;:http://doc.qt.nokia.com/4.7/qtgui.html – заголовочный файл, содержащий все классы графического интерфейса пользователя Qt.
На строке 10 используется механизм сигналов и слотов Qt для выхода из приложения при нажатии кнопки Quit. Слот это функция, которая может быть вызвана во время выполнения программы (runtime) с помощью её имени (в виде строки). Сигнал это функция, которая вызывает связанные с ней слоты; мы называем это подключением слота к сигналу (connect) и отправкой сигнала (emit).
"quit()":http://doc.qt.nokia.com/4.7/qcoreapplication.html#quit — это слот "QApplication&quot;:http://doc.qt.nokia.com/4.7/qapplication.html, который закрывает приложение. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked – это сигнал, посылаемый кнопкой ("QPushButton&quot;:http://doc.qt.nokia.com/4.7/qpushbutton.html) при нажатии. Статическая функция "QObject::connect()":http://doc.qt.nokia.com/4.7/qobject.html#connect соединяет сигнал со слотом. SIGNAL и SLOT это два макроса, которые принимают сигнатуры соединяемых функций сигнала и слота. Также необходимо передать указатели на соединяемые объекты.
На строке 12 создаётся вертикальный компоновщик ("QVBoxLayout&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html). Как было сказано выше, виджеты могут содержать другие виджеты. Можно явно указать границы (расположение и размер) дочерних виджетов, но удобнее использовать компоновщик (layout). Компоновщик управляет границами дочерних виджетов. "QVBoxLayout&quot;:http://doc.qt.nokia.com/4.7/qvboxlayout.html, например, размещает дочерние виджеты вертикально.
На строках 13 и 14 текстовый редактор и кнопка добавляются в компоновщик. На строке 17 компоновщик устанавливается на виджет.
h3. Дополнительная информация
|Тема|Статья|
|Сигналы и слоты|"Signals & Slots&quot;:http://doc.qt.nokia.com/4.7/signalsandslots.html%7C
|Компоновки|"Layout Management&quot;:http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts&quot;:http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples&quot;:http://doc.qt.nokia.com/4.7/examples-layouts.html%7C
|Виджеты Qt|"Qt Widget Gallery&quot;:http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples&quot;:http://doc.qt.nokia.com/4.7/examples-widgets.html%7C
h2. Наследование QWidget
Представим, что при выходе пользователя из приложения нам надо показать диалог для подтверждения выхода. В этом примере мы наследуем "QWidget&quot;:http://doc.qt.nokia.com/4.7/qwidget.html и добавим слот, который соединим с кнопкой выхода Quit.
p=. Наследуемся от QWidget


Давайте взглянем на код:

<br />class Notepad : public QWidget<br />{<br /> Q_OBJECT
<br />public:<br /> Notepad();
<br />private slots:<br /> void quit();
<br />private:<br /> QTextEdit *textEdit;<br /> QPushButton *quitButton;<br />};<br />


Макрос Q_OBJECT должен быть первой инструкцией в объявлении класса. Этот макрос объявляет наш класс как "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html (естественно, класс должен быть унаследован от "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html). "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html добавляет несколько возможностей обычным классам C++. Например, имя класса и имена его слотов могут быть запрошены во время выполнения программы. Также можно вызывать слоты и узнавать типы их параметров.
Строка 13 объявляет слот quit(). Для объявления слотов используется макрос slots. Теперь этот слот может быть подключен к сигналам с подходящей сигнатурой (то есть к сигналам без параметров).


Вместо настройки графического интерфейса пользователя и соединения слота в функции main() мы используем конструктор класса Notepad.

<br />Notepad::Notepad()<br />{<br /> textEdit = new QTextEdit;<br /> quitButton = new QPushButton(tr(&quot;Quit&amp;quot;));
<br /> connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
<br /> QVBoxLayout '''layout = new QVBoxLayout;<br /> layout-&gt;addWidget(textEdit);<br /> layout-&gt;addWidget(quitButton);
<br /> setLayout(layout);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br />}<br />


Как видно из определения класса, используются указатели на экземпляры "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html (textEdit и quitButton). Как правило, вы всегда должны создавать наследников "QObject&quot;:http://doc.qt.nokia.com/4.7/qobject.html в динамической памяти (heap) и никогда не копировать их.
Также мы используем функцию "tr()":http://doc.qt.nokia.com/4.7/qobject.html#tr для видимых пользователю строк. Эта функция нужна когда приложение должно быть более чем на одном языке (например, на китайском и английском). Мы не будем углубляться в детали, но все подробности можно посмотреть по ссылке о Qt Linguist в дополнительной информации.
h3. Дополнительная информация
|Тема|Статья|
|tr() и интернационализация|"Qt Linguist Manual&quot;:http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation&quot;:http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr() Example&quot;:http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalization with Qt&quot;:http://doc.qt.nokia.com/4.7/internationalization.html%7C
|"QObject&quot;:http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects и объектная модель Qt (необходимо для понимания Qt)|"Object Model&quot;:http://doc.qt.nokia.com/4.7/object.html%7C
|qmake и система сборки Qt|"qmake Manual&quot;:http://doc.qt.nokia.com/4.7/qmake-manual.html%7C
h3. Создание .pro файла


Для этого примера мы напишем собственный .pro файл вместо использования опции _qmake project_.

<br />HEADERS = notepad.h<br />SOURCES = notepad.cpp  main.cpp<br />


Соберем приложение:

<br />qmake<br />make<br />


h2. Использование QMainWindow
Многие приложения могут выиграть от использования "QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть собственный компоновщик куда вы можете добавить меню, прикрепляемые виджеты (dock widgets), панель инструментов (tool bars) и строку состояния (status bar). У "QMainWindow&quot;:http://doc.qt.nokia.com/4.7/qmainwindow.html есть центральная область где можно разместить любой виджет. В нашем случае мы разместим там наш текстовый редактор.
p=. Используем QMainWindow


Давайте взглянем на новое определение класса Notepad.

<br />#include &lt;QtGui&amp;gt;
<br />class Notepad : public QMainWindow<br />{<br /> Q_OBJECT
<br />public:<br /> Notepad();
<br />private slots:<br /> void open();<br /> void save();<br /> void quit();
<br />private:<br /> QTextEdit *textEdit;
<br /> QAction *openAction;<br /> QAction *saveAction;<br /> QAction *exitAction;
<br /> QMenu '''fileMenu;<br />};<br />


Здесь появились еще два слота для сохранения и загрузки файла. Они будут реализованы в следующем разделе.


Часто в главном окне один и тот же слот должен быть вызван сразу несколькими виджетами. Например, элементами меню и кнопками на панели инструментов. Для упрощения подобных вещей в Qt есть "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html, который может быть использован несколькими виджетами и который может быть соединён со слотом. Например, и "QMenu&quot;:http://doc.qt.nokia.com/4.7/qmenu.html, и "QToolBar&quot;:http://doc.qt.nokia.com/4.7/qtoolbar.html могут создавать элементы меню и кнопки инструментов из одного "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html. Мы скоро увидим как это работает.
Как и ранее, для настройки графического интерфейса пользователя мы используем конструктор Notepad.

<br />Notepad::Notepad()<br />{<br /> saveAction = new QAction(tr(&quot;&amp;Open&amp;quot;), this);<br /> saveAction = new QAction(tr(&quot;&amp;Save&amp;quot;), this);<br /> exitAction = new QAction(tr(&quot;E&amp;amp;xit&amp;quot;), this);
<br /> connect(openAction, SIGNAL (triggered()), this, SLOT (open()));<br /> connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));<br /> connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
<br /> fileMenu = menuBar()<s>&gt;addMenu(tr(&quot;&amp;File&amp;quot;));<br /> fileMenu</s>&gt;addAction(openAction);<br /> fileMenu-&gt;addAction(saveAction);<br /> fileMenu-&gt;addSeparator();<br /> fileMenu-&gt;addAction(exitAction);
<br /> textEdit = new QTextEdit;<br /> setCentralWidget(textEdit);
<br /> setWindowTitle(tr(&quot;Notepad&amp;quot;));<br />}<br />


Экземпляры "QAction&quot;:http://doc.qt.nokia.com/4.7/qaction.html создаются с указанием текста, который будет отображен на виджетах (в нашем случае, на элементах меню). Если мы хотим добавить их на панель инструментов, то нам может потребоваться задать ещё и "иконки&quot;:http://doc.qt.nokia.com/4.7/qicon.html.
Теперь, когда будет выбран пункт меню, он активирует действие и вызовется соответствующий слот.
h3. Дополнительная информация
|Тема|Статья|
|Главные окна и классы главного окна|"Application Main Window&quot;:http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples&quot;:http://doc.qt.nokia.com/4.7/examples-mainwindow.html%7C
|Приложения с многодокументным интерфейсом (MDI)|"QMdiArea&quot;:http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example&quot;:http://doc.qt.nokia.com/4.7/mainwindows-mdi.html%7C
h2. Сохранение и загрузка
В этом примере мы реализуем слоты open() и save(), которые были добавлены в предыдущем примере.
p=. Открытие файла в Kubuntu


Начнем со слота open():

<br />QString fileName = QFileDialog::getOpenFileName(this, tr(&quot;Open File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp'''.h)&quot;));
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::ReadOnly)) {<br /> QMessageBox::critical(this, tr(&quot;Error&amp;quot;),<br /> tr(&quot;Could not open file&amp;quot;));<br /> return;<br /> }<br /> QString contents = file.readAll().constData();<br /> textEdit</s>&gt;setPlainText(contents);<br /> file.close();<br />}<br />


Сначала у пользователя запрашивается имя открываемого файла. В Qt есть класс "QFileDialog&quot;:http://doc.qt.nokia.com/4.7/qfiledialog.html, который является диалогом выбора файла. Выше показан такой диалог в Kubuntu. Статический метод "getOpenFileName()":http://doc.qt.nokia.com/4.7/qfiledialog.html#getOpenFileName отображает модальный диалог выбора файла и не завершается, пока пользователь не выберет файл. Он возвращает путь к выбранному файлу или пустую строку, если пользователь отменил диалог.
Если пользователь выбрал файл, то попробуем его открыть с помощью метода "open()":http://doc.qt.nokia.com/4.7/qiodevice.html#open, который возвращает истину в случае успеха. Мы не будем углубляться в обработку ошибок (подробнее про них можно почитать в дополнительной информации). Если не удалось открыть файл, то отображается диалог "QMessageBox&quot;:http://doc.qt.nokia.com/4.7/qmessagebox.html с сообщением об ошибке.
Фактически, чтение данных выполняется с помощью одного метода "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, который возвращает все содержимое файла в "QByteArray&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html. Метод "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData возвращает содержимое "QByteArray&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html в виде const char, для которого у "QString&quot;:http://doc.qt.nokia.com/4.7/qstring.html есть конструктор. Затем содержимое файла отображается в текстовом редакторе. В конце работы вызывается метод "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close который закроет файл и вернет файловый дескриптор операционной системе.


Рассмотрим слот save():

<br />QString fileName = QFileDialog::getSaveFileName(this, tr(&quot;Save File&amp;quot;), &quot;&quot;,<br /> tr(&quot;Text Files ('''.txt);;C++ Files ('''.cpp *.h)&quot;));
<br />if (fileName != &quot;&quot;) {<br /> QFile file&amp;amp;#40;fileName&amp;amp;#41;;<br /> if (!file.open(QIODevice::WriteOnly)) {<br /> // error message<br /> } else {<br /> QTextStream stream(&amp;file);<br /> stream &lt;&lt; textEdit</s>&gt;toPlainText();<br /> stream.flush();<br /> file.close();<br /> }<br />}<br />

Для записи данных в файл воспользуемся классом "QTextStream&quot;:http://doc.qt.nokia.com/4.7/qtextstream.html (текстовый поток), который в нашем случае будет оберткой над экземпляром "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html. Текстовый поток может записывать "QString&quot;:http://doc.qt.nokia.com/4.7/qstring.html непосредственно в файл; "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html же принимает лишь сырые данные (char*) или "QByteArray&quot;:http://doc.qt.nokia.com/4.7/qbytearray.html с помощью методов "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write класса-предка "QIODevice&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html.

Дополнительная информация

Тема Статья
Файлы и устройства ввода-вывода "QFile&quot;:http://doc.qt.nokia.com/4.7/qfile.html, "QIODevice&quot;:http://doc.qt.nokia.com/4.7/qiodevice.html