继承QPushButton自绘按钮

        QPushButton自绘按钮使用QPainter进行二维图形绘制,QPainter可以绘制各种图形,例如点、线、矩形、圆、椭圆等,QPainter也支持线性变换,例如平移、旋转缩放等,此外,QPainter也支持一些高级特性,例如反走样等等、像素混合、渐变填充等,在绘制前可以设置画笔、画刷、字体属性来控制绘制效果。

        QPainter的使用需要一个“绘图设备”,绘图设备包括但不限于QWidget、QPixmap、QImage等。在定制窗口部件时只需要重新实现paintEvent()函数可以让我们随心所欲的控制窗口的外观、下面介绍使用QPainter绘制图片、形状、文字的方法。

        按钮文字闪烁,按钮突出感强烈,点击、选中、悬浮等功能实现。

效果

 

主要涉及两个辅助类:

  • QFontMetrics
    用于获取文本字体的像素高度与宽度

  • QBasicTimer
    定时器,用于更新文本绘制。

原理:

  • 利用QBasicTimer进行定时刷新。

  • 文本绘制时,使用QColor来设置色调(H)、饱和度(S)、亮度(V),然后计算每一个字符的绘制坐标,进行单个绘制

BannerWidget.h

#ifndef PARA_BANNER_H
#define PARA_BANNER_H

#include <QWidget>
#include <QPushButton>
#include <QBasicTimer>

class BannerWidget : public QPushButton
{
    Q_OBJECT
public:
    explicit BannerWidget(QWidget  *parent = 0);

    ~BannerWidget();

    virtual void mousePressEvent(QMouseEvent *event) override;

    virtual void mouseReleaseEvent(QMouseEvent *event) override;


public slots:
    void setText(const QString &text);

protected:
    // 绘制文本
    void paintEvent(QPaintEvent *event);
    // 定时刷新
    void timerEvent(QTimerEvent *event);

    void enterEvent(QEvent *);

    void leaveEvent(QEvent *);


private:
    QBasicTimer m_timer;
    QString m_strText;
    int m_nStep;

    bool isHovered;
    bool isClicked;
};

#endif

BannerWidget.cpp

#include <QPainter>
#include <QTimerEvent>
#include <QFont>
#include <QLinearGradient>
#include "bannerwidget.h"

#pragma execution_character_set("UTF-8")//解决汉字乱码



BannerWidget::BannerWidget(QWidget  *parent)
    : QPushButton(parent),
      m_nStep(0),
      m_strText(QString::fromLocal8Bit("一去丶二三里")),
      isHovered(false),
      isClicked(false)
{
    setAutoFillBackground(true);

    // 设置文字大小
    QFont newFont = font();
    newFont.setPointSize(newFont.pointSize() + 8);
    setFont(newFont);

    setCheckable(true);

    m_timer.start(100, this);
}

BannerWidget::~BannerWidget()
{
    m_timer.stop();
}

void BannerWidget::mousePressEvent(QMouseEvent *event)
{
    isClicked = true;
    isHovered = false;


    if (isChecked()) {
        setChecked(false);
    }
    else {
        setChecked(true);
    }

    update();

    QWidget::mouseReleaseEvent(event);
}

void BannerWidget::mouseReleaseEvent(QMouseEvent *event)
{
    isClicked = false;
    isHovered = true;
    update();

    QWidget::mouseReleaseEvent(event);
}

void BannerWidget::setText(const QString &text)
{
    m_strText = text;
}

void BannerWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    // 计算文本绘制的起始坐标
    QFontMetrics metrics(font());
    int x = (width() - metrics.width(m_strText)) / 2;
    int y = (height() + metrics.ascent() - metrics.descent()) / 2;

    QColor textColor;
    QColor textColor2 = "#ECECB1";

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing,true);


    // 上
    QLinearGradient linearGradient(2, 1, this->width() - 2, 1);
    linearGradient.setColorAt(0.2, "#848485");
    linearGradient.setColorAt(1.0, "#FAFAFA");
    painter.setPen(QPen(QBrush(linearGradient),2));
    painter.drawLine(2, 1, this->width() - 2, 1);

    // 左
    QLinearGradient linearGradient2(0, 2, 0, this->height() - 3);
    linearGradient2.setColorAt(0.2, "#848485");
    linearGradient2.setColorAt(1.0, "#FAFAFA");
    painter.setPen(QPen(QBrush(linearGradient2),4));
    painter.drawLine(0, 2, 0, this->height() - 3);


    // 右
    QLinearGradient linearGradient3(this->width(), 2, this->width(), this->height() - 3);
    linearGradient3.setColorAt(0.2, "#FAFAFA");
    linearGradient3.setColorAt(1.0, "#848485");
    painter.setPen(QPen(QBrush(linearGradient3),4));
    painter.drawLine(this->width(), 2, this->width(), this->height() - 3);


    // 下
    QLinearGradient linearGradient4(2, this->height(),this->width() - 2, this->height());
    linearGradient4.setColorAt(0.01, "#FAFAFA");
    linearGradient4.setColorAt(0.02, "#000000");
    linearGradient4.setColorAt(0.98, "#000000");
    linearGradient4.setColorAt(1.0, "#848485");
    painter.setPen(QPen(QBrush(linearGradient4),4));
    painter.drawLine(2, this->height(), this->width() - 2, this->height());



    if(isClicked){
        QRect rect(2, 2, this->width() - 4, this->height() - 4);
        painter.setPen(Qt::NoPen);
        painter.setBrush(QColor("#000000"));
        painter.drawRect(rect);
    }

    // 指定要绘制的图片(将图片路径替换为有效的图片路径)
    if (isHovered) {
        QRect rect(2, 2, this->width() - 4, this->height() - 4);
        painter.drawPixmap(rect, QPixmap(":/img/backgroundPress.png"));
    }

    if(isChecked()){
        for (int i = 0; i < m_strText.size(); ++i)
        {
            // 设置色调(H)、饱和度(S)、亮度(V)
            int nIndex = (m_nStep + i) % 16;
            textColor.setHsv((15 - nIndex) * 16, 255, 191);
            painter.setPen(textColor);

            // 单个字符绘制
            painter.drawText(x, y, QString(m_strText[i]));

            // 计算下一个字符的x坐标起始点
            x += metrics.width(m_strText[i]);
        }
    }
    else {
        for (int i = 0; i < m_strText.size(); ++i)
        {
            painter.setPen(textColor2);

            // 单个字符绘制
            painter.drawText(x, y, QString(m_strText[i]));

            // 计算下一个字符的x坐标起始点
            x += metrics.width(m_strText[i]);
        }

    }
}


void BannerWidget::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);

    if (event->timerId() == m_timer.timerId())
    {
        ++m_nStep;
        update();
    }
    else
    {
        QPushButton::timerEvent(event);
    }
}


void BannerWidget::enterEvent(QEvent *)
{
    isHovered = true;
    update();
}

void BannerWidget::leaveEvent(QEvent *)
{
    isHovered = false;
    update();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值