精通Qt4编程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

4.3 代码创建主窗口

前面详细阐述了如何在Qt设计器中绘制应用程序的主窗口,这种方法的特点是直观形象,所见即所得。现在通过手写代码实现应用程序主窗口的创建,有时候手动创建主窗口会比较快捷。之所以提供两种方法创建应用程序的主窗口,主要是为了进行互补。程序员在创建应用程序主窗口的时候,在开发程序的不同阶段,可以有一种选择。如果读者仅仅对Qt设计器绘制主窗口感兴趣,完全可以忽略本小节。

首先,创建一个名字为“codemainwindow”的新的KDevelop工程(源码路径为chapter04/codemainwindow)。修改src目录下主程序文件codemainwindow.cpp,内容和designmainwindow.cpp的完全相同。

下面依次为工程添加资源文件和主窗口的实现类。

4.3.1 创建资源文件

在新建KDevelop工程的src目录下创建新的目录images。接着,将必要的图标资源复制到images目录下。然后,在images目录下创建资源文件mainwindow.qrc文件,编辑该文件添加相应的图标资源。mainwindow.qrc的内容如下。

        <RCC>
        <qresource>
                <file>asave.png</file>
                <file>copy.png</file>
                <file>cut.png</file>
                <file>new.png</file>
                <file>open.png</file>
                <file>paste.png</file>
                <file>save.png</file>
                <file>undo.png</file>
        </qresource>
        </RCC>

4.3.2 定义主窗口类

为KDevelop工程添加新的头文件mainwindow.h,该文件给出了主窗口类CMainWindow的定义。文件内容如下所示。

        // chapter04/codemainwindow/src/mainwindow.h.
        #ifndef _MAINWINDOW_H_
        #define _MAINWINDOW_H_

        #include <QMainWindow>
        class QTextEdit;
        class CMainWindow : public QMainWindow
        {
            Q_OBJECT
        public:
            CMainWindow(QWidget* = 0);
        private:
            QMenu*      menu_F;
            QMenu*      menu_E;
            QMenu*      menu_T;
            QToolBar*   fileToolBar;
            QToolBar*   editToolBar;
            QAction*    actNew;
            QAction*    actOpen;
            QAction*    actClose;
            QAction*    actSave;
            QAction*    actASave;
            QAction*    actQuit;
            QAction*    actUndo;
            QAction*    actCut;
            QAction*    actCopy;
            QAction*    actPast;
            QAction*    actAll;
            QAction*    actFind;
            QTextEdit*  textEdit;

            void        iniMenu();
            void        iniToolBar();
            void        iniCentralWidget();
        };
        #endif

在类CMainWindow的私有区,声明了3个指向菜单的指针成员变量,分别指向文件菜单、编辑菜单和工具菜单;定义了2 个指向工具栏对象的指针,指向文件工具栏和编辑工具栏;定义了12 个指向动作的指针,以及指向菜单和工具栏的动作。这些指针将会在关联信号和槽函数等操作中使用。还定义了一个指向QTextEdit对象的指针,该QTextEdit对象是主窗口的中心部件。

私有函数iniMenu()初始化应用程序主窗口的菜单;iniToolBar()初始化应用程序主窗口的工具栏;iniCentralWidget()初始化主窗口的中心部件。

下面是主窗口类CMainWindow的实现文件mainwindow.cpp。

        // chapter04/codemainwindow/src/mainwindow.cpp.
        #include <QtGui>
        #include "mainwindow.h"

程序采用了模块化的设计,因此构造函数比较简单。

        CMainWindow::CMainWindow(QWidget* parent)
        :  QMainWindow(parent)
        {
            iniMenu();
            iniToolBar();
            iniCentralWidget();

            setWindowTitle(tr("文本编辑器"));
            showMaximized();
        }

接下来,重点看一下类CMainWindow的菜单初始化函数和工具栏初始化函数。

        void CMainWindow::iniMenu()
        {
            menu_F  = new QMenu(tr("文件(&F)"), this);
            actNew  = menu_F->addAction(QIcon(":/new.png"), tr("新建(&N)"));
            actNew->setShortcut(QKeySequence(tr("Ctrl+N")));

首先构造一个菜单QMenu对象并赋给指针menu_F,QMenu构造函数的第一个参数指定了菜单的显示文本;第二个参数指定了菜单对象的父窗口部件。

函数QMenu::addAction()添加一个新的动作到菜单的动作列表,并返回该动作对象的指针。此处,该函数具有两个参数:第一个参数构造了一个不具名的、图标为“:/new.png”的QIcon对象,前面讲过,对于不具名的常量对象的引用是合法的,“:/new.png”引用Qt资源文件中的资源;第二个参数指定了动作对象的显示文本。此外,该函数还有一个只有指定显示文本的重载函数,重载函数只指定了动作的显示文本,没有图标,在下面的代码中有用到。

函数QAction::setShortcut()为新加的动作设置快捷键,它的参数是一个不具名的QKeySequence对象。此处,QKeySequence对象构造了一个“Ctrl+N”快捷键。

注意

QMenu::addAction(QIcon(":/new.png"), tr("新建(&N)"))添加的加速键(accelerator)“N”与QAction:: setShortcut(QKeySequence(tr("Ctrl+N")))添加的快捷键(shortcut)“Ctrl + N”的不同之处。为了不至于引起混淆,笔者对加速键和快捷键的使用有意进行了约束:加速键“N”必须在文件菜单活动的状态下才有效,即在这种情况下一律使用加速键的概念;而快捷键“Ctrl + N”只要在应用程序活动的状态下就可以直接激活(此时,文中使用快捷键描述这种情况)。

接下来,创建“文件”菜单的其他动作,以及“编辑”菜单和“工具”菜单。

            actOpen = menu_F->addAction(QIcon(":/open.png"), tr("打开(&O)"));
            actOpen->setShortcut(QKeySequence(tr("Ctrl+O")));
            actClose = menu_F->addAction(tr("关闭(&C)"));
            menu_F->addSeparator();
            actSave = menu_F->addAction(QIcon(":/save.png"), tr("保存(&S)"));
            actSave->setShortcut(QKeySequence(tr("Ctrl+S")));
            actASave = menu_F->addAction(QIcon(":/asave.png"), tr("另存为(&A)"));
            menu_F->addSeparator();
            actQuit = menu_F->addAction(tr("退出(&X)"));

            menu_E = new QMenu(tr("编辑(&E)"), this);
            actUndo = menu_E->addAction(QIcon(":/undo.png"), tr("撤销(&U)"));
            actUndo->setShortcut(QKeySequence(tr("Ctrl+Z")));
            menu_E->addSeparator();
            actCut = menu_E->addAction(QIcon(":/cut.png"), tr("剪切(&C)"));
            actCut->setShortcut(QKeySequence(tr("Ctrl+X")));
            actCopy = menu_E->addAction(QIcon(":/copy.png"), tr("复制(&C)"));
            actCopy->setShortcut(QKeySequence(tr("Ctrl+C")));
            actPast = menu_E->addAction(QIcon(":/paste.png"), tr("粘贴(&P)"));
            actPast->setShortcut(QKeySequence(tr("Ctrl+V")));
            menu_E->addSeparator();
            actAll = menu_E->addAction(tr("全选(&A)"));
            actAll->setShortcut(QKeySequence(tr("Ctrl+A")));

            menu_T = new QMenu(tr("工具(&T)"), this);
            actFind =
                menu_T->addAction(QIcon(":/find.png"), tr("查找文件...(&F)"));

            QMenuBar* bar = menuBar();
            bar->addMenu(menu_F);
            bar->addMenu(menu_E);
            bar->addMenu(menu_T);
        }

函数QMainWindow::menuBar()获取主窗口的菜单栏。如果主窗口的菜单栏已经存在,该函数将返回菜单栏的指针;否则该函数将创建并返回一个新的菜单栏。

函数QMainWindow::addMenu()将前面定义好的菜单添加到主窗口的菜单栏上。

        void CMainWindow::iniToolBar()
        {
            fileToolBar = new QToolBar(this);
            fileToolBar->setAllowedAreas(Qt::AllToolBarAreas);
            fileToolBar->setOrientation(Qt::Horizontal);
            fileToolBar->addAction(actNew);
            fileToolBar->addAction(actOpen);
            fileToolBar->addAction(actSave);
            fileToolBar->addAction(actASave);

在初始化工具栏函数iniToolBar()中,首先调用QToolBar的构造函数创建一个“文件”工具栏。函数QToolBar::setAllowedAreas()设置工具栏可放置的位置,共有6个选项(Qt::ToolBarAreas枚举类型):

● Qt::LeftToolBarArea,主窗口的左侧;

● Qt::RightToolBarArea,主窗口的右侧;

● Qt::TopToolBarArea,主窗口的顶部;

● Qt::BottomToolBarArea,主窗口的底部;

● Qt::AllToolBarAreas,可以放在主窗口四个方向的任何一个;

● Qt::NoToolBarArea,没有可放置工具条的区域。

工具栏放置区域的前四个选择可以通过位或操作运算符 “|”进行任意的组合。

函数QToolBar::setOrientation()设置工具栏图标的排列方向。事实上,Qt的工具栏的方向是由主窗口QMainWindow对象自动管理的,当一个工具栏被放置在主窗口的顶部时,就决定了工具栏的方向是水平的。该函数的参数由两个选项:

● Qt::Horizontal,水平方向;

● Qt::vertical,垂直方向。

此处,无论设置哪个选项,都不会影响工具栏在当前放置区域的方向。

QToolBar::addAction() 将动作添加到相应的工具栏上,该函数继承自QToolBar类的父类QWidget。

下面完成“编辑”工具栏的创建。

            editToolBar = new QToolBar(this);
            editToolBar->setAllowedAreas(Qt::AllToolBarAreas);
            editToolBar->setOrientation(Qt::Horizontal);
            editToolBar->addAction(actUndo);
            editToolBar->addAction(actCut);
            editToolBar->addAction(actCopy);
            editToolBar->addAction(actPast);

            addToolBar(Qt::TopToolBarArea, fileToolBar);
            addToolBar(Qt::TopToolBarArea, editToolBar);
        }

最后,QMainWindow::addToolBar()将“文件”工具栏和“编辑”工具栏添加到主窗口。它的第一个参数指定了工具栏放置的区域;第二个参数指定了被放置的工具栏对象。

        void CMainWindow::iniCentralWidget()
        {
            textEdit = new QTextEdit(this);
            setCentralWidget(textEdit);
        }

iniCentralWidget()函数构造一个QTextEdit对象,并将它设置为应用程序主窗口的中心部件。

修改KDevelop工程的qmake工程文件src.pro,加入资源选项:

        RESOURCES += ./images/mainwindow.qrc

现在编译运行应用程序,它的显示效果和Qt设计器绘制的界面效果基本上是相同的,如图4-21所示。

图4-21 主窗口的运行效果图