QPushButton是一个可点击的按钮,是用户界面中最为常见和常用的控件之一

通常用于响应用户的点击,然后执行相应操作。


1. 效果演示

演示按钮的文本和图标设置,样式表的设置,并实现了一个移动标签的功能。

img


2. 属性和方法

QPushButton有很多属性,完整的可查看帮助文档,这里列出常用的属性和方法。


2.1 文本

可以获取和设置按钮上显示的文本

1
2
3
// 获取和设置按钮的文本
QString text() const
void setText(const QString &text)

2.2 图标

可以获取和设置按钮上显示的图标

1
2
3
// 获取和设置按钮的图标
QIcon icon() const
void setIcon(const QIcon &icon)

2.3 自动重复

用于设置按钮是否启用自动重复功能的。

当启用该功能后,如果用户长时间按住按钮不放,按钮会定期发出点击事件(pressed、released和clicked信号),模拟“连发”效果。

1
2
void setAutoRepeat(bool);
bool autoRepeat() const;

2.4 设置快捷键

为按钮设置快捷键。

通过这个功能,用户可以通过键盘上的快捷键来触发按钮的点击事件,从而提高操作效率

1
2
void setShortcut(const QKeySequence &key);
QKeySequence shortcut() const;

2.5 样式表

样式表可以设置包括文本颜色、背景色、边框、字体等很多样式

1
2
3
4
5
// 获取和设置样式表
// 这是继承自QWidget类的属性和方法
// 只要继承自QWidget类的控件,都有该属性
QString styleSheet() const
void setStyleSheet(const QString &styleSheet)

2.6 信号

按钮在按下和抬起的过程中,会发射多个信号。

1
2
3
4
5
6
7
8
9
10
// 当按钮被点击(按下并抬起)时,发送该信号,其中带有一个默认参数
// 对于QPushButton 通常不需要传递这个默认参数
// 对于可选中/取消选中的按钮,比如复选框QCheckBox、单选框QRadioButton 可以通过该参数,获取其是否选中
void clicked(bool checked = false);

// 当按钮被按下时,发送该信号
void pressed();

// 当按钮被抬起时,发送该信号
void released();

3. 从零实现

从零写代码实现整体效果,以演示标签的属性以及信号槽的用法


3.1 布局

在UI设计师界面,拖拽对应的控件,修改显示的文字、控件的名称,然后完成布局

  • 合理地使用了水平、垂直、栅格布局

  • 合理地使用弹簧

  • 合理地调整Layout的各种参数,来设置外边距、内边距

  • 合理地调整字体大小

  • 在设计阶段,设置标签的背景色

即可完成以下效果,多操作自然就熟练了(完成后的代码,会一并共享给大家的~)

布局完成效果如下:

image-20251229120942462


3.2 添加资源文件

把用到的图标,作为资源文件添加到项目中,如下:

image-20251229120952097


3.3 代码实现

3.3.1 文本、图标、使能

首先,在widget.cpp的构造中,设置按钮的文字和图标,如下:

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
Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);

this->setWindowTitle("明王讲QT | 第二章 常用控件 | 2.2 按钮QPushButton");

// 1. 文本、图标、使能
ui->btnOk->setText("确定");
ui->btnOk->setFont(QFont("黑体", 12));
ui->btnOk->setIcon(QIcon(":/res/ok.png"));
ui->btnOk->setIconSize(QSize(20, 20));

ui->btnCancel->setText("取消");
ui->btnCancel->setFont(QFont("黑体", 12));
ui->btnCancel->setIcon(QIcon(":/res/cancel.png"));
ui->btnCancel->setIconSize(QSize(20, 20));

ui->btnStart->setText("启动");
ui->btnStart->setFont(QFont("黑体", 12));
ui->btnStart->setIcon(QIcon(":/res/start.png"));
ui->btnStart->setIconSize(QSize(20, 20));

ui->btnStop->setText("停止");
ui->btnStop->setFont(QFont("黑体", 12));
ui->btnStop->setIcon(QIcon(":/res/stop.png"));
ui->btnStop->setIconSize(QSize(20, 20));

ui->btnStart->setEnabled(true);
ui->btnStop->setEnabled(false);
}

然后,实现启动和停止按钮的槽函数,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// widget.h
class Widget : public QWidget {
private slots:
// 1. 启动、停止
void on_btnStart_clicked();
void on_btnStop_clicked();
};

// widget.cpp
void Widget::on_btnStart_clicked()
{
ui->btnStart->setEnabled(false);
ui->btnStop->setEnabled(true);
}

void Widget::on_btnStop_clicked()
{
ui->btnStart->setEnabled(true);
ui->btnStop->setEnabled(false);
}

3.3.2 移动标签

首先,在widget.cpp的构造中,设置上下左右和复位按钮的样式表,并开启连发功能,设置快捷键,如下:

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
Widget::Widget(QWidget* parent) : QWidget(parent), ui(new Ui::Widget)
{
// ...

// 2. 移动标签
ui->btnUp->setText("");
ui->btnUp->setStyleSheet(R"(
QPushButton {
border-image: url(:/res/up_normal.png);
}

QPushButton:hover {
border-image: url(:/res/up_hover.png);
}

QPushButton:pressed {
border-image: url(:/res/up_pressed.png);
}
)");

ui->btnDown->setText("");
ui->btnDown->setStyleSheet(R"(
QPushButton {
border-image: url(:/res/down_normal.png);
}

QPushButton:hover {
border-image: url(:/res/down_hover.png);
}

QPushButton:pressed {
border-image: url(:/res/down_pressed.png);
}
)");

ui->btnLeft->setText("");
ui->btnLeft->setStyleSheet(R"(
QPushButton {
border-image: url(:/res/left_normal.png);
}

QPushButton:hover {
border-image: url(:/res/left_hover.png);
}

QPushButton:pressed {
border-image: url(:/res/left_pressed.png);
}
)");

ui->btnRight->setText("");
ui->btnRight->setStyleSheet(R"(
QPushButton {
border-image: url(:/res/right_normal.png);
}

QPushButton:hover {
border-image: url(:/res/right_hover.png);
}

QPushButton:pressed {
border-image: url(:/res/right_pressed.png);
}
)");

ui->btnReset->setText("");
ui->btnReset->setStyleSheet(R"(
QPushButton {
border-image: url(:/res/reset_normal.png);
}

QPushButton:hover {
border-image: url(:/res/reset_hover.png);
}

QPushButton:pressed {
border-image: url(:/res/reset_pressed.png);
}
)");

// 开启连发功能
ui->btnUp->setAutoRepeat(true);
ui->btnDown->setAutoRepeat(true);
ui->btnLeft->setAutoRepeat(true);
ui->btnRight->setAutoRepeat(true);

// 设置快捷键
ui->btnUp->setShortcut(QKeySequence(Qt::Key_Up));
ui->btnDown->setShortcut(QKeySequence(Qt::Key_Down));
ui->btnLeft->setShortcut(QKeySequence(Qt::Key_Left));
ui->btnRight->setShortcut(QKeySequence(Qt::Key_Right));
ui->btnReset->setShortcut(QKeySequence(Qt::Key_Home));
}

然后,实现上下左右和复位按钮的槽函数,如下:

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
// widget.h
class Widget : public QWidget {
private slots:
// 2. 移动标签
void on_btnReset_clicked();
void on_btnUp_clicked();
void on_btnDown_clicked();
void on_btnLeft_clicked();
void on_btnRight_clicked();
};

// widget.cpp
void Widget::on_btnReset_clicked()
{
// 获取父控件的大小
QWidget* widget = ui->lblMove->parentWidget();

QRect parentRect = widget->rect();
QRect lblRect = ui->lblMove->rect();

// 计算子控件应该位于父控件中心的位置
int x = parentRect.center().x() - lblRect.width() / 2;
int y = parentRect.center().y() - lblRect.height() / 2;

// 设置子控件的几何属性
ui->lblMove->move(x, y);
}

void Widget::on_btnUp_clicked()
{
ui->lblMove->move(ui->lblMove->x(), ui->lblMove->y() - 20);
if (ui->lblMove->y() <= -1 * ui->lblMove->height()) {
ui->lblMove->move(ui->lblMove->x(), ui->lblMove->parentWidget()->height());
}
}

void Widget::on_btnDown_clicked()
{
ui->lblMove->move(ui->lblMove->x(), ui->lblMove->y() + 20);
if (ui->lblMove->y() >= ui->lblMove->parentWidget()->height()) {
ui->lblMove->move(ui->lblMove->x(), -1 * ui->lblMove->height());
}
}

void Widget::on_btnLeft_clicked()
{
ui->lblMove->move(ui->lblMove->x() - 20, ui->lblMove->y());
if (ui->lblMove->x() <= -1 * ui->lblMove->width()) {
ui->lblMove->move(ui->lblMove->parentWidget()->width(), ui->lblMove->y());
}
}

void Widget::on_btnRight_clicked()
{
ui->lblMove->move(ui->lblMove->x() + 20, ui->lblMove->y());
if (ui->lblMove->x() >= ui->lblMove->parentWidget()->width()) {
ui->lblMove->move(-1 * ui->lblMove->width(), ui->lblMove->y());
}
}