QtQt控件Qt中容器类型的控件
苏丙榅文章中主要介绍了Qt中常用的容器控件, 包括: Widget, Frame, Group Box, Scroll Area, Tool Box, Tab Widget, Stacked Widget。 关于这些控件的使用除了文字描述、代码演示, 还有相关的视频讲解,赶紧给自己充电吧…
关于QWidget在前面的章节中已经介绍过了, 这个类是所有窗口类的父类, 可以作为独立窗口使用, 也可以内嵌到其它窗口中使用。
Qt中的所有控件都属于窗口类, 因此这个类也是所有控件类的基类。
如果一个窗口中还有子窗口, 为了让子窗口有序排列, 这时候我们可以选择一个QWidget类型的容器, 将子窗口放到里边, 然后再给这个QWidget类型窗口进行布局操作。
在这里给大家介绍一下关于这个类的一些属性,因为这个类是所有窗口类的基类,因此相关属性比较多,详细讲解可以观看视频。
关于这些属性大部分都有对应的API函数, 在属性名前加 set即可, 大家可以自己从 QWidget这个类里边搜索, 并仔细阅读关于这些函数的参数介绍。
在Qt中我们除了使用QWidget类型窗口作为容器使用, 也可以根据实际需求选择其他类型的容器, 下面看看具体都有哪些。
上述容器中, 后边着重为大家介绍一些常用的, 比如:Group Box, Scroll Area, Tool Box, Tab Widget, Stacked Widget, Frame, 关于Dock Widget 在前边的章节中已经介绍过了, 因此不在赘述。
2. Frame
QFrame就是一个升级版的QWidget, 它继承了QWidget的属性, 并且做了拓展, 这种类型的容器窗口可以提供边框, 并且可以设置边框的样式、宽度以及边框的阴影。
2.1 相关API
关于这个类的API, 一般是不在程序中调用的, 但是还是给大家介绍一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
   | 
 
 
 
 
 
 
 
 
 
 
 
  Shape frameShape() const;
  void setFrameShape(Shape);
 
 
 
 
 
 
 
 
 
  Shadow frameShadow() const;
  void setFrameShadow(Shadow);
 
  int lineWidth() const;
  void setLineWidth(int);
 
  int midLineWidth() const;
  void setMidLineWidth(int);
 
  | 
 
2.2 属性设置
这个类的属性并不多, 都是关于边框的设置的。
这个表格显示了一些边框样式和线宽以及阴影的组合:
3. Group Box
QGroupBox类的基类是QWidget, 在这种类型的窗口中可以绘制边框、给窗口指定标题, 并且还支持显示复选框。
3.1 相关API
关于这个类的API不常用, 下面给大家介绍一下在编码过程中可能会用到的一些:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
   |  QGroupBox::QGroupBox(QWidget *parent = Q_NULLPTR); QGroupBox::QGroupBox(const QString &title, QWidget *parent = Q_NULLPTR);
 
  bool QGroupBox::isCheckable() const;
  void QGroupBox::setCheckable(bool checkable);
 
 
 
 
 
 
 
 
 
 
 
  Qt::Alignment QGroupBox::alignment() const;
  void QGroupBox::setAlignment(int alignment);
  QString QGroupBox::title() const;
  void QGroupBox::setTitle(const QString &title);
  bool QGroupBox::isChecked() const;
  [slot] void QGroupBox::setChecked(bool checked);
 
  | 
 
3.2 属性设置
关于组框的属性对应的就是上边介绍的那几个API函数, 属性窗口如下:
组框中的flat属性没有对应的API函数, 只能在属性窗口中设置, 它控制的是窗口边框的绘制方式, 如果打开该属性, 组框的边框就消失了, 效果如下:
QScrollArea这种类型的容器, 里边可以放置一些窗口控件, 当放置的窗口控件大于当前区域导致无法全部显示的时候, 滚动区域容器会自动添加相应的滚动条(水平方向或者垂直方向), 保证放置到该区域中的所有窗口内容都可以正常显示出来。对于使用者不需要做太多事情, 只需要把需要显示的窗口放到滚动区域中就行了。
4.1 相关API
在某些特定环境下, 我们需要动态的往滚动区域内部添加要显示的窗口, 或者动态的将显示的窗口移除, 这时候就必须要调用对应的API函数来完成这部分操作了。主要API有两个 添加 - setWidget(), 移除 - takeWidget()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
   |  QScrollArea::QScrollArea(QWidget *parent = Q_NULLPTR);
 
 
  void QScrollArea::setWidget(QWidget *widget);
  QWidget *QScrollArea::takeWidget();
 
 
 
 
 
 
 
 
 
 
  Qt::Alignment alignment() const;
  void setAlignment(Qt::Alignment);
 
  bool widgetResizable() const;
 
 
 
 
 
 
  void setWidgetResizable(bool resizable);
 
  | 
 
4.2 属性设置
关于滚动区域, 其属性窗口提供的属性一般不需要设置, 因为一般情况下即便是设置了也看不到效果, 即便如此, 还是看一下吧。至于具体原因在视频中有详细的说明,感兴趣的可以去看一下。
4.3 窗口的动态添加和删除
关于窗口的滚动区域对象创建有两种方式, 第一种比较简单在编辑页面直接拖拽一个控件到UI界面, 然后布局即可。第二种方式是在程序中通过new操作创建一个实例对象, 然后通过通过代码的方式将其添加到窗口的某个布局中, 相对来说要麻烦一点。
下面通过第一种方式,演示一下如果往滚动区域中添加多个子窗口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | MainWindow::MainWindow(QWidget *parent)     : QMainWindow(parent)     , ui(new Ui::MainWindow) {     ui->setupUi(this);
           QVBoxLayout* vlayout = new QVBoxLayout;
      for(int i=0; i<11; ++i)     {                  QLabel* pic = new QLabel;                  QString name = QString(":/images/%1.png").arg(i+1);                  pic->setPixmap(QPixmap(name));                  pic->setAlignment(Qt::AlignHCenter);                  vlayout->addWidget(pic);     }
           QWidget* wg = new QWidget;          wg->setLayout(vlayout);          ui->scrollArea->setWidget(wg); }
   | 
 
关于以上代码做以下说明, 调用setWidget(wg)之后, wg会自动平铺填充满整个滚动区域, 因此:
- 在程序中调用 
void setWidgetResizable(bool resizable);不会有明显效果 
- 在程序中调用 
void setAlignment(Qt::Alignment);不会看到任何效果 
- 如果要设置显示的图片的对其方式要设置图片的载体对象即 
标签签对象 
- 如果要动态移除滚动区域中的窗口, 直接使用滚动区域对象调用 
takeWidget() 即可 
- 滚动区域中只能通过
setWidget(wg)添加一个子窗口, 如果要添加多个可使用布局的方式来实现 
代码效果展示:
QToolBox工具箱控件, 可以存储多个子窗口, 该控件可以实现类似QQ的抽屉效果, 每一个抽屉都可以设置图标和标题, 并且对应一个子窗口, 通过抽屉按钮就可以实现各个子窗口显示的切换。
5.1 相关API
这个类对应的API函数相对较多, 一部分是控件属性对应的属性设置函数, 一部分是编程过程中可能会用的到的, 怎么说呢, 理解为主吧, 知道有这么函数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   |  QToolBox::QToolBox(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
 
 
 
 
 
 
 
 
 
  int QToolBox::addItem(QWidget *widget, const QString &text); int QToolBox::addItem(QWidget *widget, const QIcon &icon, const QString &text);
  int QToolBox::insertItem(int index, QWidget *widget, const QString &text); int QToolBox::insertItem(int index, QWidget *widget, const QIcon &icon,                           const QString &text);
  void QToolBox::removeItem(int index);
 
  void QToolBox::setItemEnabled(int index, bool enabled);
  void QToolBox::setItemIcon(int index, const QIcon &icon);
  void QToolBox::setItemText(int index, const QString &text);
  void QToolBox::setItemToolTip(int index, const QString &toolTip);
 
  bool QToolBox::isItemEnabled(int index) const;
  QIcon QToolBox::itemIcon(int index) const;
  QString QToolBox::itemText(int index) const;
  QString QToolBox::itemToolTip(int index) const;
 
  int QToolBox::currentIndex() const;
  QWidget *QToolBox::currentWidget() const;
  int QToolBox::indexOf(QWidget *widget) const;
  int QToolBox::count() const;
 
 
  [signal] void QToolBox::currentChanged(int index);
 
 
  [slot] void QToolBox::setCurrentIndex(int index);
  [slot] void QToolBox::setCurrentWidget(QWidget *widget);
 
  | 
 
5.2 属性设置
关于这个容器控件的属性远比上边介绍的API要少, 来看一看吧
QTabWidget的一种带标签页的窗口,在这种类型的窗口中可以存储多个子窗口,每个子窗口的显示可以通过对应的标签进行切换。
6.1 相关API
介绍的这些API大部分是进行属性设置的, 因此我们可以完全不在程序中使用这些函数, 通属性窗口进行设置, 但是API操作比较灵活, 可以动态的设置相关属性。先来看公共成员函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
   |  QTabWidget::QTabWidget(QWidget *parent = Q_NULLPTR);
 
 
 
 
 
 
 
 
  int QTabWidget::addTab(QWidget *page, const QString &label); int QTabWidget::addTab(QWidget *page, const QIcon &icon, const QString &label); int QTabWidget::insertTab(int index, QWidget *page, const QString &label); int QTabWidget::insertTab(int index, QWidget *page,                            const QIcon &icon, const QString &label);
  void QTabWidget::removeTab(int index);
 
  int count() const;
  void QTabWidget::clear();
  int QTabWidget::currentIndex() const;
  QWidget *QTabWidget::currentWidget() const;
  QWidget *QTabWidget::widget(int index) const;
 
 
 
 
 
 
 
 
  Qt::TextElideMode QTabWidget::elideMode() const;
  void QTabWidget::setElideMode(Qt::TextElideMode);     
  QSize QTabWidget::iconSize() const
  void QTabWidget::setIconSize(const QSize &size)
 
  bool QTabWidget::isMovable() const;
  void QTabWidget::setMovable(bool movable);
 
  bool QTabWidget::tabBarAutoHide() const;
  void QTabWidget::setTabBarAutoHide(bool enabled);
 
  bool QTabWidget::isTabEnabled(int index) const;
  void QTabWidget::setTabEnabled(int index, bool enable);
 
  QIcon QTabWidget::tabIcon(int index) const;
  void QTabWidget::setTabIcon(int index, const QIcon &icon);
 
 
 
 
 
 
 
 
  TabPosition QTabWidget::tabPosition() const;
  void QTabWidget::setTabPosition(TabPosition);
 
 
 
 
 
 
  TabShape QTabWidget::tabShape() const;
  void QTabWidget::setTabShape(TabShape s);
 
  QString QTabWidget::tabText(int index) const;
  void QTabWidget::setTabText(int index, const QString &label);
 
 
  QString QTabWidget::tabToolTip(int index) const;
  void QTabWidget::setTabToolTip(int index, const QString &tip);
 
 
  bool QTabWidget::tabsClosable() const;
  void QTabWidget::setTabsClosable(bool closeable);
 
 
  bool QTabWidget::usesScrollButtons() const;
 
  void QTabWidget::setUsesScrollButtons(bool useButtons);
 
  bool QTabWidget::documentMode() const;
 
  void QTabWidget::setDocumentMode(bool set);
 
  | 
 
信号
1 2 3 4 5 6 7 8 9
   |  [signal] void QTabWidget::currentChanged(int index);
  [signal] void QTabWidget::tabBarClicked(int index)
 
  [signal] void QTabWidget::tabBarDoubleClicked(int index);
  [signal] void QTabWidget::tabCloseRequested(int index);
 
  | 
 
槽函数
1 2 3 4
   |  [slot] void QTabWidget::setCurrentIndex(int index);
  [slot] void QTabWidget::setCurrentWidget(QWidget *widget);
 
  | 
 
6.2 属性设置
容器类型的控件其大多数情况下都是直接在属性窗口中直接设置, 因为这些属性设置完毕之后, 就无需再做修改了, 程序运行过程中无需做任何变化。下图为大家标注了每个属性对应的功能。
6.3 控件使用
关于这个控件的使用, 主要是通过代码的方式演示一下相关信号发射的时机, 再有就是当标签页添加了关闭按钮并点击了该按钮, 如果移除该标签页已经如何将其再次添加到窗口中。
第一步, 在头文件中添加存储已关闭的标签对应的窗口对象和标签标题的容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |  QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE
  class MainWindow : public QMainWindow {     Q_OBJECT
  public:     MainWindow(QWidget *parent = nullptr);     ~MainWindow();
  private:     Ui::MainWindow *ui;     QQueue<QWidget*> m_widgets;	     QQueue<QString> m_names;     };
 
  | 
 
第二步在源文件中添加处理动作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
   |  MainWindow::MainWindow(QWidget *parent)     : QMainWindow(parent)     , ui(new Ui::MainWindow) {     ui->setupUi(this);
           connect(ui->tabWidget, &QTabWidget::tabCloseRequested, this, [=](int index)     {                  QWidget* wg = ui->tabWidget->widget(index);         QString title = ui->tabWidget->tabText(index);         m_widgets.enqueue(wg);         m_names.enqueue(title);                  ui->tabWidget->removeTab(index);         ui->addBtn->setEnabled(true);
      });
           connect(ui->tabWidget, &QTabWidget::tabBarClicked, this, [=](int index)     {         qDebug() << "我被点击了一下, 我的标题是: " << ui->tabWidget->tabText(index);     });
           connect(ui->tabWidget, &QTabWidget::currentChanged, this, [=](int index)     {         qDebug() << "当前显示的tab页, 我的标题是: " << ui->tabWidget->tabText(index);     });
           connect(ui->addBtn, &QPushButton::clicked, this, [=]()     {                                    ui->tabWidget->addTab(m_widgets.dequeue(), m_names.dequeue());         if(m_widgets.empty())         {             ui->addBtn->setDisabled(true);         }     }); }
 
  | 
 
测试代码效果演示:
QStackedWidget 栈类型窗口, 在这种类型的窗口中可以存储多个子窗口, 但是只有其中某一个可以被显示出来, 至于是哪个子窗口被显示, 需要在程序中进行控制,在这种类型的窗口中没有直接切换子窗口的按钮或者标签。
7.1 相关API
先来了解一些这个类为我们提供的API, 在这些函数中最常用的就是它的槽函数, 并且名字和 QToolBox, QTabWidget 两个类提供的槽函数名字相同 分别为 setCurrentIndex(int), setCurrentWidget(QWidget*) 用来设置当前显示的窗口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   |  QStackedWidget::QStackedWidget(QWidget *parent = Q_NULLPTR);
 
 
  int QStackedWidget::addWidget(QWidget *widget);
  int QStackedWidget::insertWidget(int index, QWidget *widget);
  void QStackedWidget::removeWidget(QWidget *widget);
 
  int QStackedWidget::count() const;
  int QStackedWidget::currentIndex() const;
  QWidget *QStackedWidget::currentWidget() const;
  QWidget *QStackedWidget::widget(int index) const;
  int QStackedWidget::indexOf(QWidget *widget) const;
 
 
  [signal] void QStackedWidget::currentChanged(int index);
  [signal] void QStackedWidget::widgetRemoved(int index);
 
 
  [slot] void QStackedWidget::setCurrentIndex(int index); [slot] void QStackedWidget::setCurrentWidget(QWidget *widget);
 
  | 
 
7.2 属性设置
因为栈类型的窗口容器很简单, 所以对应的属性页很少, 只有两个:
7.3 控件使用
这里主要给大家演示一下QStackedWidget类型的容器中的子窗口如何切换, 如下图所示, 我们在一个栈窗口容器中添加了两个子窗口, 通过两个按钮对这两个窗口进行切换
关于窗口的切换调用这个类的槽函数就可以了, 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | MainWindow::MainWindow(QWidget *parent)     : QMainWindow(parent)     , ui(new Ui::MainWindow) {     ui->setupUi(this);          ui->stackedWidget->setCurrentWidget(ui->window1);
      connect(ui->showWin1, &QPushButton::clicked, this, [=]()     { 	         ui->stackedWidget->setCurrentIndex(0);     });
      connect(ui->showWin2, &QPushButton::clicked, this, [=]()     {                  ui->stackedWidget->setCurrentWidget(ui->window2);     }); }
   | 
 
代码效果展示:
8. 视频讲解
以上知识点对应的视频讲解可以关注 B站-爱编程的大丙
视频地址: https://www.bilibili.com/video/BV1Ai4y1c7Di