В этой главе мы рассмотрим процесс создания главного окна приложения. По прочтении ее, вы сможете построить интерфейс приложения, который будет содержать меню, панели инструментов, строку состояния и набор дополнительных диалогов.
Рисунок 3.1. Приложение -- электронная таблица.
Главное окно -- это своего рода каркас, на который "натягивается" весь пользовательский интерфейс приложения. Здесь мы рассмотрим пример создания главного окна электронной таблицы. Внешний вид нашего будущего приложения приводится на рисунке 3.1. В этом приложении мы будем использовать диалоги "Find", "Go-to-Cell" и "Sort", которые были созданы нами в Главе 2.
Внутри большинства приложений с графическим интерфейсом "прячется" код, который обеспечивает основные функциональные возможности программы, например, работа с файлами или обработка данных, представляемых пользовательским интерфейсом. В Главе 4 мы покажем -- как реализуется такого рода функциональность, на примере нашей электронной таблицы.
Главное окно любого приложения -- это класс-наследник QMainWindow. Большинство приемов, используемых при создания диалогов и о которых мы говорили в Главе 2, вполне применимы и при создании главного окна приложения.
Главное окно может быть создано в Qt Designer, но мы все будем делать "вручную", чтобы продемонстрировать процесс создания главного окна во всех деталях. Если вы предпочитаете визуальное проектирование -- прочитайте главу "Creating a Main Window Application" в справочном руководстве к Qt Designer.
Исходные тексты главного окна будут располагаться в двух файлах: mainwindow.cpp и mainwindow.cpp. Начнем с файла заголовка:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <qmainwindow.h>
#include <qstringlist.h>
class QAction;
class QLabel;
class FindDialog;
class Spreadsheet;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0, const char *name = 0);
protected:
void closeEvent(QCloseEvent *event);
void contextMenuEvent(QContextMenuEvent *event);
Это определение класса MainWindow --
наследника QMainWindow. Оно содержит макрос
Q_OBJECT, поскольку реализует свои
собственные сигналы и слоты.Функция closeEvent(), в классе QWidget, объявлена как виртуальная. Она автоматически вызывается перед завершением приложения. Мы перекрываем ее в MainWindow для того, чтобы иметь возможность спросить у пользователя -- желает ли он сохранить произведенные изменения, а также для того, чтобы сохранить на диск пользовательские настройки.
Аналогично, функция contextMenuEvent() вызывается, когда пользователь щелкает правой кнопкой мыши по виджету. Мы перекрываем ее в MainWindow для того, чтобы вывести контекстное меню.
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void find();
void goToCell();
void sort();
void about();
Реализация действий некоторых пунктов меню, таких как
File|New и
Help|About, выполнена в виде приватных слотов MainWindow. Большинство слотов имеют тип
void, но слоты save() и saveAs
возвращают результат типа bool.
Значение, возвращаемое слотом, игнорируется в случае вызова по
сигналу, но когда слот вызывается как обычная функция, то мы
получаем от него возвращаемое значение, которое можем
использовать для своих нужд.
void updateCellIndicators();
void spreadsheetModified();
void openRecentFile(int param);
private:
void createActions();
void createMenus();
void createToolBars();
void createStatusBar();
void readSettings();
void writeSettings();
bool maybeSave();
void loadFile(const QString &fileName);
void saveFile(const QString &fileName);
void setCurrentFile(const QString &fileName);
void updateRecentFileItems();
QString strippedName(const QString &fullFileName);
Дополнительные приватные функции, необходимые для обслуживания
пользовательского интерфейса.
Spreadsheet *spreadsheet;
FindDialog *findDialog;
QLabel *locationLabel;
QLabel *formulaLabel;
QLabel *modLabel;
QStringList recentFiles;
QString curFile;
QString fileFilters;
bool modified;
enum { MaxRecentFiles = 5 };
int recentFileIds[MaxRecentFiles];
QPopupMenu *fileMenu;
QPopupMenu *editMenu;
QPopupMenu *selectSubMenu;
QPopupMenu *toolsMenu;
QPopupMenu *optionsMenu;
QPopupMenu *helpMenu;
QToolBar *fileToolBar;
QToolBar *editToolBar;
QAction *newAct;
QAction *openAct;
QAction *saveAct;
...
QAction *aboutAct;
QAction *aboutQtAct;
};
#endif
Кроме функций, класс главного окна имеет ряд скрытых переменных.
Все они будут описаны по мере необходимости.Теперь перейдем к реализации:
#include <qaction.h>
#include <qapplication.h>
#include <qcombobox.h>
#include <qfiledialog.h>
#include <qlabel.h>
#include <qlineedit.h>
#include <qmenubar.h>
#include <qmessagebox.h>
#include <qpopupmenu.h>
#include <qsettings.h>
#include <qstatusbar.h>
#include "cell.h"
#include "finddialog.h"
#include "gotocelldialog.h"
#include "mainwindow.h"
#include "sortdialog.h"
#include "spreadsheet.h"
Здесь подключаются заголовки всех классов Qt, которые
используются в приложении, а также заголовок класса главного окна и ряд
других заголовочных файлов, таких как finddialog.h, gotocelldialog.h и
sortdialog.h, которые мы создали в предыдущей главе.
MainWindow::MainWindow(QWidget *parent, const char *name)
: QMainWindow(parent, name)
{
spreadsheet = new Spreadsheet(this);
setCentralWidget(spreadsheet);
createActions();
createMenus();
createToolBars();
createStatusBar();
readSettings();
setCaption(tr("Spreadsheet"));
setIcon(QPixmap::fromMimeSource("icon.png"));
findDialog = 0;
fileFilters = tr("Spreadsheet files (*.sp)");
modified = false;
}
Конструктор начинается с создания виджета
Spreadsheet, который будет центральным виджетом
главного окна. Центральный виджет занимает все пространство,
находящееся между панелью инструментов (toolbar) и строкой
состояния (statusbar). Класс Spreadsheet является потомком класса QTable и добавляет некоторые свойства,
характерные для электронных таблиц. Среди них можно назвать
поддержку формул, которая будет реализована в Главе 4.Рисунок 3.2. Раскладка виджетов в главном окне.
Далее вызываются приватные функции createActions(), createMenus(), createToolBars() и createStatusBar(), которые создают остальную часть главного окна. Для восстановления пользовательских настроек вызывается функция readSettings().
В качестве иконки приложения устанавливается icon.png. Qt поддерживает различные форматы графических файлов, включая BMP, GIF [1] , JPEG, MNG, PNG, PNM, XBM и XPM. Вызов QWidget::setIcon() выводит иконку в верхний левый угол окна. К сожалению, отсутствует платформо-независимый способ помещения иконки на рабочий стол.
Программы с графическим интерфейсом обычно используют достаточно большое число изображений. Qt, в свою очередь, предоставляет значительное число методов работы с изображениями в приложениях. Наиболее употребимые из них:
Сохранение изображений в файлы и загрузка из файлов, в процессе работы приложения.
Включение изображений формата XPM в исходный код.
Механизм "коллекции изображений" ("image collection").
В данном примере мы будем использовать механизм "коллекции изображений", поскольку работать с ним намного проще, чем загружать файлы в процессе исполнения. К тому же он может взаимодействовать со всеми, поддерживаемыми библиотекой, графическими форматами. Все изображения мы будем хранить в каталоге images. Чтобы создать файл на языке C++ (он будет создан утилитой uic), который будет хранить наши изображения, добавим следующие строки в файл .pro:
IMAGES = images/icon.png \
images/new.png \
images/open.png \
...
images/find.png \
images/gotocell.png
Изображения будут помещены в исполняемый файл приложения и могут
быть получены вызовом QPixmap::fromMimeSource(). Преимущество такого
способа организации хранения изображений заключается в том, что они
никогда не потеряются, поскольку находятся внутри исполняемого
файла.Если главное окно создается в Qt Designer, то вы можете использовать визуальные средства, предоставляемые построителем, для вставки изображений в коллекцию.
[1] |
Если вы проживаете в стране, чье законодательство признает патенты на программное обеспечение и где компания Unisys имеет зарегистрированный патент на алгоритм сжатия LZW, то Unisys может потребовать от вас приобрести лицензию на использование GIF. По этой причине, поддержка формата GIF в Qt по-умолчанию запрещена. Мы полагаем, что срок действия этого патента по всему миру истечет к концу 2004 года. |
Пред. | В начало | След. |
Встроенные виджеты и классы диалогов. | На уровень выше | Создание меню и панелей инструментов. |