Qt基础教程之MDI及其使用方法.docx
《Qt基础教程之MDI及其使用方法.docx》由会员分享,可在线阅读,更多相关《Qt基础教程之MDI及其使用方法.docx(13页珍藏版)》请在冰豆网上搜索。
Qt基础教程之MDI及其使用方法
传统的应用程序设计中有多文档界面(Multi-documentInterface,MDI)应用程序,Qt为设计MDI应用程序提供了支持。
本节的实例中是一个MDI应用程序,程序运行效果如图1所示。
图1MDI应用程序实例的运行时界面
MDI应用程序就是在主窗口里创建多个同类型的MDI子窗口,这些MDI子窗口在主窗口里显示,并共享主窗口上的工具栏和菜单等操作功能,主窗口上的操作都针对当前活动的MDI子窗口进行。
设计MDI应用程序需要在主窗口工作区放置一个QMdiArea作为子窗体的容器。
实例samp6_4主窗口的工作区使用一个QMdiArea组件,实例的子窗口类是QFormDoc,是一个使用QPlainTextEdit进行简单文本显示和编辑的窗体。
创建的QFormDoc窗体对象作为一个子窗口加入到mdiArea组件中。
QMdiArea组件类似于实例samp6_3中主窗口上的tabWidget组件,只是QMdiArea提供更加完备的功能。
更改MDI的显示模式,可以得到与实例samp6_3相似的以多页组件管理的MDI界面效果。
文档窗口类QFormDoc的设计
以可视化方式创建一个基于QWidget的类QFormDoc,设计可视化界面时,只放置一个QPlainTextEdit组件,并以水平布局填充满整个窗口。
这里不再用可视化的方式设计Action,因为QFormDoc窗口不需要创建自己的工具栏,而是使用主窗口上的工具栏按钮对QFormDoc窗体上的QPlainTextEdit组件进行操作。
为QFormDoc添加一些用于文件打开和编辑操作的接口函数,QFormDoc类的完整定义如下:
1.classQFormDoc:
publicQWidget
2.{
3.Q_OBJECT
4.private:
5.QStringmCurrentFile;//当前文件
6.boolmFileOpened=false;//文件已打开
7.public:
8.explicitQFormDoc(QWidget*parent=0);
9.~QFormDoc();
10.voidloadFromFile(QString&aFileName);//打开文件
11.QStringcurrentFileName();//返回当前文件名
12.boolisFileOpened();//文件已经打开
13.voidsetEditFont();//设置字体
14.voidtextCut();//cut
15.voidtextCopy();//copy
16.voidtextPaste();//paste
17.private:
18.Ui:
:
QFormDoc*ui;
19.};
这些接口函数是为了在主窗口里调用,实现对MDI子窗口的操作。
实现代码如下:
1.QFormDoc:
:
QFormDoc(QWidget*parent):
2.QWidget(parent),
3.ui(newUi:
:
QFormDoc)
4.{
5.ui->setupUi(this);
6.
7.this->setWindowTitle("NewDoc");//窗口标题
8.this->setAttribute(Qt:
:
WA_DeleteOnClose);//关闭时自动删除
9.}
10.
11.QFormDoc:
:
~QFormDoc()
12.{
13.//QMessageBox:
:
information(this,"信息","文档窗口被释放");
14.deleteui;
15.}
16.
17.voidQFormDoc:
:
loadFromFile(QString&aFileName)
18.{//打开文件
19.QFileaFile(aFileName);//以文件方式读出
20.if(aFile.open(QIODevice:
:
ReadOnly|QIODevice:
:
Text))//以只读文本方式打开文件
21.{
22.QTextStreamaStream(&aFile);//用文本流读取文件
23.ui->plainTextEdit->clear();//清空
24.ui->plainTextEdit->setPlainText(aStream.readAll());//读取文本文件
25.aFile.close();//关闭文件
26.mCurrentFile=aFileName;//保存当前文件名
27.QFileInfofileInfo(aFileName);//文件信息
28.QStringstr=fileInfo.fileName();//去除路径后的文件名
29.this->setWindowTitle(str);
30.mFileOpened=true;
31.}
32.}
33.
34.QStringQFormDoc:
:
currentFileName()
35.{
36.returnmCurrentFile;
37.}
38.
39.boolQFormDoc:
:
isFileOpened()
40.{//文件是否已打开
41.returnmFileOpened;
42.}
43.
44.voidQFormDoc:
:
setEditFont()
45.{
46.QFontfont;
47.font=ui->plainTextEdit->font();
48.
49.boolok;
50.font=QFontDialog:
:
getFont(&ok,font);
51.ui->plainTextEdit->setFont(font);
52.}
53.
54.voidQFormDoc:
:
textCut()
55.{
56.ui->plainTextEdit->cut();
57.}
58.
59.voidQFormDoc:
:
textCopy()
60.{
61.ui->plainTextEdit->copy();
62.}
63.
64.voidQFormDoc:
:
textPaste()
65.{
66.ui->plainTextEdit->paste();
67.}
注意作为MDI子窗口,不管其是否设置为关闭时删除,在主窗口里关闭一个MDI子窗口时,都会删除子窗口对象。
MDI主窗口设计与子窗口的使用
主窗口界面设计
要在主窗口实现MDI功能,只需在主窗口的工作区放置一个QMdiArea组件。
图2是设计好的主窗口界面。
图2设计时的主窗口
在UI设计器里创建Action,并应用Action设计主工具栏。
在主窗口的工作区放置一个QMdiArea组件,然后在主窗口的构造函数里设置mdiArea填充满工作区。
1.QWMainWindow:
:
QWMainWindow(QWidget*parent):
QMainWindow(parent),ui(newUi:
:
QWMainWindow)
2.{
3.ui->setupUi(this);
4.this->setCentralWidget(ui->mdiArea);
5.this->setWindowState(Qt:
:
WindowMaximized);
6.ui->mainToolBar->setToolButtonStyle(Qt:
:
ToolButtonTextUnderlcon);
7.}
MDI子窗口的创建与加入
下面是主窗口上“新建文档”按钮的响应代码:
1.voidQWMainWindow:
:
on_actDoc_New_triggered()
2.{//新建文档
3.QFormDoc*formDoc=newQFormDoc(this);
4.ui->mdiArea->addSubWindow(formDoc);//文档窗口添力口到MDIformDoc->show();
5.}
代码功能是新建一个QFormDoc类的窗口formDoc,构造函数中传入了主窗口指针,所以主窗口是formDoc的父窗口,然后使用QMdiArea的addSubWindow()函数将formDoc加入到mdiArea。
下面是主窗口上“打开文档”按钮的响应代码:
1.voidQWMainWindow:
:
on_actDoc_Open_triggered()
2.{//打开文件
3.//必须先获取当前MDI子窗口,再使用打开文件对话框,否则无法获得活动的子窗口
4.boolneedNew=false;//是否需要新建子窗口
5.
6.QFormDoc*formDoc;
7.if(ui->mdiArea->subWindowList().count()>0)//如果有打开的主窗口,获取活动窗口
8.{
9.formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
10.needNew=formDoc->isFileOpened();//文件已经打开,需要新建窗口
11.}
12.else
13.needNew=true;
14.
15.QStringcurPath=QDir:
:
currentPath();
16.QStringaFileName=QFileDialog:
:
getOpenFileName(this,tr("打开一个文件"),curPath,
17."C程序文件(*.h*cpp);;文本文件(*.txt);;所有文件(*.*)");
18.if(aFileName.isEmpty())
19.return;//如果未选择文件,退出
20.
21.if(needNew)//需要新建子窗口
22.{
23.formDoc=newQFormDoc(this);//指定父窗口,必须在父窗口为Widget窗口提供一个显示区域
24.ui->mdiArea->addSubWindow(formDoc);
25.}
26.
27.formDoc->loadFromFile(aFileName);//打开文件
28.formDoc->show();
29.
30.ui->actCut->setEnabled(true);
31.ui->actCopy->setEnabled(true);
32.ui->actPaste->setEnabled(true);
33.ui->actFont->setEnabled(true);
34.}
通过QMdiArea:
:
subWindowList()可以获得子窗口对象列表,从而可以判断子窗口的个数。
如果没有一个MDI子窗口,就创建一个新的窗口并打开文件。
如果有MDI子窗口,则总有一个活动窗口,通过QMdiArea:
:
activeSubWindow()可以获得此活动的子窗口,通过子窗口的isFileOpened()函数判断是否打开了文件,如果没有打开过文件,就在这个活动窗口里打开文件,否则新建窗口打开文件。
注意一定要先获取MDI子窗口,再使用QFileDialog选择需要打开的文件。
如果顺序更换了,则无法获得正确的MDI活动子窗口。
QMdiArea常用功能函数
QMdiArea提供了一些成员函数,可以进行一些操作,工具栏上的“关闭全部”、“MDI模式”、“级联展开”、“平铺展开”等按钮都是调用QMdiArea类的成员函数实现的。
下面是这几个按钮功能的实现代码:
1.voidQWMainWindow:
:
on_actCascade_triggered()
2.{//窗口级联展开
3.ui->mdiArea->cascadeSubWindows();
4.}
5.
6.voidQWMainWindow:
:
on_actTile_triggered()
7.{//平铺展开
8.ui->mdiArea->tileSubWindows();
9.}
10.
11.voidQWMainWindow:
:
on_actCloseALL_triggered()
12.{//关闭全部子窗口
13.ui->mdiArea->closeAllSubWindows();
14.}
15.voidQWMainWindow:
:
on_actViewMode_triggered(boolchecked)
16.{//MDI显示模式
17.if(checked)//Tab多页显示模式
18.{
19.ui->mdiArea->setViewMode(QMdiArea:
:
TabbedView);//Tab多页显示模式
20.ui->mdiArea->setTabsClosable(true);//页面可关闭
21.ui->actCascade->setEnabled(false);
22.ui->actTile->setEnabled(false);
23.}
24.else////子窗口模式
25.{
26.ui->mdiArea->setViewMode(QMdiArea:
:
SubWindowView);//子窗口模式
27.ui->actCascade->setEnabled(true);//
28.ui->actTile->setEnabled(true);//
29.}
30.}
其中,设置MDI视图模式用setViewMode()函数,有两种模式可以选择:
1.QMdiArea:
:
SubWindowView是传统的子窗口模式,显不效果如图1所示。
2.QMdiArea:
:
TabbedView是多页的显示模式,显示效果如图3所示。
图3多页模式下MDI界面
MDI的信号
QMdiArea有一个信号subWindowActivated(QMdiSubWindow*argl),在当前活动窗口切换时发射,利用此信号可以在活动窗口切换时进行一些处理,例如,在状态栏里显示活动MDI子窗口的文件名,在没有MDI子窗口时,将工具栏上的编辑功能按钮设置为禁用。
下面是该信号的槽函数代码:
1.voidQWMainWindow:
:
on_mdiArea_subWindowActivated(QMdiSubWindow*arg1)
2.{//当前活动子窗口切换时
3.if(ui->mdiArea->subWindowList().count()==0)
4.{//若子窗口个数为零
5.ui->actCut->setEnabled(false);
6.ui->actCopy->setEnabled(false);
7.ui->actPaste->setEnabled(false);
8.ui->actFont->setEnabled(false);
9.ui->statusBar->clearMessage();
10.}
11.else
12.{
13.QFormDoc*formDoc=static_cast(ui->mdiArea->activeSubWindow()->widget());
14.ui->statusBar->showMessage(formDoc->currentFileName());//显示主窗口的文件名
15.}
16.}
主窗口工具栏上的“剪切”、“复制”、“粘贴”、“字体设置”等按钮都是调用当前子窗口的相应函数,关键是获取当前MDI子窗体对象。
例如,“剪切”和“字体设置”按钮的代码如下:
1.voidQWMainWindow:
:
on_actCut_triggered()
2.{//cut
3.QFormDoc*formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
4.formDoc->textCut();
5.}
6.voidQWMainWindow:
:
on_actFont_triggered()
7.{//设置字体
8.QFormDoc*formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();
9.formDoc->setEditFont();
10.}