Qt:常用控件

目录

控件概述

控件体系的发展

按钮类控件

QPushButton

QRadioButton

QCheckBox

QToolButton

显示类控件

QLabel

QLCDNumber

QProgressBar

QCalendarWidget

输入类控件

QLineEdit

QTextEdit

QComboBox

QSpinBox

QDateEdit & QTimeEdit

QDial

QSlider

多元素控件

QListWidget

QTableWidget

QTreeWidget

容器类控件

QGroupBox

QTabWidget

布局管理器

QVBoxLayout

QHBoxLayout

QGridLayout

QFormLayout

间隔类控件


控件概述

Widget是Qt中的核心概念,英文原义是"小部件",此处将其翻译为"控件"。控件是构成一个图形化界面的基本要素,如按钮、列表视图、树形视图、单行输入框、多行输入框、滚动条、下拉框等都可以称为"控件"。

Qt作为一个成熟的GUI开发框架,内置了大量的常用控件。Qt也提供了"自定义控件"的能力,可以在现有控件不能满足需求时,对现有控件做出扩展,或者自定义出新的控件。


控件体系的发展

控件是 GUI 开发中的通用概念,不仅仅局限在 Qt 中。

第一阶段:

完全没有控件,此时需要通过⼀些绘图 API 手动的绘制出按钮或者输入框等内容,代码编写繁琐,例如文曲星的 Lava 平台开发。

第二阶段:

  • 只包含粗略的控件,只是提供了按钮,输⼊框,单选框,复选框等最常用的控件.
  • 例如 html 的原生控件

第三阶段:

  • 更完整的控件体系,基本可以覆盖到 GUI 开发中的⼤部分场景
  • 例如早期的 MFC,VB,C++ Builder,Qt,Delphi,后来的 Android SDK,Java FX,前端的各种 UI 库等

按钮类控件

QPushButton

Qt中使用QPushButton表示一个按钮。QPushButton继承自QAbstractButton,该类是一个抽象类,是其他按钮的父类。

在Qt Designer中也能够看到这里的继承关系

QAbstractButton中和QPushButton相关性较大的属性

属性 说明
text 按钮中的文本
icon 按钮中的图标
iconSize 按钮中图标的尺寸
shortCut 按钮对应的快捷键
autoRepeat

按钮是否会重复触发,当鼠标左键按住不放时

若设为true,则会持续产生鼠标点击事件

若设为false,则必须释放鼠标后,再次点击鼠标才能产生点击事件

(类似于游戏手柄上的"连发效果")

autoRepeatDelay 重复触发的延时时间(按住按钮多久,开始重复触发)
autoRepeatInterval 重复触发的周期

注意:

  • QAbstractButton作为QWidget的子类,继承了QWidget的属性。QWidget里的各种属性用法,对于QAbstractButton同样适用,因此表格仅列出QAbstractButton独有的属性
  • Qt的api设计风格非常清晰,此处列出的属性都是可以获取和设置的。如:使用text()获取按钮文本,使用setText()设置文本

事实上,QPushButton的核心功能都是QAbstractButton提供的,自身提供的属性都较为简单,其中default和autoDefault影响的是按下enter时自动点击哪个按钮的行为,flat把按钮设置为扁平的样式。暂时不做过多关注。

代码示例:带有图标的按钮

创建resource.qrc文件并导入图片

在界面上创建一个按钮

修改widget.cpp

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //创建图标
    QIcon icon(":/001.png");
    //设置图标    
    ui->pushButton->setIcon(icon);
    //设置图标大小
    ui->pushButton->setIconSize(QSize(66, 66));
}
 
Widget::~Widget()
{
    delete ui;
}

运行代码

代码示例:带有快捷键的按钮

在界面中拖五个按钮。五个按钮的objectName分别为pushButtonTarget 、pushButtonUp、pushButtonDown、pushButtonLeft、pushButtonRight,五个按钮的初始位置随意,其中pushButtonTarget尺寸设为100*100,其余按钮设为50*50,文本内容均清空。

创建resource.qrc并导入5个图片

修改widget.cpp,设置图标资源和快捷键,设置四个方向键的slot函数

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    //设置图标
    ui->pushButtonTarget->setIcon(QIcon(":/image/dog.png"));
    ui->pushButtonUp->setIcon(QIcon(":/image/Up.png"));
    ui->pushButtonDown->setIcon(QIcon(":/image/Down.png"));
    ui->pushButtonLeft->setIcon(QIcon(":/image/Left.png"));
    ui->pushButtonRight->setIcon(QIcon(":/image/Right.png"));
    //设置快捷键1
    ui->pushButtonUp->setShortcut(QKeySequence(Qt::Key_W));
    ui->pushButtonDown->setShortcut(QKeySequence(Qt::Key_S));
    ui->pushButtonLeft->setShortcut(QKeySequence(Qt::Key_A));
    ui->pushButtonRight->setShortcut(QKeySequence(Qt::Key_D));
    //设置快捷键2
//    ui->pushButtonUp->setShortcut(QKeySequence("W"));
//    ui->pushButtonDown->setShortcut(QKeySequence("S"));
//    ui->pushButtonLeft->setShortcut(QKeySequence("A"));
//    ui->pushButtonRight->setShortcut(QKeySequence("D"));
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_pushButtonUp_clicked()
{
    const QRect& rect = ui->pushButtonTarget->geometry();
    ui->pushButtonTarget->setGeometry(rect.x(), rect.y() - 5, rect.height(), rect.width());
}
void Widget::on_pushButtonDown_clicked()
{
    const QRect& rect = ui->pushButtonTarget->geometry();
    ui->pushButtonTarget->setGeometry(rect.x(), rect.y() + 5, rect.height(), rect.width());
}
void Widget::on_pushButtonLeft_clicked()
{
    const QRect& rect = ui->pushButtonTarget->geometry();
    ui->pushButtonTarget->setGeometry(rect.x() - 5, rect.y(), rect.height(), rect.width());
}
void Widget::on_pushButtonRight_clicked()
{
    const QRect& rect = ui->pushButtonTarget->geometry();
    ui->pushButtonTarget->setGeometry(rect.x() + 5, rect.y(), rect.height(), rect.width());
}

运行程序,此时点击按钮,或者使用wasd均可让狗头移动

代码示例:按钮的重复触发

在上述案例中,按住快捷键是可以重复触发的,但是鼠标点击则不能

修改widget.cpp,在构造函数中开启重复触发

//开启鼠标重复触发
ui->pushButtonUp->setAutoRepeat(true);
ui->pushButtonDown->setAutoRepeat(true);
ui->pushButtonLeft->setAutoRepeat(true);
ui->pushButtonRight->setAutoRepeat(true);

QRadioButton

QRadioButton是单选按钮,可以在多个选项中选择一个。作为QAbstractButton和QWidget的子类,上面介绍的属性和用法对于QRadioButton同样适用

QAbstractButton中和QRadioButton关系较大的属性

属性 说明
checkable 是否能被选中
checked 是否已经被选中,checkable时checked的前提条件
autoExclusive

是否排它

选中一个按钮之后是否会取消其他按钮的选中

对于QRadioButton而言,默认就是排它的

代码示例:选择性别

在界面上创建一个label和三个单选按钮。设置的文本如下图,三个单选按钮的objectName分别为radioButtonMale 、radioButtonFemale、radioButtonOther

修改widget.cpp,编辑三个QRadioButton的slot函数

void Widget::on_radioButtonMale_clicked()
{
    ui->label->setText("你选择的性别为:男");
}
 
void Widget::on_radioButtonFemale_clicked()
{
    ui->label->setText("你选择的性别为:女");
}
 
void Widget::on_radioButtonOther_clicked()
{
    ui->label->setText("你选择的性别为:其他");
}

修改代码,让程序启动默认选中性别男

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置默认选中该按钮
    ui->radioButtonMale->setChecked(true);
    ui->label->setText("你选择的性别为:男");
}

禁用"其他"选项

// 禁用other选项
ui->radioButtonOther->setCheckable(false);

点击"其他"按钮时,虽然不会被选中,但是可以触发点击事件,使label显示性别为其他

使用setEnabled可以更彻底的禁用按钮,此时该按钮无法被选中,也无法响应任何输入

// 禁用other选项
ui->radioButtonOther->setEnabled(false);

代码示例:clicked、pressed、released、toggled区别

  • clicked表示一次"点击"(一次按下 + 一次释放)
  • pressed表示鼠标"按下"
  • released表示鼠标"释放"
  • toggled表示按钮状态切换

在界面上创建四个单选按钮,objectName分别为radioButton、radioButton_2、radioButton_3、radioButton_4

给1创建clicked槽函数,给2创建pressed槽函数,给3创建released槽函数,给4创建toggled槽函数

void Widget::on_radioButton_clicked()
{
    qDebug() << "clicked";
}
 
void Widget::on_radioButton_2_pressed()
{
    qDebug() << "pressed";
}
 
void Widget::on_radioButton_3_released()
{
    qDebug() << "released";
}
 
void Widget::on_radioButton_4_toggled(bool checked)
{
    if(checked) qDebug() << "toggled true";
    else qDebug() << "toggled false";
}

代码示例:单选按钮分组

在界面上创建6个单选框,用来模拟麦当劳点餐界面。objectName分别为radioButton到radioButton_6

此时直接运行程序,可以发现这六个QRadioButton之间都是排它的。但是按照正常的逻辑,应该每⼀组内部来控制排它,但是组和组之间不能排它。

引入QButtonGroup进行分组

#include "widget.h"
#include "ui_widget.h"
#include <QButtonGroup>
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    //创建三个QButtonGroup
    QButtonGroup* group1 = new QButtonGroup(this);
    QButtonGroup* group2 = new QButtonGroup(this);
    QButtonGroup* group3 = new QButtonGroup(this);
    //将QRadioButton两两一组放入QButtonGroup中
    group1->addButton(ui->radioButton);
    group1->addButton(ui->radioButton_2);
 
    group2->addButton(ui->radioButton_3);
    group2->addButton(ui->radioButton_4);
 
    group3->addButton(ui->radioButton_5);
    group3->addButton(ui->radioButton_6);
}
 
Widget::~Widget()
{
    delete ui;
}

再次执行程序,就可以按照正确的分组方式来进行排它了

QCheckBox

QCheckBox表示复选按钮,可以允许选中多个。和QCheckBox最相关的属性是checkable和checked,都是继承自QAbstractButton

至于QCheckBox独有的属性tristate用来实现"三态复选框",不过较为冷门,暂时不做讨论

代码示例:获取复选按钮的取值

在界面上创建三个复选按钮和一个普通按钮,objectName分别为checkBoxEat、checkBoxSleep、checkBoxPlay以及pushButton

给pushButton添加slot函数

void Widget::on_pushButton_clicked()
{
    QString result;
    if(ui->checkBoxEat->isChecked())
        result += ui->checkBoxEat->text();
    if(ui->checkBoxSleep->isChecked())
        result += ui->checkBoxSleep->text();
    if(ui->checkBoxPlay->isChecked())
        result += ui->checkBoxPlay->text();
    qDebug() << "选中的内容:" << result;
}

QToolButton

QToolButton大部分功能和QPushButton一致,但是QToolButton主要应用在工具栏、菜单等场景。


显示类控件

QLabel

QLabel可以用来显示文本和图片

核心属性

属性 说明
text QLabel中的文本
textFormat

文本的格式

Qt::PlainText 纯文本

Qt::Rich Text 富文本(支持html标签)

Qt::MarkdownText markdown格式

Qt::AutoText 根据文本内容自动决定文本格式

pixmap QLabel内部包含的图片
scaledContents

设为true表示内容自动拉伸填充QLabel

设为false则不会自动拉伸

alignment 对齐方式(可以设置水平方向和垂直方向如何对齐)
wordWrap

设为true内部文本会自动换行

设为false则内部文本不会自动换行

indent 设置文本缩进(水平方向和垂直方向都生效)
margin 内部文本与边框之间的边距
openExternalLinks

是否允许打开一个外部链接

(当QLabel的文本中包含url时涉及)

buddy

给QLabel关联一个"伙伴",按下QLabel指示的快捷键时就能激活对应的伙伴

若伙伴是一个QCheckBox,那么该QCheckBox就会被选中

代码示例:显示不同格式的文本

在界面上创建三个QLabel,objectName分别为label、label_2、label_3

修改widget.cpp,设置三个label的属性

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setTextFormat(Qt::PlainText);
    ui->label->setText("这是一段纯文本");
    ui->label_2->setTextFormat(Qt::RichText);
    ui->label_2->setText("<b> 这是一段富文本 </b>");
    ui->label_3->setTextFormat(Qt::MarkdownText);
    ui->label_3->setText("## 这是一段MarkDown文本");
}
 
Widget::~Widget()
{
    delete ui;
}
 

运行程序,观察效果

代码示例:显示图片

虽然QPushButton也可以通过设置图标的方式设置图片,但是并非是一个好的选择,更多的时候还是希望通过QLabel来作为一个更单纯的显示图片的方式

在界面上创建一个QLabel,objectName为label

创建resource.qrc文件并把图片导入到qrc中

修改widget.cpp,给QLabel设置图片

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置label大小与窗口大小相同
    ui->label->setGeometry(0, 0, 800, 600);
    //设置label图片
    QPixmap pixmap(":/huaji.png");
    ui->label->setPixmap(pixmap);
    //设置label内容拉伸
    ui->label->setScaledContents(true);
}
 
Widget::~Widget()
{
    delete ui;
}

运行程序,观察效果,可以看到图片已经被拉伸,可以把窗口填满了。但是若拖动窗口大小,可以看到图片并不会随着窗口大小的改变而同步变化

为了解决该问题,可以在Widget中重写resizeEvent函数

void Widget::resizeEvent(QResizeEvent *event)
{
    ui->label->setGeometry(0, 0, event->size().width(), event->size().height());
    qDebug() << event->size();
}

注意:

  • 此处的resizeEvent函数没有手动调用,但是能在窗口大小变化时被自动调用。这个过程就是依赖C++中的多态来实现的,Qt框架内部管理着QWidget对象表示窗口,在窗口大小发生改变时,Qt就会自动调用resizeEvent函数
  • 但是实际上这个窗口的并非是QWidget,而是QWidget的子类,也就是自主编写的Widget。此时虽然是通过父类调用函数,但是实际上执行的是子类的函数(即重写后的resizeEvent )
  • 此处属于是多态机制的一种经典用法。通过上述过程,就可以把自定义的代码插入到框架内部执行,相当于"注册回调函数"

代码示例:文本对齐、自动换行、缩进、边距

创建四个label,objectName分别是label到label_4,并且在QFrame中设置frameShape为Box(设置边框后看起来会更清晰一些)

QFrame是QLabel的父类,其中frameShape属性用来设置边框性质

  • QFrame::Box:矩形边框
  • QFrame::Panel:带有可点击区域的面板边框
  • QFrame::WinPanel:Windows风格的边框
  • QFrame::HLine:水平线边框
  • QFrame::VLine:垂直线边框
  • QFrame::StyledPanel:带有可点击区域的面板边框,但样式取决于窗口主题

编写widget.cpp,给这四个label设置属性

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
 
    //设置文字居中对齐
    ui->label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    ui->label->setText("垂直水平居中的文本");
    //设置自动换行
    ui->label_2->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_2->setWordWrap(true);
    ui->label_2->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");
    //设置首行缩进
    ui->label_3->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_3->setIndent(20);
    ui->label_3->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");
    //设置边距
    ui->label_4->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    ui->label_4->setMargin(20);
    ui->label_4->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");
}
 
Widget::~Widget()
{
    delete ui;
}
 
  • 第一个label垂直水平居中
  • 第二个label设置了wordWrap,能够自动动换行
  • 第三个label设置了Indent,左侧和上方和边框有间距,右侧则没有
  • 第四个label设置了margin,四个方向均有间距(图上仅体现出三个方向,下方看不出来)

代码示例:设置伙伴

创建两个label和两个radioButton,objectName分别为label、label_2、radioButton、radioButton_2

注意:

  • 此处把label中的文本设置为"快捷键 &A"这样的形式,其中&后面跟着的字符就是快捷键,可以通过alt+A的方式来触发该快捷键
  • 但是这里的快捷键和QPushButton不同,需要搭配alt和单个字母的方式才能触发

编写widget.cpp,设置buddy属性

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setBuddy(ui->radioButton);
    ui->label_2->setBuddy(ui->radioButton_2);
}
 
Widget::~Widget()
{
    delete ui;
}

QLCDNumber

QLCDNumer是一个专门用来显示数字的控件,类似于"老式计算器"的效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值