Qt 的MDI 多文檔窗口


一、MDI簡介

MDI就是多文檔界面(Multi-document Interface,MDI)應用程序

MDI就是在主窗口里創建多個同類型的MDI子窗口,這些MDI子窗口在主窗口里顯示,並共享主窗口上工具欄和菜單等操作功能,主窗口上的操作都針對當前活動的MDI子窗口進行

二、QMdiArea組件

設計MDI應用程序需要在主窗口工作區放置一個QMdiArea作為MDI子窗體的容器

所以我們需要事先創建窗體類對象,然后將窗口類通過addSubWindow函數添加到MDIArea組件中,然后再調用窗口類的show函數顯示窗體

image.png

三、MDI的一些注意事項

  • 當在主窗口中關閉一個MDI子窗口時,這個MDI窗口對象都會刪除。也可以使用setAttribute(Qt::WA_DeleteOnClose);函數顯示設置在關閉MDI時刪除窗口對象

四、QMDIArea組件的相關函數

addSubWindow函數

  • 此函數將一個窗口類添加到MDIArea中,然后調用窗口類的show函數顯示在MDIArea中

image.png

image.png

activeSubWindow、widget函數

該函數返回當前選中的活動的子窗口,返回的是QMdiSubWindow指針對象

這樣我們就可以通過activeSubWindow函數返回的QMdiSubWindow指針對象,間接通過widget函數得到該窗口的對象(但是需要強制類型轉換)

QMdiSubWindow *QMdiArea::activeSubWindow() const

C++
//頭文件:#include <QMdiSubWindow> QWidget *QMdiSubWindow::widget() const

image.png

subWindowList函數

  • 此函數返回MDIArea組件中的窗口類列表

  • 因此我們可以通過該函數再調用count函數獲取當前MDIArea中的窗體數量

C++
QList<QMdiSubWindow *> QMdiArea::subWindowList(WindowOrder order = CreationOrder) const

image.png

loadFormFile函數

  • 當某個窗體添加到MDIArea中之后,就可以通過此函數加載一個文件的內容

  • 參數為QString對象,該對象是通過QFileDialog::getOpenFileName函數打開的

image.png

closeAllSubWindows函數

  • 通過此函數關閉MDIArea組件中的所有窗口

void QMdiArea::closeAllSubWindows()

image.png

tabsClosable()、setTabsClosable函數

  • tabsClosable:返回當前的MDIArea中的某個窗口是否可以關閉

  • setTabsClosable:設置當前的MDIArea中的某個窗口是否可以關閉

C++
bool tabsClosable() const void setTabsClosable(bool closable)

viewMode、setViewMode函數

  • viewMode:返回當前MDIArea中某個窗口的顯示模式

  • setViewMode:設置當前MDIArea中某個窗口的顯示模式

C++
ViewMode viewMode() const void setViewMode(ViewMode mode)
C++
ViewMode 類型如下:
QMdiArea::TabbedView //Tab多頁顯示模式 QMdiArea::SubWindowView //子窗口模式

窗口默認顯示為“子窗口模式”顯示,Tab多頁顯示模式如下圖所示:

image.png

cascadeSubWindows、tileSubWindows函數

  • cascadeSubWindows:窗口級聯模式展開顯示

  • tileSubWindows:窗口平鋪模式展開顯示

C++
void QMdiArea::cascadeSubWindows() void QMdiArea::tileSubWindows()

image.png

textCut、setEditFont等函數

  • 當我們將窗口添加到MDIArea中之后,就可以調用這些函數來對窗口的字體進行格式化設置、剪切、復制

image.png

五、QMDIArea組件的信號函數

subWindowActivated信號函數

  • 當前活動窗口切換時觸發此信號函數,利用此信號可以在活動窗口切換時進行一些處理

subWindowActivated(QMdiSubWindow *arg1)

演示案例

image.png

一、文檔類窗體的設計

  • 這個窗體類是用來放在主窗體的MDIArea組件中的

①窗體創建與設計

  • 類中只放置一個QPlainTextEdit組件,並以水平布局填充整個窗口

image.png

image.png

image.png

image.png

image.png

②類的初始化

C++
class QFormDoc : public QWidget { Q_OBJECT private: QString mCurrentFile; //當前文件名 bool mFileOpened=false; //判斷當前文件是否已打開,默認為未打開 public: explicit QFormDoc(QWidget *parent = 0); ~QFormDoc(); void loadFormFile(QString &aFileName); //打開文件,並將文件內容讀取plainTextEdit中 QString currentFileName(); //返回當前文件名 bool isFileOpened(); //判斷文件是否已打開 void setEditFont(); //設置字體 void textCut(); //cut void textCopy(); //copy void textPaste(); //paste private: Ui::QFormDoc *ui; };

③相關函數的定義

C++
//構造函數 QFormDoc::QFormDoc(QWidget *parent) : QWidget(parent), ui(new Ui::QFormDoc) { ui->setupUi(this); this->setWindowTitle("New Doc"); //窗口標題 this->setAttribute(Qt::WA_DeleteOnClose);//關閉時自動刪除(備注:不論是否設置此項,MDI在關閉時,都會刪除窗口對象) }
C++
//析構函數 QFormDoc::~QFormDoc() { QMessageBox::information(this,QStringLiteral("信息"), QStringLiteral("文檔窗口被釋放"));//窗口關閉之后提示 delete ui; }
C++
//打開文件,並將文件內容讀取plainTextEdit中 void QFormDoc::loadFormFile(QString &aFileName) { QFile aFile(aFileName); if(aFile.open(QIODevice::ReadOnly|QIODevice::Text)) { //讀取文件並講內容放入plainTextEdit QTextStream aStream(&aFile); ui->plainTextEdit->clear(); ui->plainTextEdit->setPlainText(aStream.readAll()); aFile.close(); //根據文件名獲取文件信息,將文件名設置MDI窗體的標題 mCurrentFile=aFileName; QFileInfo fileInfo(aFileName); QString str=fileInfo.fileName(); this->setWindowTitle(str); mFileOpened=true; } }
C++
//返回當前文件名稱 QString QFormDoc::currentFileName() { return mCurrentFile; }
C++
//判斷當前文件是否打開,打開返回true bool QFormDoc::isFileOpened() { return mFileOpened; }
C++
//設置plainTextEdit的梯子 void QFormDoc::setEditFont() { QFont font=ui->plainTextEdit->font(); bool ok; font=QFontDialog::getFont(&ok,font); //打開字體設置窗體 ui->plainTextEdit->setFont(font); }
C++
//對文檔的剪切、復制、黏貼 void QFormDoc::textCut() { ui->plainTextEdit->cut(); } void QFormDoc::textCopy() { ui->plainTextEdit->copy(); } void QFormDoc::textPaste() { ui->plainTextEdit->paste(); }

二、主窗體設計

①主窗體界面設計

  • 主窗體中是一個MDI Area組件

image.png

因為要在主窗口調用剛才自己設計的MDI窗體類QFormDoc,所以加入下面的頭文件

image.png

②Action設計

  • 添加了以下的Action,作為主窗體的工具欄使用

 

image.png

③構造函數

C++
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); this->setCentralWidget(ui->mdiArea); //讓MDI Area組件填充滿主窗口區域 this->setWindowState(Qt::WindowMaximized); //設置窗體最大化 //讓工具按鈕的文字處於圖標的下方 ui->mainToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); }

④新建文檔按鈕的觸發函數

image.png

點擊此按鈕,在MDIArea中創建一個新的窗體

C++
void MainWindow::on_actDoc_New_triggered() { QFormDoc *formDoc=new QFormDoc(this); //創建文檔窗口對象 ui->mdiArea->addSubWindow(formDoc); //將文檔窗口添加到MDI中 formDoc->show(); //顯示MDI窗體 }

⑤打開文檔按鈕的觸發函數

image.png

點擊此按鈕,選擇一個文檔,並將文檔的內容顯示到MDIArea的窗體中

C++
void MainWindow::on_actDoc_Open_triggered() { bool needNew=false; //是否需要新建子窗口 QFormDoc *formDoc; if(ui->mdiArea->subWindowList().count()>0) //如有mdiArea組件中已經有窗口 { formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget();//獲取當前鼠標所選中的窗口對象 needNew=formDoc->isFileOpened(); //needNew為false,表示不需要新建子窗口 } else needNew=true; //mdiArea組件中還沒有窗口,需要新建 //打開一個文件 QString curPath=QDir::currentPath(); QString aFileName=QFileDialog::getOpenFileName(this, QStringLiteral("打開一個文件"),curPath, QStringLiteral("C程序文件(*.h *.cpp);;所有文件(*.*)")); if(aFileName.isEmpty()) return; if(needNew) //如果需要新建窗口,那么新建窗口 { formDoc=new QFormDoc(this); ui->mdiArea->addSubWindow(formDoc); //將新建的窗口變為當前的操作窗口 } formDoc->loadFormFile(aFileName); //通過文件名加載文件內容 formDoc->show(); //顯示窗口 ui->actCut->setEnabled(true); ui->actCopy->setEnabled(true); ui->actPaste->setEnabled(true); ui->actFont->setEnabled(true); }

⑥關閉全部按鈕的觸發函數

image.png

點擊此按鈕,關閉MDI中所有窗體

C++
void MainWindow::on_actCloseAll_triggered() { ui->mdiArea->closeAllSubWindows();//關閉全部子窗口 }

⑦MDI模式按鈕的觸發函數

image.png

C++
void MainWindow::on_actViewMode_triggered(bool checked) { if(checked) { ui->mdiArea->setViewMode(QMdiArea::TabbedView);//Tab多頁顯示模式 ui->mdiArea->setTabsClosable(true); //頁面可關閉 //窗體不能夠設置級聯展開和平鋪展開 ui->actCascade->setEnabled(false); ui->actTile->setEnabled(false); } else { ui->mdiArea->setViewMode(QMdiArea::SubWindowView); //子窗口模式 //窗體可以設置級聯展開和平鋪展開 ui->actCascade->setEnabled(true); ui->actTile->setEnabled(true); } }

⑧級聯展開、平鋪展開按鈕觸發函數

image.png

C++
//窗體級聯顯示 void MainWindow::on_actCascade_triggered() { ui->mdiArea->cascadeSubWindows(); } //窗體平鋪顯示 void MainWindow::on_actTile_triggered() { ui->mdiArea->tileSubWindows(); }

image.png

級聯展開

 

image.png

平鋪展開

 

 

⑨其他按鈕觸發函數

image.png

C++
void MainWindow::on_actCut_triggered() { //獲取當前的活動窗口 QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget(); formDoc->textCut();//剪切 } void MainWindow::on_actFont_triggered() { QFormDoc* formDoc=(QFormDoc*)ui->mdiArea->activeSubWindow()->widget(); formDoc->setEditFont(); }

⑩MDI的subWindowActivated信號函數

  • 當前活動窗口切換時產生觸發此信號函數,利用該信號函數可以在活動窗口切換時進行一些處理

C++
void MainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1) { if(ui->mdiArea->subWindowList().count()==0)//如果當前MDI中沒有窗口了 { //編輯按鈕都不能使用 ui->actCut->setEnabled(false); ui->actCopy->setEnabled(false); ui->actPaste->setEnabled(false); ui->actFont->setEnabled(false); ui->statusBar->clearMessage(); } else { //當窗口切換時,將當前活動的窗口打開的文件名顯示到statusBar中 QFormDoc *formDoc=static_cast<QFormDoc*>( ui->mdiArea->activeSubWindow()->widget()); ui->statusBar->showMessage(formDoc->currentFileName()); }



url 網址
http://www.skcircle.com/?id=978


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM