自定义控件
自定义按钮
基于Qt提供的事件处理器函数,我们可以非常轻松地按照自己的想法制作出一个按钮,按钮的要求如下:
- 从视觉上看是一个不规则按钮(按钮实际上都是矩形的)
- 按钮上需要显示指定的背景图片
- 按钮在鼠标的不同操作阶段(无操作、鼠标悬停、鼠标按下)能够显示不同的背景图
按钮效果如下:
添加子类
新添加的按钮类可以让它继承 QPushButton,也可以让它继承其他的窗口类(代价是当鼠标点击事件触发之后需要自己发射自定义信号),这里让添加的子类从QWidget类派生。
自定义类头文件
cpp
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QWidget>
class MyButton : public QWidget
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
void setImage(QString normal, QString hover, QString pressed);
protected:
void mousePressEvent(QMouseEvent* ev);
void mouseReleaseEvent(QMouseEvent* ev);
void enterEvent(QEvent* ev);
void leaveEvent(QEvent* ev);
void paintEvent(QPaintEvent* ev);
signals:
void clicked();
private:
QPixmap m_normal;
QPixmap m_press;
QPixmap m_hover;
QPixmap m_current;
};
#endif // MYBUTTON_H
自定义类源文件
cpp
#include "mybutton.h"
#include <QPainter>
MyButton::MyButton(QWidget *parent) : QWidget(parent)
{
}
void MyButton::setImage(QString normal, QString hover, QString pressed)
{
// 加载图片
m_normal.load(normal);
m_hover.load(hover);
m_press.load(pressed);
m_current = m_normal;
// 设置按钮和图片大小一致
setFixedSize(m_normal.size());
}
void MyButton::mousePressEvent(QMouseEvent *ev)
{
// 鼠标被按下, 发射这个自定义信号
emit clicked();
m_current = m_press;
update();
}
void MyButton::mouseReleaseEvent(QMouseEvent *ev)
{
m_current = m_normal;
update();
}
void MyButton::enterEvent(QEvent *ev)
{
m_current = m_hover;
update();
}
void MyButton::leaveEvent(QEvent *ev)
{
m_current = m_normal;
update();
}
void MyButton::paintEvent(QPaintEvent *ev)
{
QPainter p(this);
p.drawPixmap(rect(), m_current);
}
使用自定控件
由于Qt的UI工具箱中提供的都是标准控件,自定义的控件是不能直接拖拽到UI窗口中的,这时我们需要先看一下自定义控件的基类类型:上面自定义的 MyButton 的基类是 QWidget 类型,因此需要往窗口中拖拽一个QWidget类型的标准控件,然后在这个标准控件上鼠标右键:
这样添加的控件类型就变成了自定义的子类类型:
设置图片
在主窗口中通过添加的按钮的对象,调用子类的成员函数给其添加图片:
mainwindow.cpp
cpp
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 给自定义按钮设置图片
ui->button->setImage(":/ghost-1.webp", ":/ghost-2.webp", ":/ghost-3.webp");
// 处理自定义按钮的鼠标点击事件
connect(ui->button, &MyButton::clicked, this, [=]()
{
QMessageBox::information(this, "按钮", "莫要调戏我...");
});
}
MainWindow::~MainWindow()
{
delete ui;
}