欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【学习笔记】C++ GUI Qt4 第三章 3.7 多文档和3.8程序启动画面

程序员文章站 2022-05-22 19:53:09
...

3.7 多文档

#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应用程序实例。但是这对于用户来讲是很不方便的,用户需要的是一个可以处理多个文档的单应用程序实例,就像在一个网页浏览器实例中可以同时提供多个浏览器窗口一样。

下面将修改Spreadsheet应用程序,以使它可以处理多个文档。首先,需要对File菜单做一些简单改动:
● 利用File->New创建一个空文档主窗口,而不是再次使用已经存在的主窗口。
● 利用File->Close关闭当前主窗口。
● 利用File->Exit关闭所有窗口。。
在File菜单的最初版本中,并没有Close 选项,这只是因为当时它还和Exit一样具有相同的功能。

int main(int argc, char *argv[])
{
	QApplication app(argC, argv);
	MainWindow *mainWin = new MainWindow;
	mainWin->show();
	return app. exec();
}

我们只创建了一个新的MainWindow实例。这看起来有些奇怪,因为没有保留指向这个新窗口的任何指针;但实际上这并不是什么问题,因为Qt会对所有的窗口进行跟踪。

以下是用于Close和Exit的动作:

void MainWindow::createActions()
{
	...
	closeAction = new QAction(tr("&Close"), this);
	ctoseAction->setShortcut(QKeySequence::Close);
	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, SIGNAE(triggered()), qApp, SLOT(closeAllWindows()));
	...
}

槽QApplication: :closeAllWindows()会关闭所有应用程序的窗口,除非其中一个应用程序拒绝了这个关闭事件。这正是在此所需的行为。我们不用再考虑那些有关是否保存的事情,因为就算关闭一个窗口,都会在MainWindow::closeEvent()中处理这些情况。看起来好像已经完成了应用程序对多窗口处理能力的工作。遗憾的是,这里还隐藏着一个潜在的问题:如果用户一直创建并且关闭主窗口,那么这台机器早晚会耗尽它的全部内存。这是因为我们保存了newFile()中创建的MainWindow窗口部件,但是从没有删除它们。当用户关闭一个主窗口时,默认行为是隐藏它,所以它还会保留在内存中。对于如此多的主窗口的确会造成一定的问题。解决办法是在构造函数中对Qt::WA_DeleteOnClose 的属性进行设置:

MainWindow::MainWindow()
{
	...
	setAttribute(Qt::WA_Delete0nClose);
	...
}

这样做就会告诉Qt在关闭窗口时将其删除。Qt::WA _DeleteOnClose属性是可以在QWidget上进行设置并用来影响这个窗口部件的行为的诸多标记之一。内存泄漏并不是必须处理的唯一问题。 最初的应用程序设计包含了一个隐含的假设,也就是它仅有一个主窗口。对于多窗口,每一个主窗口都有它自己的最近打开文件列表和它自己的一些
选项。很明显,最近打开文件列表对于整个应用程序来说应该是全局的。通过把recentFiles变量声明为静态变量,可以相当容易地解决这个问题,这样对于整个应用程序来说,会只存在一个该列表的实例。 但随后必须确保的是无论何时调用updateRecentFileActions()函数来更新File菜单,都必须是在所有的主窗口上调用它。这是实现这一做法的代码:

foreach(QWidget *win, QApplication::topLevelWidgets()) 
{
	if(MainWindow *mainWin = qobject_ cast<MainWindow *>(win))
	mainWin->updateRecentFileActions();
}

这段代码使用了Qt的foreach结构体(将在第11章中对其进行说明)来遍历这个应用程序的所有窗口,并且对所有类型为MainWindow的窗口部件调用updateRecentFileActions()。可以使用类似的代码来同步Show Grid和Auto-Recalculate 选项,或者用于确保同一个文件不会被加载两次。

在每一个主窗口中只提供一个文档的应用程序称为单文档界面( single document interface , SDI)应用程序。在Windows系统下,一种常用的替代方法是多文档界面(multiple document interface,MDI),这种应用程序只有一个单一的主窗口,但可以对主窗口*区域的多个文档窗口进行管理。Qt可以在它支持的所有平台上创建SDI和MDI应用程序。图3.17给出了使用这两种方法的Spreadsheet应用程序。第6章将对MDI进行说明。

3.8 程序启动画面

许多应用程序都会在启动的时候显示一个程序启动画面(splashi screen) ,图3.18给出的就是这样的一个实例。一些程序员使用程序启动画面对缓慢的启动过程进行掩饰,而另外一些人则是用于满足市场部门的要求。使用QSplashScreen类,可以非常容易地为Qt应用程序添加一个程序启动画面。

【学习笔记】C++ GUI Qt4 第三章 3.7 多文档和3.8程序启动画面

类QSplashScreen会在应用程序的主窗口出现之前显示一个图片。它也可以在这个图片上显示一些消息,用来通知用户有关应用程序初始化的过程。通常,程序启动画面的代码会放在main( )函数中,位于QApplication: :exec( )调用之前。下面给出了一个main()函数的例子,在应用程序中,它使用QSplashScreen显示的程序启动画面表示启动时载入的一些模块和网络连接的建立。

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSplashScreen *splash = new QSplashScreen;
    splash->setPixmap(QPixmap(":/images/splash.png"));
    splash->show();

    Qt::Alignment topRight = Qt::AlignRight | Qt::AlignTop;
    splash->showMessage(QObject::tr("Setting up the main window..."),topRight,Qt::white);

    MainWindow mainWin;

    splash->showMessage(QObject::tr("Loading modules..."),topRight,Qt::white);
    loadModules();

    splash->showMessage(QObject::tr("Establishing connections..."),topRight,Qt::white);
    establishConnections();

    mainWin.show();
    splash->finish(&mainWin);
    delete splash;

    return a.exec();
}

到此为止,我们已经创建了Spreadsheet 应用程序的用户界面。在下一章中,将会通过实现电子制表软件的核心功能来完成这个应用程序。

相关标签: Qt笔记 qt