3-7 多文档(Multiple Documents)

现在我们开始实现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实例。在程序中止的时候,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实例。

槽函数MainWindow::newFile()要改成这样:

void MainWindow::newFile()

{

    MainWindow *mainWin = new MainWindow;

    mainWin->show();

}

我们只是简单的创建一个新的MainWindow实例。奇怪的是我们没有保存新窗口的指针,这是因为Qt会为我们记录所有窗口的地址。

MainWindow::createActions()中,我们需要CloseExit行为:

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();

}

上面的代码用到了Qtforeach(这将在第11章介绍)遍历所有程序窗口,类型为MainWindow的窗口全部调用updateRecentFilesActions()。选项ShowGridAutoRecalculate也要这样处理进行同步,确保同一个文件不会调用两次。

一个主窗口只能处理一个文档的程序称为SDIsingle document interface)程序。能处理多个文档的程序称之为MDIMultiple document interface)程序。Qt能够在所有操作系统平台上支持SDIMDI程序。

 

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值