现在的位置: 首页 > 综合 > 正文

(转)3.7多文档(Multiple Documents)

2014年03月01日 ⁄ 综合 ⁄ 共 2579字 ⁄ 字号 评论关闭
现在我们开始实现Spreadsheet程序的main()函数:
include <QApplication>
include "mainwindow.h"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow mainWin;
    mainWin.show();
    return app.exec();
}
这个main()函数和以前实现的稍有不同:我们在栈上创建了MainWindow对象,而并没用new来创建。在程序中止的时候,MainWindow对象自动销毁。
使用以上的main()函数,Spreadsheet程序提供一个主窗口,一次只能处理一个文档。如果我们希望在同时处理多个文档,我们就要同时启动多个Spreadsheet程序。这对用户来说很不方便,他们更喜欢在一个应用程序中打开多个窗口,就如同一个web浏览器可以同时打开多个窗口一样。
为了处理多文档,我们需要对Spreadsheet进行一点修改。首先File菜单要进行修改:
  • File|New 创建一个带有空文档的新的主窗口,而不是重新使用已经存在的主窗口。
  • File|Close 关闭当前主窗口。
  • File|Exit 关闭所有窗口。
在原来的程序版本中没有Close菜单项,因为这个菜单项和Exit时一样。
新的main()函数变为这样:
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    MainWindow *mainWin = new MainWindow;
    mainWin->show();
    return app.exec();
}
由于有了多个主窗口,我们需要用new创建MainWindow实例,这样当完成该文档后就可以使用delete删除一个主窗口以节约内存。
槽函数MainWindow::newFile()要改成这样:
void MainWindow::newFile()
{
    MainWindow *mainWin = new MainWindow;
    mainWin->show();
}
我们只是简单的创建一个新的MainWindow实例。奇怪的是我们没有保存新窗口的指针,这是因为Qt会为我们记录所有窗口的地址。
在MainWindow::createActions()中,我们需要Close和Exit行为:
void MainWindow::createActions()
{
    ...
    closeAction = new QAction(tr("&Close"), this);
    closeAction->setShortcut(tr("Ctrl+W"));
    closeAction->setStatusTip(tr("Close this window"));
    connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
    exitAction = new QAction(tr("E&xit"), this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setStatusTip(tr("Exit the application"));
    connect(exitAction, SIGNAL(triggered()),
            qApp, SLOT(closeAllWindows()));
    ...
}
函数QApplication::closeAllWindows()关闭所有应用程序的窗口,除非有些窗口拒绝了这个关闭事件。这个功能是很需要的。因为只要关闭一个窗口,MainWindow::closeEvent()里面会处理未保存的变化,这样我们就不用担心有些文档没有存盘。
到现在,看起来我们的程序已经能够处理多文档窗口了。但是还有一个隐藏的问题:如果用户不停的创建关闭主窗口,那么机器最终会耗尽所有内存。因为我们在newFile()中不停的创建主窗口 但是却没有删除它。用户关闭一个窗口只是把它隐藏,窗口实例一直在内存中。在内存中不用的主窗口越来越多,这个问题就很严重了。
解决这个问题很简单,在构造函数中我们把窗口属性设置为Qt::WA_DeleteOnClose就可以了:
MainWindow::MainWindow()
{
    ...
    setAttribute(Qt::WA_DeleteOnClose);
    ...
}
这样Qt就在窗口关闭的同时销毁它。QWidgets有许多可以影响行为的属性,Qt::WA_DeleteOnClose只是其中的一个。
内存泄漏只是我们需要处理的问题之一。在我们的原来程序设计中,我们假定只有一个主窗口。如果创建了多个窗口,那么每一个窗口都有自己最近打开的文档列表和自己的设置选项。很明显,最近打开的文档列表应该是对程序全局有效的。我们可以声明recentFiles为静态变量,这样在整个程序运行期间就只有一份拷贝存在。这样我们就需要所有的主窗口都要调用updateRecentFilesActions()函数,代码实现如下:
foreach (QWidget *win, QApplication::topLevelWidgets()) {
    if (MainWindow *mainWin = qobject_cast<MainWindow *>(win))
        mainWin->updateRecentFileActions();
}
上面的代码用到了Qt的foreach(这将在第11章介绍)遍历所有程序窗口,类型为MainWindow的窗口全部调用updateRecentFilesActions()。选项ShowGrid和AutoRecalculate也要这样处理进行同步,确保同一个文件不会调用两次。
一个主窗口只能处理一个文档的程序称为SDI(single document interface)程序。只有一个主窗口,在其内部区域能管理多个文档窗口的程序称之为MDI(Multiple document interface)程序。Qt能够在所有操作系统平台上支持SDI和MDI程序。

抱歉!评论已关闭.