<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## 11.4 堆棧布局 堆棧布局也是布局管理器的一種。它把一系列的窗口部件排列成類似堆棧的樣子,但 每次只能有一個窗口部件是當前的可見窗口。 ### 11.4.1 使用方法 QStackedLayout 類被用來創建堆棧布局的實例。使用堆棧布局創建出來的應用程序的 樣子與使用 QTabWidget 創建的效果有些相像。也可以使用 QStackedWidget 類來創建一個 應用程序界面,和使用 QStackedLayout 效果差不多,目前在最新的 4.5.2 版 Qt 中,我們如果使用 Qt Designer 創建用戶界面,那么通常會使用 QStackedWidget,這點在后面還會講到。 實際上,你可以把堆棧布局看成是由一系列的子窗口部件組成的,它們都是一些 “頁 面”(pages)。 在使用堆棧布局時,首先應包含其頭文件: ``` #include &lt;QStackedLayout&gt; ``` 下面是手寫代碼創建一個堆棧布局的實例: ``` QWidget *firstPageWidget = new QWidget; QWidget *secondPageWidget = new QWidget; QWidget *thirdPageWidget = new QWidget; QStackedLayout *stackedLayout = new QStackedLayout; stackedLayout-&gt;addWidget(firstPageWidget); stackedLayout-&gt;addWidget(secondPageWidget); stackedLayout-&gt;addWidget(thirdPageWidget); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout-&gt;addLayout(stackedLayout); setLayout(mainLayout); ``` 創建棧布局的大致步驟如下: 第 1 步,創建布局內的窗口部件,也即是各個頁面。 第 2 步,創建棧布局的實例,也就是創建一個 QStackedLayout 類的實例,并將第 1 步 創建的窗口部件加入到布局之中。 向布局內加入窗口部件的方法可以使用 addWidget(),也可以使用 insertWidget(), 前者將把窗口部件加入到子窗口索引的最后,而后者則可以指定在索引中的位置加入窗口部 件。可以根據實際需要選用。 第 3 步,調用 QWidget::setLayout()函數將布局安裝到窗體上。 11.4.2 如何索引窗口部件 由于 QStackedLayout 類并沒有提供位于其內部的窗口部件(即上文提到的 “頁面”) 的索引,所以我們在使用堆棧布局時,通常需要使用組合框類( QComboBox)或者列表部件 類(QListWidget)的實例來存儲這些子窗口的索引,繼而實現切換堆棧布局中子窗口的目 的。下面是一個使用 QComboBox 類的實例: ``` QComboBox *pageComboBox = new QComboBox; pageComboBox-&gt;addItem(tr("Page 1")); pageComboBox-&gt;addItem(tr("Page 2")); pageComboBox-&gt;addItem(tr("Page 3")); connect(pageComboBox, SIGNAL(activated(int)), stackedLayout, SLOT(setCurrentIndex(int))); ``` 在上述代碼中,通過 addItem()方法為 QComboBox 的實例依次加入堆棧布局的索引,這樣當調用 connect()函數顯式的連接 pageComboBox 的 activated()信號和 stackedLayout 的 setCurrentIndex()槽時,這些索引就會被加入到內部的一個鏈表中,這樣就可以方便的 查找布局內的窗口部件了。 要獲得棧布局內的窗口部件的數量,可以使用 count()方法。 那么我們如何找到位于堆棧布局內的任意一個子窗口呢,可以使用堆棧窗口的 widget() 方法返回當前指定位置索引的子窗口,它的原型如下: ``` QWidget * QStackedLayout::widget ( int index ) const ``` 它將返回由 index 指定的位置的子窗口,當返回值為 0 時,則表示在 index 指定的位置處并沒有任何子窗口。 作為上述的一個特例,要找到當前的活動子窗口,可以先找到當前它對應的 index,方 法是使用 currentIndex()方法,它的原型如下: ``` int currentIndex () const ``` 如果要取得某一個窗口部件在布局中的索引,可以使用 indexof()方法,其原型如下: ``` int QLayout::indexOf ( QWidget * widget ) const [virtual] ``` 該方法將 widget 在布局內的索引返回,如果返回值為-1,則表示沒有找到這個窗口部件。 小貼士:實際上堆棧布局有一個重要的屬性 currentIndex : int,是一個 int 常量,它對 應當前活動子窗口的索引,獲得該屬性值的方法即是調用 currentIndex()方法。如果它的 值為-1,則表示沒有當前活動子窗口,也就是沒有子窗口在堆棧布局內。 要想找到當前的活動子窗口,可以使用 currentWidget()方法,它的原型如下: ``` QWidget * QStackedLayout::currentWidget () const ``` 它將返回堆棧布局內當前的活動子窗口,如果返回值為 0,則表示沒有當前的 堆棧布局內沒有子窗口,由此這個函數也可以被用來判斷當前布局內是否存在窗口部件。 要想指定一個位于堆棧布局內部的子窗口為當前的活動窗口,可以使用 setCurrentWidget()方法,它的原型如下: ``` void QStackedLayout::setCurrentWidget ( QWidget * widget ) [slot] ``` 它將把你指定的 widget 作為當前的活動子窗口,前提是這個子窗口必須已經位于堆棧 布局內部。 此外,一旦堆棧布局內當前的窗口部件產生了變化或者被移除,布局就會發 出 currentChanged() 以及 widgetRemoved() 信號。 ### 11.4.3 實例-堆棧窗體 本實例實現一個堆棧窗體的使用,實現的效果如圖 11-23 所示。當用戶選擇左側列表 框中不同的選項時,右側則對應顯示所選的窗體。 ![](https://box.kancloud.cn/2016-01-22_56a1a15932f53.png) 圖 11-23 堆棧窗體實例 為了使讀者朋友熟練掌握使用方法,這里將用兩種方法為大家分別實現,一是完全手 寫代碼的方法,源代碼見實例 stack。二是使用 Qt Designer 設計界面,然后在 Qt Creator 中創建工程輔以部分手寫代碼的方法,源代碼見 stackDlg。 1\.完全手寫代碼 實現頭文件 stackdlg.h。 ``` class StackDlg : public QDialog { Q_OBJECT public: StackDlg(QWidget *parent = 0, Qt::WindowFlags f1 = 0); QLabel *label1; QLabel *label2; QLabel *label3; QListWidget *listWidget; QStackedWidget *stackWidget; }; ``` 在頭文件中聲明一個對話框類,它繼承自 QDialog,然后聲明所用到的窗口部件。 實現源文件 stackdlg.cpp。 ``` StackDlg::StackDlg(QWidget *parent, Qt::WindowFlags f1) : QDialog(parent,f1) { setWindowTitle(tr("Stacked Widgets")); listWidget = new QListWidget(this); listWidget-&gt;insertItem(0,tr("The Window 1")); listWidget-&gt;insertItem(1,tr("The Window 2")); listWidget-&gt;insertItem(2,tr("The Window 3")); label1 = new QLabel(tr("It is Window 1 !")); label2 = new QLabel(tr("It is Window 2 !")); label3 = new QLabel(tr("It is Window 3 !")); stackWidget = new QStackedWidget(this); stackWidget-&gt;addWidget(label1); stackWidget-&gt;addWidget(label2); stackWidget-&gt;addWidget(label3); QHBoxLayout *mainLayout = new QHBoxLayout(this); mainLayout-&gt;setMargin(5); mainLayout-&gt;setSpacing(5); mainLayout-&gt;addWidget(listWidget); mainLayout-&gt;addWidget(stackWidget,0,Qt::AlignHCenter); mainLayout-&gt;setStretchFactor(listWidget,1); mainLayout-&gt;setStretchFactor(stackWidget,3); connect(listWidget,SIGNAL(currentRowChanged(int)),stackWidget,SLOT(setCurrentIndex(int))); } ``` 第 1 行設置應用程序的標題,注意要使用 tr()函數。 第 2-5 行創建樂一個 QListWidget 窗口部件的實例,并在其中插入 3 個條目,當我們 在 3 個條目之間切換時,右面的堆棧窗口將會對應變化 。 第 6-8 行依次創建了 3 個 QLabel 窗口部件的實例,作為右面的堆棧窗口中對應顯示的 3 個窗體。 第 9 行創建了一個 QStackWidget 堆棧窗體的實例。 第 10-12 行調用 addWidget()方法把前面創建的 3 個 QLabel 窗體部件的實例依次插入 到堆棧窗中。 第 13 行設置了一個頂層(Top Level)布局,它是一個 QHBoxLayout 實例。 第 14 行調用 setMargin()函數設置布局距離窗體邊界的尺寸。 第 15 行調用 setSpacing()設置了在該布局中的窗體部件之間的距離。該函數的原型如 下: ``` void setSpacing ( int ) ``` 小貼士:QLayout 有兩個非常重要的屬性: + sizeConstraint : SizeConstraint 該屬性定義了布局的伸縮模式。 + spacing : int 該屬性定義了在一個布局內部的窗口部件之間的距離,也就是間距。 如果沒有明確的設置該屬性值,那么該布局將繼承它的父布局的設置,或者該布局中的 窗口部件將繼承它們的父窗口部件的設置。 再次提醒,當使用 QGridLayout 或者 QFormLayout 布局時,很可能要分別設置不同的水 平和垂直方向的間距,這時就可以使用 setHorizontalSpacing() 、 setVerticalSpacing()這兩個方法。當調用了這兩個方法設置了水平和垂直間距后,再調用 spacing()獲取該屬性,這時它的返回值就是-1 了。 第 20 行連接 QListWidget 的 currentRowChanged()信號與堆棧窗的 setCurrentIndex() 槽,實現按選擇顯示窗體。此處的堆棧窗體 index 按插入的順序從 0 起依次排序,與 QListWidget 的條目排序相一致。 2\.Qt Designer 結合 Qt Creator 實現 本實例分析了堆棧窗的基本使用方法。在實際應用中,堆棧窗口多與列表框 QListWidget 或者下拉列表框 QComboBox 配合使用。 這種方法是前面第 5 章所講述的 Qt 編程的 3 種基本方法之一,在此引領大家溫習一 遍。對于.ui 文件的使用我們選用單繼承法,如果對此法的使用還有不熟悉的地方,請回到 第 7 章復習。 項目的實現步驟如下: 第 1 步,創建一個新的項目 打開 Qt Designer,創建一個名為 stackDesigner 的新的項目,項目類型為用以存放項目文件。 第 2 步,創建程序界面文件(.ui 文件) I\. 啟動 Qt Designer,在其中創建本程序的界面,模板的類型可以使 Widget 或者是 Dialog 等。 II\. 從窗口部件盒內依次拖拉出 1 個 ListWidget、1 個 Horizontal Spacer 和 1 個 Stacked Widget,把它們擺放在大致的位置即可,它們構成了頂級布局的要素。 III\. 然后在 ListWidget 的界面上雙擊鼠標左鍵,即可在彈出的如圖 11-24 所示的【編輯 列表窗口部件】對話框中為列表添加項目,依次添加 3 個:window1、window2 和 window3。 ![](https://box.kancloud.cn/2016-01-22_56a1a1593fc34.png) 圖 11-24 為列表窗口部件添加項目 IV\. 接下來,為堆棧窗口部件添加子窗口部件,也就是頁。初始情況下,堆棧窗口已經 為我們內置了兩個頁,我們從窗口部件盒中拖出 2 個 Label,分別放入兩個頁中。 注意,切換這兩個頁的方式是用鼠標點擊堆棧窗口右上角的那兩個黑色的三角形的導 航按鈕,左邊的那個是向前翻頁,右邊的那個是向后翻頁。 V\. 然后我們需要為堆棧窗口部件添加第 3 個頁,方法先切換到第 2 個頁,然后用鼠標 右鍵點擊那兩個導航按鈕之一,在彈出的上下文菜單中依次選擇 【插入頁】→【在當前頁 之后】,就完成了第 3 個頁的插入。然后仿照上面的步驟,向其中加入 1 個 Label。 VI\. 這之后,再在每個頁面上 Label 的左右兩側各放置一個 Horizontal Spacer。 VII\. 接下來我們為窗口部件設置屬性,為簡單起見,都取默認屬性,而 3 個 Label 窗口 部件的 text 屬性設置為 It is Window 1、It is Window 2 和 It is Window3。 必須要設置的是 Stacked Widget 的第 3 個頁的 objectName 屬性,這是 Qt Designer 的一個 bug,在目前的 4.5.2 版 Qt 里,你自己增加的頁面的 objectName 屬性將被 Qt Designer 命名為類似“頁”的亂碼,這將導致后面 qmake 運行時的錯誤。把它手動修改為 page_3。 VIII\. 然后我們從里到外,依次為窗口部件布置布局。 布置好的樣子如圖 11-25 所示,你可以清楚的看到各個布局的情況,在此不再贅述。 ![](https://box.kancloud.cn/2016-01-22_56a1a15951a5a.png) 圖 11-25 在對象查看器中看到的布局情況 第 3 步,向項目中引入該界面文件。 把這個文件命名為 stack Designer,保存在我們的項目目錄下。在項目上點擊鼠標右 鍵,在上下文菜單中選擇【Add Existing Files...】,把該.ui 文件加入到工程中。 第 4 步,運行 qmake,以生成 ui_stackDesigner.h 頭文件。 這時,先運行一下 qmake,它將調用 moc,以生成需要的 ui_stackDesigner.h 頭文件。 第 5 步,自定義一個界面類,采用單繼承方法使用界面文件。 首先新建一個名為 stackDesignerDlg.h 的頭文件,其內容如下: ``` #ifndef STACKDESIGNERDLG_H #define STACKDESIGNERDLG_H #include &lt;QtGui&gt; #include "ui_stackDesigner.h" class StackDesignerDlg : public QDialog { Q_OBJECT public: StackDesignerDlg(QWidget *parent = 0, Qt::WindowFlags f1 = 0); private: Ui::Form ui; }; #endif // STACKDESIGNERDLG_H ``` 在其中定義了該類公有單繼承自 QDialog,以及它的構造函數。最重要的是聲明了一個私有變量 ui,它是界面原生類的對象,這是單繼承法最明顯的特征。再建立該類的實現文件,其內容如下: ``` #include "stackDesignerDlg.h" StackDesignerDlg::StackDesignerDlg(QWidget *parent, Qt::WindowFlags f1) : QDialog(parent,f1) { setWindowTitle(tr("Stacked Widgets")); ui.setupUi(this); connect(ui.listWidget,SIGNAL(currentRowChanged(int)),ui.stackedWidget,SLOT(setCurrentIndex(int))); } ``` 為簡單起見,這里主要實現了其構造函數。 首先加入了類頭文件聲明。然后設置程序的標題,調用 setupUi()方法來完成界面布局 的初始化。 接下來把 listWidget 的 currentRowChanged()信號和 stackedWidget 的 setCurrentIndex()槽關聯起來。 第 6 步,書寫主程序文件。 完成了界面類的定義后,最后新建一個 main.cpp 文件,其內容如下: ``` #include &lt;QApplication&gt; #include "stackDesignerDlg.h" int main( int argc, char * argv[] ) { QApplication a( argc, argv ); StackDesignerDlg stack; stack.show(); return a.exec(); } ``` 這段代碼中定義一個我們剛才定義的界面類的實例,然后把它顯示出來。 第 7 步,編譯運行程序。 我們采用快捷鍵,依次按下 Ctrl+B 和 Ctrl+R 編譯運行程序,其效果如圖 11-26 所 示,與手寫代碼無異。 ![](https://box.kancloud.cn/2016-01-22_56a1a1596238a.png) 圖 11-26 程序運行效果 需要注意的是,目前的 Qt Creator 并沒有把 Qt Designer 的全部功能集成進來,比如 我們無法在其中預覽 Qt Designer 生成的界面效果,因而筆者建議大家最好還是直接在 Qt Designer 中設計界面,然后使用 Qt Creator 完成項目的構建。 總而言之,這兩種方法都是常用的,且各有長處。手寫代碼的方式似乎更加簡潔,而 Qt Designer 結合 Qt Creator 的方式能使編程過程簡化,且可以直觀的驗證你的布局情 況。讀者朋友可以根據自己的喜好掌握。而筆者建議最好是將手寫代碼方式弄通,熟練之后 再使用 IDE 的方式,這樣也能更好的理解 Qt 編程的精髓。
                  <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>

                              哎呀哎呀视频在线观看