QPushButton 是一个可点击的按钮,是用户界面中最为常见和常用的控件之一
通常用于响应用户的点击,然后执行相应操作。

1. 效果演示

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

img

2. 属性和方法

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

2.1 文本

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

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

2.2 图标

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

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

2.3 自动重复

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

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

2.4 设置快捷键

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

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

2.5 样式表

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

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

2.6 信号

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

// 当按钮被点击(按下并抬起)时,发送该信号,其中带有一个默认参数
// 对于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 的构造中,设置按钮的文字和图标,如下:

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);
}

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

// 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 的构造中,设置上下左右和复位按钮的样式表,并开启连发功能,设置快捷键,如下:

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));
}

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

// 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());
    }
}