效果
实现
1.继承QWidget
#include <QWidget>
class ArrowButton : public QWidget
{
Q_OBJECT
public:
explicit ArrowButton( QString text,QWidget *parent = nullptr);
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void paintEvent(QPaintEvent *event);
void mousePressEvent(QMouseEvent *event);
signals:
void sig_clicked();
private:
bool m_bHover{false};
QString m_text;
};
2.构造
根据字体设置窗口尺寸最小值
ArrowButton::ArrowButton(QString text, QWidget *parent)
: QWidget{parent},m_text{text}
{
setAttribute(Qt::WA_TranslucentBackground);
QFontMetrics metrics = this->fontMetrics();
int w = metrics.horizontalAdvance(m_text);
this->setMinimumWidth(w+60);
this->setMinimumHeight(metrics.height()+metrics.leading()+5);
}
3.鼠标事件
void ArrowButton::enterEvent(QEvent *event)
{
if(event){
event->accept();
}
m_bHover = true;
update();
}
void ArrowButton::leaveEvent(QEvent *event)
{
if(event){
event->accept();
}
m_bHover = false;
update();
}
void ArrowButton::mousePressEvent(QMouseEvent *event)
{
if(event){
event->accept();
}
emit sig_clicked();//发送点击信号
}
4.绘制事件
void ArrowButton::paintEvent(QPaintEvent *event)
{
if(event){
event->accept();
}
QPainter painter(this);
painter.save();
painter.setRenderHint(QPainter::Antialiasing);
if(m_bHover){
painter.setPen(Qt::darkGray);
painter.setBrush(Qt::darkCyan);
}else{
painter.setPen(Qt::darkGreen);
painter.setBrush(Qt::white);
}
//绘制背景色
painter.drawRoundedRect(this->rect(),2.5,2.5);
painter.restore();
QFont font = painter.font();
font.setPointSize(10);
font.setBold(true);
if(m_bHover){
painter.setPen(Qt::white);
font.setBold(true);
}else{
painter.setPen(Qt::black);
}
painter.setFont(font);
QFontMetrics m = painter.fontMetrics();
if(m_bHover){
//文字居中
int w = m.horizontalAdvance(m_text);
painter.drawText((this->width()-w)/2,(this->height()-m.ascent()-m.descent())/2+m.ascent(),m_text);
}else{
//文字垂直居中
painter.drawText(15,(this->height()-m.ascent()-m.descent())/2+m.ascent(),m_text);
}
//绘制箭头
if(false == m_bHover){
painter.setRenderHints(QPainter::Antialiasing);
QPen pen = painter.pen();
pen.setColor(Qt::darkGray);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
pen.setWidthF(pen.widthF()+0.3f);
painter.setPen(pen);
painter.drawLine(this->width()-25,this->height()*0.3,this->width()-10,this->height()/2);
painter.drawLine(this->width()-10,this->height()/2,this->width()-25,this->height()-this->height()*0.3);
}
}
5.居中绘制文字说明
文字相关尺寸借用一张图
5.1如何获取QFontMetrics
QFontMetrics metrics = this->fontMetrics();
或者
QFontMetrics m = painter.fontMetrics();
5.2如何知道文字宽度
int w = m.horizontalAdvance(m_text); //qt5.11
或者
int width(const QString &, int len = -1) const;
5.3如何计算文字水平居中
(this->width()-w)/2
5.4如何计算文字垂直居中
(this->height()-m.ascent()-m.descent())/2+m.ascent()
6.使用
ArrowButton* pArrowButton = new ArrowButton("启动",this);
pArrowButton->setGeometry(10,10,150,35);
connect(pArrowButton,&ArrowButton::sig_clicked,this,[&]{QMessageBox::information(this,"tip","click");});