九、容器组控件containers
9.1 组合框QGroupBox
分组框提供框架、顶部的标题、键盘快捷键,并在自身内部显示各种其他小部件。键盘快捷方式将键盘焦点移动到组框的子小组件之一。
QGroupBox 还允许您设置标题(通常在构造函数中设置)和标题 的对齐方式 。可以选中 组框。启用或禁用可选中组框中的子小组件,具体取决于是否选中 了组框。
您可以通过启用 flat 属性来最大程度地减少分组框的空间消耗。在大多数样式 中,启用此属性会导致删除框架的左、右和下边缘。
QGroupBox 不会自动布置子小部件(通常是 QCheckBox es 或 QRadioButton s,但可以是任何小部件)。
这次我们创建QWidget工程,并且只在widget.cpp中完成代码。
widget.cpp
我们创建一个单选按钮组合框。
QGridLayout *gl=new QGridLayout(this);
QGroupBox *gb1=new QGroupBox("单选按钮组合框");
QRadioButton *rb1=new QRadioButton("单选按钮1");
QRadioButton *rb2=new QRadioButton("单选按钮2");
QVBoxLayout *vbl=new QVBoxLayout;
vbl->addWidget(rb1);
vbl->addWidget(rb2);
gb1->setLayout(vbl);
gl->addWidget(gb1,0,0,1,1);
首先我们创建一个布局对象用来对组合框布局,然后创建一个组合框对象、两个单选按钮对象和一个垂直布局对象,垂直布局对象用来对单选按钮进行布局的。
这时候我们应该先把单选按钮对象放入到垂直布局里,然后再把垂直布局对象放入到组合框,最后再对组合框进行布局。
以下依次类推
QGroupBox *gb2=new QGroupBox("复选框按钮组合框");
QCheckBox *cb1=new QCheckBox("复选框1");
QCheckBox *cb2=new QCheckBox("复选框2");
cb1->setChecked(true);
QVBoxLayout *vbl2=new QVBoxLayout;
vbl2->addWidget(cb1);
vbl2->addWidget(cb2);
gb2->setLayout(vbl2);
gl->addWidget(gb2,0,1,1,1);
QGroupBox *gb3=new QGroupBox("综合按钮组合框");
gb3->setCheckable(true);
gb3->setChecked(true);
QPushButton *pb1=new QPushButton("命令按钮1");
QPushButton *pb2=new QPushButton("命令按钮2");
pb2->setCheckable(true);
pb2->setChecked(true);
QPushButton *pb3=new QPushButton("命令按钮3");
//给命令按钮添加子菜单
QMenu *m=new QMenu(this);
m->addAction("zhangsan");
m->addAction("lisi");
m->addAction("wangwu");
pb3->setMenu(m);
QVBoxLayout *vbl3=new QVBoxLayout;
vbl3->addWidget(pb1);
vbl3->addWidget(pb2);
vbl3->addWidget(pb3);
gb3->setLayout(vbl3);
gl->addWidget(gb3,0,2,1,1);
setCheckable(bool):
此属性用于确定组框的标题中是否有复选框
如果此属性为true,则组框将使用复选框代替普通标签显示其标题。如果选中复选框,则启用组框的子框;否则,它们将被禁用并无法访问。
默认情况下,组框不可选中。
如果为组框启用了此属性,则还将在初始时选中该属性,以确保启用了其内容。
QAction *QMenu::addAction(const QString &text):
这个方便的函数创建一个带有文本的新操作。该函数将新创建的操作添加到菜单的操作列表中,并返回该操作。
QMenu获取返回的QAction的所有权。
完整代码
#include "widget.h"
#include "ui_widget.h"
#include<QGroupBox>
#include<QPushButton>
#include<QRadioButton>
#include<QCheckBox>
#include<QGridLayout>
#include<QVBoxLayout> //可以在水平方向和垂直方向进行排列的控件,QHBoxLayout/QVBoxLayout所继承
#include<QMenu>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout *gl=new QGridLayout(this);
QGroupBox *gb1=new QGroupBox("单选按钮组合框");
QRadioButton *rb1=new QRadioButton("单选按钮1");
QRadioButton *rb2=new QRadioButton("单选按钮2");
QVBoxLayout *vbl=new QVBoxLayout;
vbl->addWidget(rb1);
vbl->addWidget(rb2);
gb1->setLayout(vbl);
gl->addWidget(gb1,0,0,1,1);
QGroupBox *gb2=new QGroupBox("复选框按钮组合框");
QCheckBox *cb1=new QCheckBox("复选框1");
QCheckBox *cb2=new QCheckBox("复选框2");
cb1->setChecked(true);
QVBoxLayout *vbl2=new QVBoxLayout;
vbl2->addWidget(cb1);
vbl2->addWidget(cb2);
gb2->setLayout(vbl2);
gl->addWidget(gb2,0,1,1,1);
QGroupBox *gb3=new QGroupBox("综合按钮组合框");
gb3->setCheckable(true);
gb3->setChecked(true);
QPushButton *pb1=new QPushButton("命令按钮1");
QPushButton *pb2=new QPushButton("命令按钮2");
pb2->setCheckable(true);
pb2->setChecked(true);
QPushButton *pb3=new QPushButton("命令按钮3");
//给命令按钮添加子菜单
QMenu *m=new QMenu(this);
m->addAction("zhangsan");
m->addAction("lisi");
m->addAction("wangwu");
pb3->setMenu(m);
QVBoxLayout *vbl3=new QVBoxLayout;
vbl3->addWidget(pb1);
vbl3->addWidget(pb2);
vbl3->addWidget(pb3);
gb3->setLayout(vbl3);
gl->addWidget(gb3,0,2,1,1);
}
Widget::~Widget()
{
delete ui;
}
9.2 滚动区域QScrollArea
卷动区域用于在框架内显示子级 Widget 的内容。若 Widget 超过框架大小,视图可以提供滚动条,以便可以查看子级小部件的整个区域。指定子级 Widget 必须采用 setWidget ()。
main.cpp
#include "widget.h"
#include <QApplication>
#include<QScrollArea>
#include<QLabel>
#include<QGridLayout>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.resize(300,200);
QLabel *lb=new QLabel;
lb->setScaledContents(true);
QImage imge("E:/blog/source/img/wallhaven-3k2y79.jpg");
lb->setPixmap(QPixmap::fromImage(imge));
QScrollArea *sa=new QScrollArea;
//居中
sa->setAlignment(Qt::AlignCenter);
sa->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
sa->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
sa->setWidget(lb);
QGridLayout *gl=new QGridLayout;
gl->addWidget(sa);
w.setLayout(gl);
w.show();
return a.exec();
}
下方按钮可以让图片进行滑动。
void setScaledContents(bool):
此属性用于确定标签是否缩放其内容以填充所有可用空间。
当启用并且标签显示像素图时,它将缩放像素图以填充可用空间。
此属性的默认值为false。
void setPixmap(const QPixmap &):
这个属性保存标签的像素图
如果没有设置像素图,将返回nullptr。
设置像素图清除之前的任何内容。好友快捷方式(如果有)被禁用。
QPixmap QPixmap::fromImage(const QImage &image(图片), Qt::ImageConversionFlags flags = Qt::AutoColor):
使用指定的标志来控制转换,将给定的图像转换为像素图。flags参数是Qt::ImageConversionFlags的位或。为标志传递0将设置所有默认选项。
在单色和8位图像的情况下,图像首先转换为32位像素图,然后用颜色表中的颜色填充。如果这个操作太昂贵,你可以使用QBitmap::fromImage()代替。
enum Qt::ScrollBarPolicy
9.3 标签小部件QTabWidget
选项卡小部件提供选项卡栏 (见 QTabBar ) 和页面区域用于显示每选项卡相关页面。默认情况下,选项卡栏展示在页面区域上方,但有不同可用配置 (见 TabPosition )。每选项卡关联不同 Widget (称为页面)。页面区域仅展示当前页面。所有其它页面被隐藏。用户可以展示不同页面通过点击其选项卡或按下其 Alt+ letter 快捷键若有的话。
通常,使用 QTabWidget 的方式是履行以下:
- 创建 QTabWidget。
- 创建 QWidget 对于每选项卡对话框页面,但不要为它们指定父级小部件。
- 将子级 Widget 插入页面小部件,使用布局正常安放它们。
- 调用 addTab () 或 insertTab () 将页面 Widget 放入选项卡小部件,为每选项卡赋予适合标签采用可选键盘快捷键。
选项卡位置的定义通过 tabPosition ,它们的形状通过 tabShape .
信号 currentChanged () 被发射当用户选择页面时。
当前页面索引可用作 currentIndex (),当前页面 Widget 采用 currentWidget ()。可以检索具有给定索引的页面小部件指针使用 widget (),和可以查找小部件的位置索引采用 indexOf ()。使用 setCurrentWidget () 或 setCurrentIndex () 以展示特定页面。
可以更改选项卡的文本和图标使用 setTabText () 或 setTabIcon ()。可以移除选项卡及其关联页面采用 removeTab ().
可以随时启用或禁用每选项卡 (见 setTabEnabled ())。若选项卡被启用,将正常绘制选项卡文本且用户可以选择该选项卡。若被禁用,将以不同方式绘制选项卡且用户无法选择该选项卡。注意,即使选项卡被禁用,页面仍可见 (例如:若所有选项卡被禁用)。
选项卡小部件可以是拆分复杂对话框的很好方式。另一方式是使用 QStackedWidget 提供在页面之间导航的一些手段,例如 QToolBar 或 QListWidget .
大多数 QTabWidget 功能的提供通过 QTabBar (在顶部,提供选项卡) 和 QStackedWidget (大部分区域,组织各个页面)。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QTabWidget>
#include<QPushButton>
#include<QLabel>
#include<QGridLayout>
#include<QLineEdit>
#include<QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
QTabWidget *tw;
private slots:
void msgcommit();
};
#endif // WIDGET_H
widget.cpp
首先创建QTabWidget对象。
tw=new QTabWidget(this);
tw->setGeometry(20,20,560,360);
tw->show();
void QWidget::show():
显示小部件及其子小部件。
这相当于调用showFullScreen()、showMaximized()或setVisible(true),具体取决于平台对窗口标志的默认行为。
进行标签小部件测试。
bool twui1=true;
bool twui2=true;
if(twui1)
{
QWidget *wg1=new QWidget();
tw->addTab(wg1,"进程");
QGridLayout *gl=new QGridLayout();
QLabel *lb=new QLabel("请选择文件或文件夹");
QLineEdit *le=new QLineEdit();
QPushButton *pb=new QPushButton("消息框");
connect(pb,SIGNAL(clicked(bool)),this,SLOT(msgcommit()));
gl->addWidget(lb,0,0);
gl->addWidget(le,0,1);
gl->addWidget(pb,0,2);
wg1->setLayout(gl);
}
if(twui2)
{
QWidget *wg2=new QWidget();
tw->addTab(wg2,"性能");
}
void Widget::msgcommit()
{
QMessageBox::information(NULL,"test","QMessageBox测试成功",QMessageBox::Ok);
}
以上代码逻辑很简单,就是先安排好内层部件,最后再安排外层部件。
clicked(bool):
表示按钮被点击时发出的信号,带有一个bool类型的参数,表示按钮是否被按下。如果按钮被按下,则参数为true;如果按钮被释放,则参数为false。
int QMessageBox::information(QWidget *parent, const QString &title, const QString &text, int button0, int button1 = 0, int button2 = 0):
这个功能已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
打开具有给定标题和文本的信息消息框。对话框最多可以有三个按钮。每个按钮,button0, button1和button2可以设置为以下值之一:
QMessageBox::NoButton
QMessageBox::Ok
QMessageBox::Cancel
QMessageBox::Yes
QMessageBox::No
QMessageBox::Abort
QMessageBox::Retry
QMessageBox::Ignore
QMessageBox::YesAll
QMessageBox::NoAll
如果您不需要所有三个按钮,请将最后一个按钮或最后两个按钮设置QMessageBox::NoButton。
一个按钮可以用QMessageBox::Default进行OR-ed,另一个按钮可以用QMessageBox::Escape进行OR-ed。返回被点击按钮的标识(QMessageBox::Ok,或QMessageBox::No,等等)。
消息框是一个应用程序模态对话框。
警告:不要在对话框执行期间删除父级。如果您想这样做,您应该使用QMessageBox构造函数之一自己创建对话框。
完整代码
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setGeometry(300,200,600,400);
tw=new QTabWidget(this);
tw->setGeometry(20,20,560,360);
tw->show();
bool twui1=true;
bool twui2=true;
if(twui1)
{
QWidget *wg1=new QWidget();
tw->addTab(wg1,"进程");
QGridLayout *gl=new QGridLayout();
QLabel *lb=new QLabel("请选择文件或文件夹");
QLineEdit *le=new QLineEdit();
QPushButton *pb=new QPushButton("消息框");
connect(pb,SIGNAL(clicked(bool)),this,SLOT(msgcommit()));
gl->addWidget(lb,0,0);
gl->addWidget(le,0,1);
gl->addWidget(pb,0,2);
wg1->setLayout(gl);
}
if(twui2)
{
QWidget *wg2=new QWidget();
tw->addTab(wg2,"性能");
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::msgcommit()
{
QMessageBox::information(NULL,"test","QMessageBox测试成功",QMessageBox::Ok);
}
9.4 停靠窗口部件QDockWidget
QDockWidget 提供了停靠小部件的概念,也称为工具选项板或实用程序窗口。Dock 窗口是放置在 QMainWindow 中中央 widget 周围的 dock widget 区域中的辅助窗口。
停靠窗口可以在其当前区域内移动,移动到新区域并由最终用户浮动(例如,取消停靠)。QDockWidget API 允许程序员限制 Dock Widget 移动、浮动和关闭的能力,以及它们可以放置的区域。
这次我们创建QMainWindow工程。而且只在mainwindow.cpp文件里写代码。
我们创建一个QDockWidget对象,并且设置颜色。
QDockWidget *dw=new QDockWidget("停靠窗口部件测试",this);
//设置颜色
QPalette p;
p.setColor(QPalette::Background,Qt::cyan);
dw->setAutoFillBackground(true);
dw->setPalette(p);
void setAutoFillBackground(bool enabled(启动)):
此属性保留小部件背景是否自动填充
如果启用,此属性将导致Qt在调用paint事件之前填充小部件的背景。使用的颜色由小部件调色板中的QPalette::Window颜色角色定义。
此外,Windows总是被QPalette::Window填充,除非设置了WA_OpaquePaintEvent或WA_NoSystemBackground属性。
如果小部件的父类具有静态渐变背景,则此属性不能关闭(即设置为false)。
警告:与Qt样式表一起谨慎使用此属性。当小部件具有具有有效背景或边框图像的样式表时,此属性将自动禁用。
默认情况下,此属性为false。
接下来实现一些学历层次信息。
// 学历层次
QLabel *lab=new QLabel("学历层次:");
QComboBox *cbx=new QComboBox();
cbx->addItem("小学");
cbx->addItem("初中");
cbx->addItem("高中");
cbx->addItem("专科");
cbx->addItem("本科");
cbx->addItem("硕士研究生");
cbx->addItem("博士研究生");
QPushButton *pbt1=new QPushButton("清华大学");
QPushButton *pbt2=new QPushButton("北京大学");
// 通过栅格布局(网格布局)
QGridLayout *glayout=new QGridLayout();
glayout->addWidget(lab,0,0,1,1);
glayout->addWidget(cbx,0,1,1,1);
glayout->addWidget(pbt1,1,0,1,1);
glayout->addWidget(pbt2,1,1,1,1);
glayout->setHorizontalSpacing(10);
glayout->setVerticalSpacing(10);
glayout->setContentsMargins(20,20,20,20);
QWidget *wgt=new QWidget();
wgt->setLayout(glayout);
dw->setWidget(wgt);
dw->setMaximumSize(300,300);
我们可以拖动窗口进行位置停靠。
void QWidget::setMaximumSize(int maxw, int maxh):
这个函数对应于setMaximumSize(QSize(maxw, maxh))。将最大宽度设置为maxw,最大高度设置为maxh。
完整代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDockWidget>
#include<QLabel>
#include<QComboBox>
#include<QPushButton>
#include<QGridLayout>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setGeometry(200,200,500,400);
QDockWidget *dw=new QDockWidget("停靠窗口部件测试",this);
//设置颜色
QPalette p;
p.setColor(QPalette::Background,Qt::cyan);
dw->setAutoFillBackground(true);
dw->setPalette(p);
// 学历层次
QLabel *lab=new QLabel("学历层次:");
QComboBox *cbx=new QComboBox();
cbx->addItem("小学");
cbx->addItem("初中");
cbx->addItem("高中");
cbx->addItem("专科");
cbx->addItem("本科");
cbx->addItem("硕士研究生");
cbx->addItem("博士研究生");
QPushButton *pbt1=new QPushButton("清华大学");
QPushButton *pbt2=new QPushButton("北京大学");
// 通过栅格布局(网格布局)
QGridLayout *glayout=new QGridLayout();
glayout->addWidget(lab,0,0,1,1);
glayout->addWidget(cbx,0,1,1,1);
glayout->addWidget(pbt1,1,0,1,1);
glayout->addWidget(pbt2,1,1,1,1);
glayout->setHorizontalSpacing(10);
glayout->setVerticalSpacing(10);
glayout->setContentsMargins(20,20,20,20);
QWidget *wgt=new QWidget();
wgt->setLayout(glayout);
dw->setWidget(wgt);
dw->setMaximumSize(300,300);
}
MainWindow::~MainWindow()
{
delete ui;
}