QT中有九種容器組件,分別是組合框QGroupBox、滾動區QScrollArea、工具箱QToolBox、選項卡QTabWidget、控件棧QWidgetStack、框架QFrame、組件QWidget、MDI窗口顯示區QMdiArea、停靠窗口QDockWidget。
本博主要介紹:組合框QGroupBox、滾動區QScrollArea、工具箱QToolBox、選項卡QTabWidget
一、控件棧QWidgetStack
(1)屬性
class Q_WIDGETS_EXPORT QStackedWidget : public QFrame { Q_OBJECT Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged) Q_PROPERTY(int count READ count) 。。。。。。。。。。。。。。。 }
(2)常用函數
int addWidget(QWidget *w); int insertWidget(int index, QWidget *w); void removeWidget(QWidget *w); QWidget *currentWidget() const; int currentIndex() const; int indexOf(QWidget *) const; QWidget *widget(int) const; int count() const;
(3)信號、槽
public Q_SLOTS: void setCurrentIndex(int index); void setCurrentWidget(QWidget *w); Q_SIGNALS: void currentChanged(int); void widgetRemoved(int index);
(4)示例
#include "mainwindow.h" #include <QApplication> #include <QListWidget> #include <QHBoxLayout> #include <QLabel> #include <QStackedWidget> #include <QObject> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; QWidget *pWidget = new QWidget(&w); QHBoxLayout *pLayout = new QHBoxLayout(pWidget); QStackedWidget *pStackedWidget = new QStackedWidget(pWidget); QListWidget* pList = new QListWidget(pWidget); pList->insertItem(0, "label0"); pList->insertItem(1, "label1"); pList->insertItem(2, "label2"); QLabel* pLabel0 = new QLabel("label0 test"); QLabel* pLabel1 = new QLabel("label1 test"); QLabel* pLabel2 = new QLabel("label2 test"); pStackedWidget->addWidget(pLabel0); pStackedWidget->addWidget(pLabel1); pStackedWidget->addWidget(pLabel2); w.connect(pList, SIGNAL(currentRowChanged(int)), pStackedWidget, SLOT(setCurrentIndex(int))); pLayout->addWidget(pList); pLayout->addWidget(pStackedWidget,0,Qt::AlignCenter); pLayout->setStretchFactor(pList, 1); pLayout->setStretchFactor(pStackedWidget, 3); pWidget->setLayout(pLayout); w.setCentralWidget(pWidget); w.setWindowTitle("container test"); w.setMinimumSize(50,50); w.show(); return a.exec(); }

二、QMdiArea多文檔區域組件
QMdiArea組件中文稱作“MDI窗口顯示區”,MDI是 Multiple Document Interface的簡稱,中文意思是多文檔界面,主要適用於完成一項工作時需要用到多個文件。QMainWindow是SDI(Signal Document Interface,單文檔界面)每個開啟的文件占據一個視窗,主要適用於所有工作沒有太多文件參與的情況。
QMdiSubWindow類繼承自QWidget,主要用來創建MDI子窗體實例
QtExmaple中提供了相應的例子:\Examples\Qt-5.9.3\widgets\mainwindows\mdi

(1)屬性
背景、窗口順序(SubWindowList)、視圖模式(SubWindowView/tabbedView)、tabsClosable、tabsMovable、TabPositionTabShape
class Q_WIDGETS_EXPORT QMdiArea : public QAbstractScrollArea { Q_OBJECT Q_PROPERTY(QBrush background READ background WRITE setBackground) Q_PROPERTY(WindowOrder activationOrder READ activationOrder WRITE setActivationOrder) Q_PROPERTY(ViewMode viewMode READ viewMode WRITE setViewMode) #if QT_CONFIG(tabbar) Q_PROPERTY(bool documentMode READ documentMode WRITE setDocumentMode) Q_PROPERTY(bool tabsClosable READ tabsClosable WRITE setTabsClosable) Q_PROPERTY(bool tabsMovable READ tabsMovable WRITE setTabsMovable) #endif #if QT_CONFIG(tabwidget) Q_PROPERTY(QTabWidget::TabShape tabShape READ tabShape WRITE setTabShape) Q_PROPERTY(QTabWidget::TabPosition tabPosition READ tabPosition WRITE setTabPosition) 。。。。。。。。。。。 }
(2)常用函數、信號、槽
QSize sizeHint() const Q_DECL_OVERRIDE; QSize minimumSizeHint() const Q_DECL_OVERRIDE; QMdiSubWindow *currentSubWindow() const; QMdiSubWindow *activeSubWindow() const; QList<QMdiSubWindow *> subWindowList(WindowOrder order = CreationOrder) const; QMdiSubWindow *addSubWindow(QWidget *widget, Qt::WindowFlags flags = Qt::WindowFlags()); void removeSubWindow(QWidget *widget); QBrush background() const; void setBackground(const QBrush &background); WindowOrder activationOrder() const; void setActivationOrder(WindowOrder order); void setOption(AreaOption option, bool on = true); bool testOption(AreaOption opton) const; void setViewMode(ViewMode mode); ViewMode viewMode() const;
Q_SIGNALS: void subWindowActivated(QMdiSubWindow *); public Q_SLOTS: void setActiveSubWindow(QMdiSubWindow *window); void tileSubWindows(); void cascadeSubWindows(); void closeActiveSubWindow(); void closeAllSubWindows(); void activateNextSubWindow(); void activatePreviousSubWindow(); protected Q_SLOTS: void setupViewport(QWidget *viewport) Q_DECL_OVERRIDE;
(3)示例
:\Examples\Qt-5.9.3\widgets\mainwindows\mdi
(4)注意Mdi子窗口的關閉
void MainWindow::closeEvent(QCloseEvent *event) { m_pMdiArea->closeAllSubWindows(); if (m_pMdiArea->currentSubWindow()) { event->ignore(); } else { event->accept(); } }
三、QDockWidget停靠窗口
QDockWidget停靠窗體組件,可以作為一個頂層窗口漂浮在桌面,主要作為輔助窗體出現在界面中,可以在很多IDE中看到停靠窗體。
QDockWidget包含工具欄和內容區域,工具欄用於顯示窗口標題,一個浮動按鈕和一個關閉按鈕。QDockWidget可以作為子窗口部件的封裝,通過setWidget()設置子窗口部件。自定義的尺寸提示,最小和最大化尺寸以及尺寸策略都必須由子窗口部件來實現。QDockWidget會遵守它們,調整它自己的限制包括框架和工具欄。我們不應該為QDockWidget設置尺寸限制,因為它們根據QDockWidget是否鎖住而改變,一個鎖住的QDockWidget窗口部件不 包括框架和小的工具欄。

(1)屬性
屬性包括:是否懸浮、停靠窗口特征(移動,關閉,懸浮)、停靠區域、窗口標題
class Q_WIDGETS_EXPORT QDockWidget : public QWidget { Q_OBJECT Q_PROPERTY(bool floating READ isFloating WRITE setFloating) Q_PROPERTY(DockWidgetFeatures features READ features WRITE setFeatures NOTIFY featuresChanged) Q_PROPERTY(Qt::DockWidgetAreas allowedAreas READ allowedAreas WRITE setAllowedAreas NOTIFY allowedAreasChanged) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle DESIGNABLE true) 。。。。。。。。。。。。。。。。。 }
窗口特征枚舉:
enum DockWidgetFeature { DockWidgetClosable = 0x01, DockWidgetMovable = 0x02, DockWidgetFloatable = 0x04, DockWidgetVerticalTitleBar = 0x08, DockWidgetFeatureMask = 0x0f, AllDockWidgetFeatures = DockWidgetClosable|DockWidgetMovable|DockWidgetFloatable, // ### Qt 6: remove NoDockWidgetFeatures = 0x00, Reserved = 0xff };
(2)信號、槽
Q_SIGNALS: void featuresChanged(QDockWidget::DockWidgetFeatures features); void topLevelChanged(bool topLevel); void allowedAreasChanged(Qt::DockWidgetAreas allowedAreas); void visibilityChanged(bool visible); void dockLocationChanged(Qt::DockWidgetArea area); protected: void changeEvent(QEvent *event) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; bool event(QEvent *event) Q_DECL_OVERRIDE; void initStyleOption(QStyleOptionDockWidget *option) const;
(3)示例
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) //ui(new Ui::MainWindow) { setWindowTitle("MDI test"); setMinimumSize(400,400); m_pFileAction = new QAction("open", this); m_pFileMenu = menuBar()->addMenu("File"); m_pFileMenu->addAction(m_pFileAction); connect(m_pFileAction, SIGNAL(triggered(bool)), this, SLOT(openView())); m_pMdiArea = new QMdiArea(this); m_pMdiArea->setViewMode(QMdiArea::TabbedView); m_pMdiArea->setTabShape(QTabWidget::Triangular); m_pMdiArea->setTabPosition(QTabWidget::North); m_pMdiArea->setTabsMovable(true); m_pMdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_pMdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); setCentralWidget(m_pMdiArea); QDockWidget* pDockWidget = new QDockWidget("dockwindow", this); pDockWidget->setFeatures(QDockWidget::DockWidgetFeature::AllDockWidgetFeatures); QWidget* pWidget = new QWidget(this); QVBoxLayout *pLayout = new QVBoxLayout(pWidget); QPushButton *pOkBtn = new QPushButton("ok"); QPushButton *pCancelBtn = new QPushButton("cancel"); pLayout->addWidget(pOkBtn); pLayout->addWidget(pCancelBtn); pDockWidget->setWidget(pWidget); addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, pDockWidget); }

