<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 8.8 多文檔 在每一個主窗口中只提供一個文檔的應用程序被稱為單文檔界面( SDI)應用程序。基 于 SDI 的應用程序只提供了一個單一主窗口,并且在同一時間只能處理一個文檔。如果想 讓它在同一時間具有處理多個文檔的能力,就需要同時啟動多個應用程序實例。但是這對于 用戶來講是很不方便的。針對這種情況,我們可以使用基于多文檔界面( MDI)的應用程 序,它也只有一個主窗口,但可以產生和管理多個文檔窗口。基于多文檔的應用程序也是很 常見的,比如 FireFox 瀏覽器就是典型的例子,它允許用戶在同一時間內打開多個瀏覽器 窗口。 Qt 可以在它所支持的所有平臺上創建 SDI 和 MDI 應用程序。 根據筆者的經驗,在通常的工程項目中,使用 SDI 的應用程序占到了大多數的比例,但我們仍然需要對 MDI 有所了解。 ### 8.8.1 創建多文檔 在 Qt4 中創建 MDI 應用程序主要有以下方法: 1\. 多實例實現主窗口的多文檔 在一個應用程序中實例化多個主窗口,即當打開或新建文檔的時候,文本編輯器應用 程序新建一個主窗口,這個主窗口單獨加載和編輯文檔。這種情況下,多個主窗口屬于同一 個應用程序,當關閉所有的主窗口的時候,文本編輯器應用程序也就結束了運行。這種方法 稱為多實例實現主窗口的多文檔。 下面將修改應用程序,以使它可以處理多個文檔。首先,需要對 File 菜單做一些簡單 改動: + 利用 File→New 創建一個空文檔窗口,而不是再次使用已經存在的主窗口。 + 利用 File→Close 關閉當前主窗口。 + 利用 File→Exit 關閉所有窗口。 在 File 菜單的最初版本中,并沒有 Close 選項,這只是因為當時它還和 Exit 一樣具 有相同的功能。新的 File 菜單如圖 8-27 所示。 新的 main()函數為: ``` int main(int argc,char *argv[]) { QApplication app(argc,argv); MainWindow *mainWin = new MainWindow; mainWin-&gt;show(); return app.exec(); } ``` 具有多窗口功能后,現在就需要使用菜單中的 new 來創建 MainWindow。考慮到節省內 存,可以再工作完成之后使用 delete 操作來刪除主窗口。 這是新的 MainWindow::newFile()槽: ``` void MainWindow::newFile() { MainWindow *mainWin = new MainWindow; mainWin-&gt;show(); } ``` 我們只創建了一個新的 MainWindow 實例。這看起來有些奇怪,因為沒有保留指向這個 新窗口的任何指針,但實際上這并不是什么問題,因為 Qt 會對所有的窗口進行跟蹤。 以下是用于 Close 和 Exit 的動作: ``` void MainWindow::createActions() { ... closeAct = new QAction(tr("Cl&ose"), this); closeAct-&gt;setShortcut(tr("Ctrl+F4")); closeAct-&gt;setStatusTip(tr("Close the active window")); connect(closeAct, SIGNAL(triggered()),mdiArea, SLOT(closeActiveSubWindow())); exitAct = new QAction(tr("E&xit"), this); exitAct-&gt;setShortcut(tr("Ctrl+Q")); exitAct-&gt;setStatusTip(tr("Exit the application")); connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); } ``` 到此,我們就實現了從 SDI 到 MDI 的“轉變”,組合好你的工程文件,編譯、鏈接、 運行程序即可。 小貼士:在 Mac OS X 系統中,通常采用這種方法實現 MDI 應用程序。 2\.使用 QWorkSpace 使用 QWorkSpace 作為主窗口的中心部件,在 QWorkspace 中打開多個子窗口,每一個 子窗口可以單獨對文檔進行加載和編輯。 QWorkspace 類繼承自 QWidget 類,利用它可以很方便的實現多文檔的應用。使用它的 方法有如下步驟: 第 1 步,在主窗口的頭文件(如 mainwindow.h)中加入 QWorkspace 類的頭文件,代碼 如下: ``` #include &lt;QWorkspace&gt; ``` 也可以采用類的前置聲明,代碼如下: ``` class QWorkspace; ``` 第 2 步,在主窗口頭文件中聲明一個 QWorkspace 類對象,代碼如下: ``` QWorkspace *workspace; ``` 第 3 步,在構造函數中實例化該對象,并把該對象設置為主窗口的中心窗口部件,代 碼如下: ``` MainWindow::MainWindow() { workspace = new QWorkspace; setCentralWidget(workspace); ... } ``` 第 4 步,創建多個子窗口,并創建它們各自的中心窗口部件 。 ``` QMainWindow *window1 = new QMainWindow; window1-&gt;setWindowTitle(tr("window 1")); QTextEdit *textEdit1 = new QTextEdit; textEdit1-&gt;setText(tr("Window 1")); window1-&gt;setCentralWidget(textEdit1); QMainWindow *window2 = new QMainWindow; window2-&gt;setWindowTitle(tr("window 2")); QTextEdit * textEdit2 = new QTextEdit; textEdit2-&gt;setText(tr("Window 2")); window2-&gt;setCentralWidget(textEdit2); QMainWindow *window3 = new QMainWindow; window3-&gt;setWindowTitle(tr("window 3")); QTextEdit * textEdit3 = new QTextEdit; textEdit3-&gt;setText(tr("Window 3")); window3-&gt;setCentralWidget(textEdit3); ``` 第 5 步,在 workSpace 對象中加入這幾個子窗口,對它們進行管理,代碼如下: ``` workSpace-&gt;addWindow(window1); workSpace-&gt;addWindow(window2); workSpace-&gt;addWindow(window3); ``` 第 6 步,組織好你的工程文件,編譯、鏈接、運行程序即可。 完整的示例程序在本章目錄下的 workspace 文件夾下面。 小貼士:在 Qt4.5 版推出以后,不推薦采用上述方法來創建 MDI 應用程序。來自 Qt 的 官方說法是,QWorkspace 是被廢棄的類,它的存在就是為了使采用以前版本的 Qt 開發的程 序能夠正常運行。所以,如果你使用的是 Qt4.5 及以后的版本,我們強烈建議你使用 QMdiArea 來創建 MDI 應用程序。 3\.使用 QMdiArea 這種方法的核心主要是掌握兩個類的用法: QMdiArea 和 QMdiSubWindow,前者主要用 于創建程序主窗口的中心窗口部件,后者用于創建主窗口的各個子窗口。具體的做法是把 QMdiArea 類的實例作為主窗口的中心部件,把 QMdiSubWindow 類的實例作為子窗口,并由 QMdiArea 實現對多個子窗口的管理。 QMdiArea 類繼承自 QAbstractScrollArea,它是 Qt 4.3 以后新增加的類。在創建 MDI 應用程序時,QMdiArea 類的實例通常被用作主窗口的中心窗口部件,但也可以被放置于一 個布局中。實際上,QMdiArea 是 MDI 應用程序的窗口管理器。它建立、繪制、管理在它之 上的子窗口,并可采用層疊或者平鋪的方式排列它們。 QMdiSubWindow 繼承自 QWidget,它的作用是為 QMdiArea 創建子窗口。它代表了在 QMdiArea 中創建的頂層窗口。它主要包含一個標題欄、一個內部窗口( Internal Widget)、一個窗口框架和一個大小控制手柄。 QMdiSubWindow 有自己的布局(Layout), 在其中包含窗口標題欄以及內部窗口的中心窗口區域。一個典型的 QMdiSubWindow 實例如 圖 8-27 所示。 ![](https://box.kancloud.cn/2016-01-22_56a1a15547981.png) 圖 8-27 QMdiSubWindow 子窗口 聽了上面的介紹,大家是不是有點“暈”呢?別著急,請看圖 8-28,它示意了采用這 種方法創建 MDI 應用程序的窗口布局以及創建的方法。圖中的主窗口是子類化 QMainWindow 類創建的;主窗口的中心窗口部件使用 QMdiArea 的實例創建;子窗口是子類化 QWidget 實 現的,而子窗口的內部窗口部件是使用 QMdiSubWindow 的實例創建的。 它們之間的關系總結如下:QMdiArea 是所有子窗口的容器和管理器,QMdiArea 中的子 窗口都是 QMdiSubWindow 類的實例。我們通過 addSubWindow()方法把它們加入到 MDI 應用 程序中。使用時,通常先建立一個 QWidget 或其子類的實例,然后把它作為參數調用 addSubWindow()函數,addSubWindow()函數將把它作為子窗口的內部窗口,并填充中心窗口 區域。由于 QMdiSubWindow 是 QWidget 的子類,所以你可以像使用以前我們介紹過的常見 頂層窗口那樣使用它,如可以調用基類 QWidget 的 show(), hide(), showMaximized(), 以及 setWindowTitle()等方法對窗口實例進行設置。 看著這張圖再對照筆者上面的講解,應該就很清楚了吧。 ![](https://box.kancloud.cn/2016-01-22_56a1a15556674.png) 圖 8-28 使用 QMdiArea 類創建 MDI 時的窗口框架 小貼士:為 QMdiSubWindow 創建內部窗口有兩種方法,一種是調用 addSubWindow(widget),其中 widget 參數將作為內部窗口部件;另一種是先創建一個繼承 自 QWidget 的窗口實例,然后調用 setWidget ( QWidget * widget )方法,把 widget 作為子 窗口的內部窗口部件即可,這個內部窗口部件將被顯示在子窗口的中心區域。注意, QMdiArea 會對其內部的子窗口進行管理,你不必使用代碼顯式的管理它們。 QMdiSubWindow 還有許多專門對應 MDI 應用類型而設置的方法和屬性,大家可以在 Qt Assistant 中獲得詳盡的介紹。 好了,我們詳細解說一下如何采用 QMdiArea 和 QMdiSubWindow 類來創建 MDI 應用程 序,這個例子在本章目錄 mdi 文件夾下面。 第 1 步,包含用到的類 在主窗口的頭文件(如 mainwindow.h)中包含程序中使用到的類,有兩種方法,一是可 以加入頭文件;二是當情況比較簡單時,也可以采用類的前置聲明。 加入頭文件: ``` #include &lt;QMdiArea&gt; #include &lt;QMdiSubWindow&gt; ... ``` 或者采用類前置聲明: ``` class QMdiArea; class QMdiSubWindow; ... ``` 第 2 步,聲明一個 QMdiArea 類對象 在主窗口的頭文件中聲明一個 QMdiArea 類對象,在后面還需要聲明一個你的子窗口類 的對象,代碼如下: ``` QMdiArea *mdiArea; ... MdiChild *child;//聲明子窗口類的對象 ... ``` 第 3 步,設置中心窗口部件 在主窗口類的實現文件中(如 mainwindow.cpp,通常在其構造函數中)實例化該對 象,并把它設置為主窗口的中心窗口部件,代碼如下: ``` MainWindow::MainWindow() { mdiArea = new QMdiArea; setCentralWidget( mdiArea ); ... } ``` 第 4 步,創建子窗口 新建一個子窗口類,它可派生自 QWidget 或其子類,比如 QTextEdit。這個類的實例將 作為子窗口的內部窗口部件。這個子窗口類的創建與我們前面講到的子類化對話框和子類化 QWidget 的方法相同,只是它沒有菜單欄、工具欄和狀態欄。 另外記得在主窗口的頭文件中加入該子窗口類的聲明。 第 5 步,實例化子窗口類,并使用 QMdiArea 對它進行管理,代碼如下: ``` child = new MdiChild; QMdiSubWindow *subWindow = mdiArea-&gt;addSubWindow(child); subWindow-&gt;show(); ... ``` 小貼士:QMdiArea::addSubWindow()函數創建一個新的 QMdiSubWindow,把作為參數傳遞的 該窗口部件放進子窗口中,并且返回該子窗口。最后一行代碼調用 show()方法,使該子窗口可見。 第 6 步,創建并顯示子窗口 這通常是在用戶點擊 File-&gt;NewFile 時完成的,代碼如下: ``` void MainWindow::newFile() { child-&gt;newFile(); child-&gt;show(); } ``` 整個程序的實現過程可以用圖描述。 ![](https://box.kancloud.cn/2016-01-22_56a1a15568750.png) 圖 8-29 程序的實現過程 小貼士:在 MDI 應用程序中,主窗口類并不需要對文檔進行具體處理,這些工作是在子窗 口類中完成的,相當于在 SDI 應用程序中實現的文檔處理功能。 第 7 步,創建 main.cpp 文件 這步沒有什么好說的,代碼如下: ``` #include &lt;QApplication&gt; #include "mainwindow.h" int main(int argc, char *argv[]) { Q_INIT_RESOURCE(mdi);//使用 Qt 資源系統 QApplication app(argc, argv); MainWindow mainWin; mainWin.show(); return app.exec(); } ``` 做完這些后,組織好你的工程內的文件(頭文件、實現文件、資源文件、資源集文件 等),編譯、鏈接、運行程序即可。一個典型的 MDI 應用程序界面如圖 8-30 所示。 ![](https://box.kancloud.cn/2016-01-22_56a1a1557add5.png) 圖 8-30 使用 QMdiArea 建立的 MDI 應用程序界面 到這里,關于如何使用 Qt4 創建 MDI 應用程序就講解完了。采用 QMdiArea 的方法是筆 者重點講解的,一是因為它是 Qt4.5 版以后官方所推薦采用的方法,用于替代 QWorkspace;二是因為它也是實現 MDI 的方法中使用起來最為復雜和令人困惑的一個。即 使是讓 Qt“老鳥”來解釋清楚什么是“主窗口的中心窗口”、“子窗口的內部窗口”、 “子窗口的中心區域”等等這些名詞以及用法,也不是一件容易的事。 相對而言,使用 QWorkspace 創建 MDI 是比較容易的,但 Qt 以后將不再對這個類繼續更新和支持,而“多實例實現多文檔”的方法在 Mac OS X 上應用很廣泛,它實質上就是使 用了多個頂層窗口,也是比較容易掌握的。 熟練使用 Qt4 建立 MDI 應用程序所涉及的內容遠遠不止本書所介紹的這些,比如子窗 口如何響應鍵盤與鼠標事件,如何同步所有主窗口的 “最近打開文件列表”等等問題都需要 費些力氣解決。對于初學者而言,這是一個比較復雜的話題。大家在閱讀到此處時,建議仍 然采用“知道、會用即可”的原則,不必深究它們背后的機理。隨著學習進程的逐步深入, 一些開始接觸時覺得困難的內容,就會在你心中逐漸明晰了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看