2009-2-3
第三章 创建主窗口
本章将教你如何使用Qt创建主窗口。
最终你将能够创建有菜单、工具栏、状态栏,并有相应的对话框的应用。
一个主窗口提供了应用程序的框架。本周将以一个电子表格应用为例。这个电子表格应用将使用我们在第二章创建的Find,Go to Cell,Sort对话框。
继承QMainWindow(Subclassing QMainWindow)
一个应用的主窗口通过集成QMainWindow创建。第二章中关于对话框的很多技术对窗口也适用,因为QDialog和QMainWindow都是继承自QWidget.
主窗口可以通过Qt Designer创建,但是本章我们将完全编码以演示如何手工完成。如果你细化图形化工具,请参考随机文档的"Creating Main Windows in Qt Designer"
表格应用包括mainwindow.h, mainwidow.cpp两个文件。
让我们从头文件开始:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QAction;
class QLabel;
class FindDialog;
class Spreadsheet;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
protected:
void closeEvent(QCloseEvent *event);
首先定义了QMainWindow的子类MainWindow.这个子类包括Q_OBJECT宏以提供自己的signals和slots.
closeEvent()函数是QWidget的虚函数,当关闭window时会自动调用。在MainWindow重新实现以便我们能够输出一个询问对话框"你是否想保存修改?"并保存用户参数到磁盘。
private slots:
void newFile();
void open();
bool save();
bool saveAs();
void find();
void goToCell();
void sort();
void abort();
一些菜单选项,比如File|New和Help|About在MainWindow中作为私有slots实现。许多slots的返回值是void,但save(),saveAs返回bool.作为响应signal执行的时候,slot返回值没有意义被忽略,但当slot作为不同函数被调用时,返回值就有意义了。
void openRecentFile();
void updateStatusBar();
void spreadsheetModified();
private:
void createActions();
void createMenus();
void createContextMenu();
void createToolBars();
void createStatusBar();
void readSettings();
void writeSettings();
bool okToContinue();
bool loadFile(const QString &fileName);
bool saveFile(const QString &fileName);
void setCurrentFile(const QString *fileName);
void updateRecentFileActions();
QString strippedName(const QString &fullFileName);
main window需要一些private slot和一些private function来支持用户接口。
Spreadsheet *spreadsheet;
FindDialog *findDialog;
QLabel *locationLabel;
QLabel *formulaLabel;
QStringList recentFiles;
QString curFile;
enum { MaxRecentFiles = 5 };
QAction *recentFileActions[MaxRecentFiles];
QAction *separatorAction;
QMenu *fileMenu;
QMenu *editMenu;
...
QToolBar *fileToolBar;
QToolBar *editToolBar;
QAction *newAction;
QAction *openAction;
...
QAction *aboutQtAction;
};
#endif
下面看看实现文件:
#include <QtGui>
#include "finddialog.h"
#include "gotocelldialog.h"
#include "mainwindow.h"
#include "sortdialog.h"
#include "spreadsheet.h"
包含<QtGui>,启动定义了所有的Qt类,还包含若干第二章的头文件。
MainWindow::MainWindow()
{
spreadsheet = new Spreadsheet;
setCentralWidget(spreadsheet);
createActions();
createMenus();
createContextMenu();
createToolBars();
createStatusBar();
readSettings();
findDialog = 0;
setWindowIcon(QIcon(":/images/icon.png"));
setCurrentFile("");
}
构造方法中,首先创建一个Spreadsheet构件并设置为主窗口的中心组件。 中心组件占据了main window的中心。Spreadsheet是QTableWidget的子类,增加了一些电子表格的功能,如支持电子表格公式。我们在第四章实现。
我们调用私有方法createActions(),createMenus(),createContextMenu(),createToolBars()和createStatusBar()来设置main window的其余部分。我们也调用私有方法readSettings()来读应用存储的设置信息。
我们初始化findDialog指针为空。第一次MainWindow::find()调用时,我们将创建FindDialog对象。
构造函数的最后,我们设置窗口的icon为icon.png. Qt支持许多image format,包括BMP,GIP,JPEG,PNM,SVG,TIFF,XBM,XPM.调用QWidget::setWindowIcon()设置窗口右上角的图标。不幸的是,没有平台独立的方法设置图标。(为什么?)
GUI应用通常有许多images。有许多方法可以提供image:
--存储images到一个文件并在运行时load;
--在源代码中包含XPM文件;
--使用Qt的resource技术;(难道和MFC类似?)
本例使用resource技术。为了使用resource,我们需要创建一个resourcer文件并在.pro中增加一行标识资源文件。本例中资源文件为spreadsheet.qrc,于是在.pro中增加:
RESOURCES = spreadsheet.qrc
资源文件本身是简单的XML格式:
<RCC>
<qresource>
<file>images/icon.png</file>
...
<file>images/gotocell.png</file>
</qresource>
</RCC>
资源文件被编译到应用程序的执行文件中。当我们调用resource时,使用:/作为前最。资源可以是任意类型的文件,我们将在12章介绍如何使用。