Создание подкласса QMainWindow

Создание подкласса QMainWindow

Главное окно приложения создается в виде подкласса QMainWindow. Многие из представленных в главе 2 методов также подходят для построения главных окон, поскольку оба класса QDialog и QMainWindow являются наследниками QWidget.

Главные окна можно создавать при помощи Qt Designer, но в данной главе мы продемонстрируем, как это все делается при непосредственном программировании. Если вы предпочитаете пользоваться визуальными средствами проектирования, то необходимую информацию вы сможете найти в главе «Creating a Main Window Application» (Создание приложения на основе класса главного окна) в онлайновом руководстве по Qt Designer.

Исходный код программы главного окна приложения Электронная таблица содержится в двух файлах: mainwindow.h и mainwindow.cpp. Сначала приведем заголовочный файл:

01 #ifndef MAINWINDOW_H

02 #define MAINWINDOW_H

03 #include <QMainWindow>

04 class QAction;

05 class QLabel;

06 class FindDialog;

07 class Spreadsheet;

08 class MainWindow : public QMainWindow

09 {

10 Q_OBJECT

11 public:

12 MainWindow();

13 protected:

14 void closeEvent(QCloseEvent *event);

Мы определяем класс MainWindow как подкласс QMainWindow. Он содержит макрос Q_OBJECT, поскольку имеет собственные сигналы и слоты.

Функция closeEvent() определена в QWidget как виртуальная функция; она автоматически вызывается при закрытии окна пользователем. Она переопределяется в MainWindow для того, чтобы можно было задать пользователю стандартный вопрос относительно возможности сохранения изменений («Do you want to save your changes?») и чтобы сохранить на диске пользовательские настройки.

15 private slots:

16 void newFile();

17 void open();

18 bool save();

19 bool saveAs();

20 void find();

21 void goToCell();

22 void sort();

23 void about();

Некоторые функции меню, как, например, File | New (Файл | Создать) или Help | About (Помощь | О программе), реализованы в MainWindow в виде закрытых слотов. Большинство слотов возвращают значение типа void, однако save() и saveAs() возвращают значение типа bool. Возвращаемое значение игнорируется при выполнении слота в ответ на сигнал, но при вызове слота в качестве функции мы может воспользоваться возвращаемым значением, как это мы можем делать при вызове любой обычной функции С++.

24 void openRecentFile();

25 void updateStatusBar();

26 void spreadsheetModified();

27 private:

28 void createActions();

29 void createMenus();

30 void createContextMenu();

31 void createToolBars();

32 void createStatusBar();

33 void readSettings();

34 void writeSettings();

35 bool okToContinue();

36 bool loadFile(const QString &fileName);

37 bool saveFile(const QString &fileName);

38 void setCurrentFile(const QString &fileName);

39 void updateRecentFileActions();

40 QString strippedName(const QString &fullFileName);

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

41 Spreadsheet *spreadsheet;

42 FindDialog *findDialog;

43 QLabel *locationLabel;

44 QLabel *formulaLabel;

45 QStringList recentFiles;

46 QString curFile;

47 enum { MaxRecentFiles = 5 };

48 QAction *recentFileActions[MaxRecentFiles];

49 QAction *separatorAction;

50 QMenu *fileMenu;

51 QMenu *editMenu;

52 QToolBar *fileToolBar;

53 QToolBar *editToolBar;

54 QAction *newAction;

55 QAction *openAction;

56 QAction *aboutQtAction;

57 };

58 #endif

Кроме этих закрытых слотов и закрытых функций в подклассе MainWindow имеется также много закрытых переменных. По мере их использования мы будем объяснять их назначение.

Теперь мы кратко рассмотрим реализацию этого подкласса:

01 #include <QtGui>

02 #include "finddialog.h"

03 #include "gotocelldialog.h"

04 #include "mainwindow.h"

05 #include "sortdialog.h"

06 #include "spreadsheet.h"

Мы включаем заголовочный файл <QtGui>, который содержит определения всех классов Qt, используемых нашим подклассом. Мы также включаем некоторые пользовательские заголовочные файлы из главы 2, а именно finddialog.h, gotocelldialog.h и sortdialog.h.

07 MainWindow::MainWindow()

08 {

09 spreadsheet = new Spreadsheet;

10 setCentralWidget(spreadsheet);

11 createActions();

12 createMenus();

13 createContextMenu();

14 createToolBars();

15 createStatusBar();

16 readSettings();

17 findDialog = 0;

18 setWindowIcon(QIcon(":/images/icon.png"));

19 setCurrentFile("");

20 }

В конструкторе мы начинаем создание виджета Электронная таблица Spreadsheet и определяем его в качестве центрального виджета главного окна. Центральный виджет занимает среднюю часть главного окна (см. рис. 3.2). Класс Spreadsheet является подклассом QTableWidget, который обладает некоторыми возможностями электронной таблицы: например, он поддерживает формулы электронной таблицы. Реализацию этого класса мы рассмотрим в главе 4.

Рис. 3.2. Области главного окна QMainWindow.

Мы вызываем закрытые функции createActions(), createMenus(), createContextMenu(), createToolBars() и createStatusBar() для построения остальной части главного окна. Мы также вызываем закрытую функцию readSettings() для чтения настроек, сохраненных в приложении.

Мы инициализируем указатель findDialog в нулевое значение, а при первом вызове MainWindow::find() мы создадим объект FindDialog. B конце конструктора в качестве пиктограммы окна мы задаем PNG—файл: icon.png. Qt поддерживает многие форматы графических файлов, включая BMP, GIF[4], JPEG, PNG, PNM, XBM и XPM. Функция QWidget::setWindowIcon() устанавливает пиктограмму в левый верхний угол окна. К сожалению, не существует независимого от платформы способа установки пиктограммы приложения, отображаемого на рабочем столе компьютера. Описание этой процедуры для различных платформ можно найти в сети Интернет по адресу http://doc.trolltech.com/4.1/appicon.html.

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

• хранение изображений в файлах и загрузка их во время выполнения приложения;

• включение файлов XPM в исходный код программы; это возможно, поскольку файлы XPM являются совместимыми с файлами исходного кода С++);

• использование механизма определения ресурсов, предусмотренного в Qt.

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

Для применения системы ресурсов Qt мы должны создать файл ресурсов и добавить в файл .pro строку, которая задает этот файл ресурсов. В нашем примере мы назвали файл ресурсов spreadsheet.qrc, поэтому в файл .pro мы добавляем следующую строку:

RESOURCES = spreadsheet.qrc

Сам файл ресурсов имеет простой XML—формат. Ниже показан фрагмент из используемого нами файла ресурсов:

<!DOCTYPE RCC><RCC version="1.0">

<qresource>

<file>images/icon.png</file>

<file>images/gotocell.png</file>

</qresource>

</RCC>

Файлы ресурсов после компиляции входят в состав исполняемого модуля приложения, поэтому они не могут теряться. При ссылке на ресурсы мы используемпрефикс пути :/ (двоеточие и слеш), и именно поэтому пиктограмма задается как :/images/icon.png. Ресурсами могут быть любые файлы (не только изображения), и мы можем их использовать в большинстве случаев, когда в Qt ожидается применение имени файла. Они более подробно рассматриваются в гл. 12.