GettingStartedWithQtRussian: Difference between revisions
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
[toc align_right= | [toc align_right="yes" depth="2"] | ||
= Начало работы с Qt = | = Начало работы с Qt = | ||
Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (''toolkit'') для разработки графического интерфейса пользователя (''GUI''). В данном руководстве мы изучим основы Qt, написав простое приложение | Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (''toolkit'') для разработки графического интерфейса пользователя (''GUI''). В данном руководстве мы изучим основы Qt, написав простое приложение "Блокнот". После прочтения этого руководства вы сможете лучше ориентироваться в документации и найти там всю необходимую информацию для разработки своих приложений. | ||
== Привет, Блокнот! == | == Привет, Блокнот! == | ||
В качестве первого примера создадим и отобразим текстовый редактор ( | В качестве первого примера создадим и отобразим текстовый редактор ("QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html). Это, пожалуй, самая простая программа на Qt с графическим интерфейсом пользователя, которая только может существовать. | ||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Самое простое приложение на Qt]] | p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs1.png|Самое простое приложение на Qt]] | ||
Исходный код: | Исходный код: | ||
<code> | |||
#include <QApplication> | |||
#include <QTextEdit> | |||
int main(int argv, char **args) | int main(int argv, char **args) | ||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | QTextEdit textEdit; | ||
textEdit.show(); | |||
return app.exec | return app.exec();; | ||
} | |||
</code> | |||
Давайте рассмотрим каждую строку кода. На первых двух строках мы подключаем заголовочные файлы для "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html и "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html – двух классов которые потребуются для этого примера. Для каждого класса Qt есть заголовочный файл с соответствующим именем. | |||
На строке 6 создается экземпляр | На строке 6 создается экземпляр "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html. Этот объект управляет ресурсами уровня приложения и необходим для запуска любой программы на Qt с графическим интерфейсом. Ему необходимо передать ''argv'' и ''args'', так как Qt может принимать некоторые параметры командной строки. | ||
На строке 8 создаётся экземпляр текстового редактора | На строке 8 создаётся экземпляр текстового редактора "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Текстовый редактор – это графический элемент интерфейса пользователя. В Qt мы называем такие элементы виджетами. Примерами других виджетов являются полосы прокрутки (''scroll bars''), метки (''labels'') и переключатели (''radio buttons''). Виджет также может быть контейнером для других виджетов, например, диалог или главное окно приложения. | ||
На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, | На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть панели инструментов (''toolbars''), меню, строка состояния (''status bar'') и другие виджеты), то можно показать отдельный виджет как полноценное окно. По умолчанию виджеты скрыты; метод "show()":http://doc.qt.nokia.com/4.7/qwidget.html#show делает их видимыми. | ||
На строке 11 | На строке 11 "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html входит в цикл событий (''eventloop''). Во время работы приложения на Qt события генерируются и отправляются виджетам. Примерами событий могут служить нажатия кнопок мыши или ввод с клавиатуры. Когда пользователь вводит текст в текстовый редактор, этот виджет получает события нажатий клавиш и отображает набранный текст на экране. | ||
Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды: | Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды: | ||
<code> | |||
qmake -project | |||
qmake | |||
make | |||
</code> | |||
Так как утилита qmake может работать в двух режимах- для создания Makefile или для создания .pro файла, мы должны импользовать ее два раза. | |||
После этого в каталоге появится исполняемый файл (обратите внимание, что в Windows вместо ''make'' необходимо выполнить ''nmake'' и исполняемый файл будет в подкаталоге ''debug'' или ''release''). ''qmake'' – это инструмент Qt для сборки приложения, использующий конфигурационный файл, который создается при запуске ''qmake'' с ключом -project. Используя заданный конфигурационный файл (файл с расширением .pro), ''qmake'' создаёт файл для утилиты ''make'', которая будет собирать ваше приложение. Мы рассмотрим написание собственных .pro файлов позже. | |||
Для | h3. Дополнительная информация | ||
|Тема|Статья| | |||
|Виджеты и геометрия окна|"Window and Dialog Widgets":http://doc.qt.nokia.com/4.7/application-windows.html| | |||
|События и их обработка|"The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html| | |||
h2. Добавление кнопки выхода | |||
В настоящем приложении обычно требуется более одного виджета. Добавим кнопку ("QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html) под текстовым редактором. Кнопка будет закрывать Блокнот при нажатии на неё. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs2.png|Кнопка выход]] | |||
Давайте взглянем на код. | |||
<code> | |||
#include <QtGui> | |||
int main(int argv, char **args) | |||
{ | |||
QApplication app(argv, args); | |||
QTextEdit textEdit; | |||
QPushButton quitButton("Quit"); | |||
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit())); | |||
QVBoxLayout layout; | |||
layout.addWidget(&textEdit); | |||
layout.addWidget(&quitButton); | |||
QWidget window; | |||
window.setLayout(&layout); | |||
window.show(); | |||
return app.exec(); | |||
} | |||
</code> | |||
На первой строке мы включаем "QtGui":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":http://doc.qt.nokia.com/4.7/qapplication.html, который закрывает приложение. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked – это сигнал, посылаемый кнопкой ("QPushButton":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":http://doc.qt.nokia.com/4.7/qvboxlayout.html). Как было сказано выше, виджеты могут содержать другие виджеты. Можно явно указать границы (расположение и размер) дочерних виджетов, но удобнее использовать компоновщик (''layout''). Компоновщик управляет границами дочерних виджетов. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, например, размещает дочерние виджеты вертикально. | |||
На строках 13 и 14 текстовый редактор и кнопка добавляются в компоновщик. На строке 17 компоновщик устанавливается на виджет. | |||
h3. Дополнительная информация | |||
|Тема|Статья| | |||
|Сигналы и слоты|"Signals & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html| | |||
|Компоновки|"Layout Management":http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples":http://doc.qt.nokia.com/4.7/examples-layouts.html| | |||
|Виджеты Qt|"Qt Widget Gallery":http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples":http://doc.qt.nokia.com/4.7/examples-widgets.html| | |||
h2. Наследование QWidget | |||
Представим, что при выходе пользователя из приложения нам надо показать диалог для подтверждения выхода. В этом примере мы наследуем "QWidget":http://doc.qt.nokia.com/4.7/qwidget.html и добавим слот, который соединим с кнопкой выхода '''Quit'''. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs3.png|Наследуемся от QWidget]] | |||
Давайте взглянем на код: | |||
<code> | |||
class Notepad : public QWidget | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QPushButton *quitButton; | |||
}; | |||
</code> | |||
Макрос ''Q_OBJECT'' должен быть первой инструкцией в объявлении класса. Этот макрос объявляет наш класс как "QObject":http://doc.qt.nokia.com/4.7/qobject.html (естественно, класс должен быть унаследован от "QObject":http://doc.qt.nokia.com/4.7/qobject.html). "QObject":http://doc.qt.nokia.com/4.7/qobject.html добавляет несколько возможностей обычным классам C++. Например, имя класса и имена его слотов могут быть запрошены во время выполнения программы. Также можно вызывать слоты и узнавать типы их параметров. | |||
Строка 13 объявляет слот ''quit()''. Для объявления слотов используется макрос ''slots''. Теперь этот слот может быть подключен к сигналам с подходящей сигнатурой (то есть к сигналам без параметров). | |||
Вместо настройки графического интерфейса пользователя и соединения слота в функции ''main()'' мы используем конструктор класса Notepad. | |||
<code> | |||
Notepad::Notepad() | |||
{ | |||
textEdit = new QTextEdit; | |||
quitButton = new QPushButton(tr("Quit")); | |||
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit())); | |||
QVBoxLayout '''layout = new QVBoxLayout; | |||
layout->addWidget(textEdit); | |||
layout->addWidget(quitButton); | |||
setLayout(layout); | |||
setWindowTitle(tr("Notepad")); | |||
} | |||
</code> | |||
Как видно из определения класса, используются указатели на экземпляры "QObject":http://doc.qt.nokia.com/4.7/qobject.html (''textEdit'' и ''quitButton''). Как правило, вы всегда должны создавать наследников "QObject":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":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr() Example":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalization with Qt":http://doc.qt.nokia.com/4.7/internationalization.html| | |||
|"QObject":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects и объектная модель Qt (необходимо для понимания Qt)|"Object Model":http://doc.qt.nokia.com/4.7/object.html| | |||
|qmake и система сборки Qt|"qmake Manual":http://doc.qt.nokia.com/4.7/qmake-manual.html| | |||
h3. Создание .pro файла | |||
Для этого примера мы напишем собственный .pro файл вместо использования опции _qmake -project_. | |||
<code> | |||
HEADERS = notepad.h | |||
SOURCES = notepad.cpp main.cpp | |||
</code> | |||
Соберем приложение: | |||
<code> | |||
qmake | |||
make | |||
</code> | |||
h2. Использование QMainWindow | |||
Многие приложения могут выиграть от использования "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть собственный компоновщик куда вы можете добавить меню, прикрепляемые виджеты (''dock widgets''), панель инструментов (''tool bars'') и строку состояния (''status bar''). У "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html есть центральная область где можно разместить любой виджет. В нашем случае мы разместим там наш текстовый редактор. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs4.png|Используем QMainWindow]] | |||
Давайте взглянем на новое определение класса Notepad. | |||
<code> | |||
#include <QtGui> | |||
class Notepad : public QMainWindow | |||
{ | |||
Q_OBJECT | |||
public: | |||
Notepad(); | |||
private slots: | |||
void open(); | |||
void save(); | |||
void quit(); | |||
private: | |||
QTextEdit *textEdit; | |||
QAction *openAction; | |||
QAction *saveAction; | |||
QAction *exitAction; | |||
QMenu '''fileMenu; | |||
}; | |||
</code> | |||
Здесь появились еще два слота для сохранения и загрузки файла. Они будут реализованы в следующем разделе. | |||
Часто в главном окне один и тот же слот должен быть вызван сразу несколькими виджетами. Например, элементами меню и кнопками на панели инструментов. Для упрощения подобных вещей в Qt есть "QAction":http://doc.qt.nokia.com/4.7/qaction.html, который может быть использован несколькими виджетами и который может быть соединён со слотом. Например, и "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html, и "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html могут создавать элементы меню и кнопки инструментов из одного "QAction":http://doc.qt.nokia.com/4.7/qaction.html. Мы скоро увидим как это работает. | |||
Как и ранее, для настройки графического интерфейса пользователя мы используем конструктор Notepad. | |||
<code> | |||
Notepad::Notepad() | |||
{ | |||
saveAction = new QAction(tr("&Open"), this); | |||
saveAction = new QAction(tr("&Save"), this); | |||
exitAction = new QAction(tr("E&amp;xit"), this); | |||
connect(openAction, SIGNAL (triggered()), this, SLOT (open())); | |||
connect(saveAction, SIGNAL (triggered()), this, SLOT (save())); | |||
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit())); | |||
fileMenu = menuBar()->addMenu(tr("&File")); | |||
fileMenu->addAction(openAction); | |||
fileMenu->addAction(saveAction); | |||
fileMenu->addSeparator(); | |||
fileMenu->addAction(exitAction); | |||
textEdit = new QTextEdit; | |||
setCentralWidget(textEdit); | |||
setWindowTitle(tr("Notepad")); | |||
} | |||
</code> | |||
Экземпляры "QAction":http://doc.qt.nokia.com/4.7/qaction.html создаются с указанием текста, который будет отображен на виджетах (в нашем случае, на элементах меню). Если мы хотим добавить их на панель инструментов, то нам может потребоваться задать ещё и "иконки":http://doc.qt.nokia.com/4.7/qicon.html. | |||
Теперь, когда будет выбран пункт меню, он активирует действие и вызовется соответствующий слот. | |||
h3. Дополнительная информация | |||
|Тема|Статья| | |||
|Главные окна и классы главного окна|"Application Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples":http://doc.qt.nokia.com/4.7/examples-mainwindow.html| | |||
|Приложения с многодокументным интерфейсом (MDI)|"QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html| | |||
h2. Сохранение и загрузка | |||
В этом примере мы реализуем слоты ''open()'' и ''save()'', которые были добавлены в предыдущем примере. | |||
p=. [[Image:http://doc.qt.nokia.com/4.7/images/gs5.png|Открытие файла в Kubuntu]] | |||
Начнем со слота ''open()'': | |||
<code> | |||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "", | |||
tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::ReadOnly)) { | |||
QMessageBox::critical(this, tr("Error"), | |||
tr("Could not open file")); | |||
return; | |||
} | |||
QString contents = file.readAll().constData(); | |||
textEdit->setPlainText(contents); | |||
file.close(); | |||
} | |||
</code> | |||
Сначала у пользователя запрашивается имя открываемого файла. В Qt есть класс "QFileDialog":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":http://doc.qt.nokia.com/4.7/qmessagebox.html с сообщением об ошибке. | |||
Фактически, чтение данных выполняется с помощью одного метода "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, который возвращает все содержимое файла в "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. Метод "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData возвращает содержимое "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html в виде const char''', для которого у "QString":http://doc.qt.nokia.com/4.7/qstring.html есть конструктор. Затем содержимое файла отображается в текстовом редакторе. В конце работы вызывается метод "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close который закроет файл и вернет файловый дескриптор операционной системе. | |||
Рассмотрим слот ''save()'': | |||
<code> | |||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "", | |||
tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)")); | |||
if (fileName != "") { | |||
QFile file(fileName); | |||
if (!file.open(QIODevice::WriteOnly)) { | |||
// error message | |||
} else { | |||
QTextStream stream(&file); | |||
stream << textEdit->toPlainText(); | |||
stream.flush(); | |||
file.close(); | |||
} | |||
} | |||
</code> | |||
Для записи данных в файл воспользуемся классом "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html (текстовый поток), который в нашем случае будет оберткой над экземпляром "QFile":http://doc.qt.nokia.com/4.7/qfile.html. Текстовый поток может записывать "QString":http://doc.qt.nokia.com/4.7/qstring.html непосредственно в файл; "QFile":http://doc.qt.nokia.com/4.7/qfile.html же принимает лишь сырые данные (''char*'') или "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html с помощью методов "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write класса-предка "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html. | |||
=== Дополнительная информация === | === Дополнительная информация === | ||
Line 113: | Line 303: | ||
|- | |- | ||
|Файлы и устройства ввода-вывода | |Файлы и устройства ввода-вывода | ||
| | |"QFile":http://doc.qt.nokia.com/4.7/qfile.html, "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html | ||
|} | |} |
Revision as of 09:08, 25 February 2015
[toc align_right="yes" depth="2"]
Начало работы с Qt
Добро пожаловать в мир Qt — кроссплатформенного набора инструментов (toolkit) для разработки графического интерфейса пользователя (GUI). В данном руководстве мы изучим основы Qt, написав простое приложение "Блокнот". После прочтения этого руководства вы сможете лучше ориентироваться в документации и найти там всю необходимую информацию для разработки своих приложений.
Привет, Блокнот!
В качестве первого примера создадим и отобразим текстовый редактор ("QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html). Это, пожалуй, самая простая программа на Qt с графическим интерфейсом пользователя, которая только может существовать.
p=. Самое простое приложение на Qt
Исходный код:
#include <QApplication>
#include <QTextEdit>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
textEdit.show();
return app.exec();;
}
Давайте рассмотрим каждую строку кода. На первых двух строках мы подключаем заголовочные файлы для "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html и "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html – двух классов которые потребуются для этого примера. Для каждого класса Qt есть заголовочный файл с соответствующим именем.
На строке 6 создается экземпляр "QApplication":http://doc.qt.nokia.com/4.7/qapplication.html. Этот объект управляет ресурсами уровня приложения и необходим для запуска любой программы на Qt с графическим интерфейсом. Ему необходимо передать argv и args, так как Qt может принимать некоторые параметры командной строки.
На строке 8 создаётся экземпляр текстового редактора "QTextEdit":http://doc.qt.nokia.com/4.7/qtextedit.html. Текстовый редактор – это графический элемент интерфейса пользователя. В Qt мы называем такие элементы виджетами. Примерами других виджетов являются полосы прокрутки (scroll bars), метки (labels) и переключатели (radio buttons). Виджет также может быть контейнером для других виджетов, например, диалог или главное окно приложения.
На строке 9 текстовый редактор отображается на экране. Так как виджеты также служат контейнерами (например, "QMainWindow":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":http://doc.qt.nokia.com/4.7/qapplication.html входит в цикл событий (eventloop). Во время работы приложения на Qt события генерируются и отправляются виджетам. Примерами событий могут служить нажатия кнопок мыши или ввод с клавиатуры. Когда пользователь вводит текст в текстовый редактор, этот виджет получает события нажатий клавиш и отображает набранный текст на экране.
Чтобы запустить приложение нужно в командной строке перейти в каталог с .cpp-файлом и выполнить следующие команды:
qmake -project
qmake
make
Так как утилита qmake может работать в двух режимах- для создания Makefile или для создания .pro файла, мы должны импользовать ее два раза.
После этого в каталоге появится исполняемый файл (обратите внимание, что в Windows вместо make необходимо выполнить nmake и исполняемый файл будет в подкаталоге debug или release). qmake – это инструмент Qt для сборки приложения, использующий конфигурационный файл, который создается при запуске qmake с ключом -project. Используя заданный конфигурационный файл (файл с расширением .pro), qmake создаёт файл для утилиты make, которая будет собирать ваше приложение. Мы рассмотрим написание собственных .pro файлов позже.
h3. Дополнительная информация
|Тема|Статья| |Виджеты и геометрия окна|"Window and Dialog Widgets":http://doc.qt.nokia.com/4.7/application-windows.html%7C |События и их обработка|"The Event System":http://doc.qt.nokia.com/4.7/eventsandfilters.html%7C
h2. Добавление кнопки выхода
В настоящем приложении обычно требуется более одного виджета. Добавим кнопку ("QPushButton":http://doc.qt.nokia.com/4.7/qpushbutton.html) под текстовым редактором. Кнопка будет закрывать Блокнот при нажатии на неё.
p=. Кнопка выход
Давайте взглянем на код.
#include <QtGui>
int main(int argv, char **args)
{
QApplication app(argv, args);
QTextEdit textEdit;
QPushButton quitButton("Quit");
QObject::connect(&quitButton, SIGNAL (clicked()), qApp, SLOT (quit()));
QVBoxLayout layout;
layout.addWidget(&textEdit);
layout.addWidget(&quitButton);
QWidget window;
window.setLayout(&layout);
window.show();
return app.exec();
}
На первой строке мы включаем "QtGui":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":http://doc.qt.nokia.com/4.7/qapplication.html, который закрывает приложение. "clicked()":http://doc.qt.nokia.com/4.7/qabstractbutton.html#clicked – это сигнал, посылаемый кнопкой ("QPushButton":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":http://doc.qt.nokia.com/4.7/qvboxlayout.html). Как было сказано выше, виджеты могут содержать другие виджеты. Можно явно указать границы (расположение и размер) дочерних виджетов, но удобнее использовать компоновщик (layout). Компоновщик управляет границами дочерних виджетов. "QVBoxLayout":http://doc.qt.nokia.com/4.7/qvboxlayout.html, например, размещает дочерние виджеты вертикально.
На строках 13 и 14 текстовый редактор и кнопка добавляются в компоновщик. На строке 17 компоновщик устанавливается на виджет.
h3. Дополнительная информация
|Тема|Статья| |Сигналы и слоты|"Signals & Slots":http://doc.qt.nokia.com/4.7/signalsandslots.html%7C |Компоновки|"Layout Management":http://doc.qt.nokia.com/4.7/layout.html, "Widgets and Layouts":http://doc.qt.nokia.com/4.7/widgets-and-layouts.html, "Layout Examples":http://doc.qt.nokia.com/4.7/examples-layouts.html%7C |Виджеты Qt|"Qt Widget Gallery":http://doc.qt.nokia.com/4.7/gallery.html, "Widget Examples":http://doc.qt.nokia.com/4.7/examples-widgets.html%7C
h2. Наследование QWidget
Представим, что при выходе пользователя из приложения нам надо показать диалог для подтверждения выхода. В этом примере мы наследуем "QWidget":http://doc.qt.nokia.com/4.7/qwidget.html и добавим слот, который соединим с кнопкой выхода Quit.
Давайте взглянем на код:
class Notepad : public QWidget
{
Q_OBJECT
public:
Notepad();
private slots:
void quit();
private:
QTextEdit *textEdit;
QPushButton *quitButton;
};
Макрос Q_OBJECT должен быть первой инструкцией в объявлении класса. Этот макрос объявляет наш класс как "QObject":http://doc.qt.nokia.com/4.7/qobject.html (естественно, класс должен быть унаследован от "QObject":http://doc.qt.nokia.com/4.7/qobject.html). "QObject":http://doc.qt.nokia.com/4.7/qobject.html добавляет несколько возможностей обычным классам C++. Например, имя класса и имена его слотов могут быть запрошены во время выполнения программы. Также можно вызывать слоты и узнавать типы их параметров.
Строка 13 объявляет слот quit(). Для объявления слотов используется макрос slots. Теперь этот слот может быть подключен к сигналам с подходящей сигнатурой (то есть к сигналам без параметров).
Вместо настройки графического интерфейса пользователя и соединения слота в функции main() мы используем конструктор класса Notepad.
Notepad::Notepad()
{
textEdit = new QTextEdit;
quitButton = new QPushButton(tr("Quit"));
connect(quitButton, SIGNAL (clicked()), this, SLOT (quit()));
QVBoxLayout '''layout = new QVBoxLayout;
layout->addWidget(textEdit);
layout->addWidget(quitButton);
setLayout(layout);
setWindowTitle(tr("Notepad"));
}
Как видно из определения класса, используются указатели на экземпляры "QObject":http://doc.qt.nokia.com/4.7/qobject.html (textEdit и quitButton). Как правило, вы всегда должны создавать наследников "QObject":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":http://doc.qt.nokia.com/4.7/linguist-manual.html, "Writing Source Code for Translation":http://doc.qt.nokia.com/4.7/i18n-source-translation.html, "Hello tr() Example":http://doc.qt.nokia.com/4.7/linguist-hellotr.html, "Internationalization with Qt":http://doc.qt.nokia.com/4.7/internationalization.html%7C |"QObject":http://doc.qt.nokia.com/4.7/qtwebkit-bridge.html#qobjects и объектная модель Qt (необходимо для понимания Qt)|"Object Model":http://doc.qt.nokia.com/4.7/object.html%7C |qmake и система сборки Qt|"qmake Manual":http://doc.qt.nokia.com/4.7/qmake-manual.html%7C
h3. Создание .pro файла
Для этого примера мы напишем собственный .pro файл вместо использования опции _qmake -project_.
HEADERS = notepad.h
SOURCES = notepad.cpp main.cpp
Соберем приложение:
qmake
make
h2. Использование QMainWindow
Многие приложения могут выиграть от использования "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html, у которого есть собственный компоновщик куда вы можете добавить меню, прикрепляемые виджеты (dock widgets), панель инструментов (tool bars) и строку состояния (status bar). У "QMainWindow":http://doc.qt.nokia.com/4.7/qmainwindow.html есть центральная область где можно разместить любой виджет. В нашем случае мы разместим там наш текстовый редактор.
Давайте взглянем на новое определение класса Notepad.
#include <QtGui>
class Notepad : public QMainWindow
{
Q_OBJECT
public:
Notepad();
private slots:
void open();
void save();
void quit();
private:
QTextEdit *textEdit;
QAction *openAction;
QAction *saveAction;
QAction *exitAction;
QMenu '''fileMenu;
};
Здесь появились еще два слота для сохранения и загрузки файла. Они будут реализованы в следующем разделе.
Часто в главном окне один и тот же слот должен быть вызван сразу несколькими виджетами. Например, элементами меню и кнопками на панели инструментов. Для упрощения подобных вещей в Qt есть "QAction":http://doc.qt.nokia.com/4.7/qaction.html, который может быть использован несколькими виджетами и который может быть соединён со слотом. Например, и "QMenu":http://doc.qt.nokia.com/4.7/qmenu.html, и "QToolBar":http://doc.qt.nokia.com/4.7/qtoolbar.html могут создавать элементы меню и кнопки инструментов из одного "QAction":http://doc.qt.nokia.com/4.7/qaction.html. Мы скоро увидим как это работает. Как и ранее, для настройки графического интерфейса пользователя мы используем конструктор Notepad.
Notepad::Notepad()
{
saveAction = new QAction(tr("&Open"), this);
saveAction = new QAction(tr("&Save"), this);
exitAction = new QAction(tr("E&amp;xit"), this);
connect(openAction, SIGNAL (triggered()), this, SLOT (open()));
connect(saveAction, SIGNAL (triggered()), this, SLOT (save()));
connect(exitAction, SIGNAL (triggered()), qApp, SLOT (quit()));
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
textEdit = new QTextEdit;
setCentralWidget(textEdit);
setWindowTitle(tr("Notepad"));
}
Экземпляры "QAction":http://doc.qt.nokia.com/4.7/qaction.html создаются с указанием текста, который будет отображен на виджетах (в нашем случае, на элементах меню). Если мы хотим добавить их на панель инструментов, то нам может потребоваться задать ещё и "иконки":http://doc.qt.nokia.com/4.7/qicon.html.
Теперь, когда будет выбран пункт меню, он активирует действие и вызовется соответствующий слот.
h3. Дополнительная информация
|Тема|Статья| |Главные окна и классы главного окна|"Application Main Window":http://doc.qt.nokia.com/4.7/mainwindow.html, "Main Window Examples":http://doc.qt.nokia.com/4.7/examples-mainwindow.html%7C |Приложения с многодокументным интерфейсом (MDI)|"QMdiArea":http://doc.qt.nokia.com/4.7/qmdiarea.html, "MDI Example":http://doc.qt.nokia.com/4.7/mainwindows-mdi.html%7C
h2. Сохранение и загрузка
В этом примере мы реализуем слоты open() и save(), которые были добавлены в предыдущем примере.
Начнем со слота open():
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp'''.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
QMessageBox::critical(this, tr("Error"),
tr("Could not open file"));
return;
}
QString contents = file.readAll().constData();
textEdit->setPlainText(contents);
file.close();
}
Сначала у пользователя запрашивается имя открываемого файла. В Qt есть класс "QFileDialog":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":http://doc.qt.nokia.com/4.7/qmessagebox.html с сообщением об ошибке.
Фактически, чтение данных выполняется с помощью одного метода "readAll()":http://doc.qt.nokia.com/4.7/qiodevice.html#readAll, который возвращает все содержимое файла в "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html. Метод "constData()":http://doc.qt.nokia.com/4.7/qbytearray.html#constData возвращает содержимое "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html в виде const char, для которого у "QString":http://doc.qt.nokia.com/4.7/qstring.html есть конструктор. Затем содержимое файла отображается в текстовом редакторе. В конце работы вызывается метод "close()":http://doc.qt.nokia.com/4.7/qiodevice.html#close который закроет файл и вернет файловый дескриптор операционной системе.
Рассмотрим слот save():
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "",
tr("Text Files ('''.txt);;C++ Files ('''.cpp *.h)"));
if (fileName != "") {
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
// error message
} else {
QTextStream stream(&file);
stream << textEdit->toPlainText();
stream.flush();
file.close();
}
}
Для записи данных в файл воспользуемся классом "QTextStream":http://doc.qt.nokia.com/4.7/qtextstream.html (текстовый поток), который в нашем случае будет оберткой над экземпляром "QFile":http://doc.qt.nokia.com/4.7/qfile.html. Текстовый поток может записывать "QString":http://doc.qt.nokia.com/4.7/qstring.html непосредственно в файл; "QFile":http://doc.qt.nokia.com/4.7/qfile.html же принимает лишь сырые данные (char*) или "QByteArray":http://doc.qt.nokia.com/4.7/qbytearray.html с помощью методов "write()":http://doc.qt.nokia.com/4.7/qiodevice.html#write класса-предка "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html.
Дополнительная информация
Тема | Статья |
Файлы и устройства ввода-вывода | "QFile":http://doc.qt.nokia.com/4.7/qfile.html, "QIODevice":http://doc.qt.nokia.com/4.7/qiodevice.html |