自定义按键组件:用于管理分类窗体

本文介绍了一种自定义的动画按键控件,该控件采用C++编写,基于QWidget,实现了顶端与左端布局,提供了丰富的自定义选项,如按键尺寸、布局模式、动画时间间隔等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自定义按键组件

自定义动画按键导航控件
参考网上大神绘制的自定义按键组件思路,自己重新整理一份代码,方便学习管理,源码全部开放,不喜勿喷!谢谢。
目前实现顶端与左端布局,当作控件使用,布局即可。
#ifndef BUTTONGROUP_H
#define BUTTONGROUP_H

//
// 按键组件:用于管理分类窗体
//

#include <QWidget>
#include <QBoxLayout>
#include <QPaintEvent>

class QBoxLayout;
class QPushButton;
class QButtonGroup;
class QAbstractButton;
class QPropertyAnimation;

class ButtonGroup : public QWidget {
        Q_OBJECT
    public:
        ButtonGroup(QWidget *parent = NULL);
        ~ButtonGroup();

        enum LinePosition {
            LinePosition_Left = 0,     //左边
            LinePosition_Right = 1,    //右边
            LinePosition_Top = 2,      //上边
            LinePosition_Bottom = 3    //下边
        };

        // 设置按键尺寸
        void setButtonSize(QSize buttonSize);

        // 设置布局模式
        void setLayoutMode(QBoxLayout::Direction mode);

        // 添加按键
        void addButtonItem(QAbstractButton *button, int id, bool isEnd = false);

        // 设置动画时间间隔
        void setInterval(int interval) {
            _interval = interval;
        }

        // 设置基准颜色
        void setBaseColor(const QColor &color) {
            _baseColor = color;
        }

        // 设置线颜色
        void setLineColor(const QColor &color) {
            _lineColor = color;
        }

        // 设置线条
        void setLineWeight(int lineWeight) {
            _lineWeight = lineWeight;
        }

        // 设置方向
        void setLinePosition(LinePosition linePosition) {
            _linePosition = linePosition;
        }

    protected:
        // 大小改变事件
        void resizeEvent(QResizeEvent *e);

        // 绘图事件
        void paintEvent(QPaintEvent *e);

    private slots:
        // 响应按键点击事件
        void _onButtonClicked(int id);

        // 响应动画参数值改变
        void _onValueChange(QVariant _currentIndex);

    private:
        // 初始化动画
        void _initAnimation();

    private:
        int _offset;                     // 偏移量
        int _lineWeight;                 // 线条的长度
        int _interval;                   // 线条移动的速度
        int _currentIndex;               // 当前索引
        LinePosition _linePosition;      // 线条方向

        QSize _btnSize;                  // 按钮的尺寸
        QColor _textColor;               // 文字颜色
        QColor _baseColor;               // 基准颜色
        QColor _lineColor;               // 线条的颜色
        QColor _hoverColor;              // 按钮经过颜色
        QBoxLayout::Direction _mode;     // 布局模式

        QBoxLayout *_layout;             // 布局
        QButtonGroup *_btnGroup;         // 按钮组
        QPropertyAnimation *_animation;  // 属性动画
};

#endif // BUTTONGROUP_H
#include <QPainter>
#include <QBoxLayout>
#include <QPushButton>
#include <QButtonGroup>
#include <QAbstractButton>
#include <QPropertyAnimation>

#include "ButtonGroup.h"

////////////////////////////////////////////////////////////////////////////////
// 构造函数
////////////////////////////////////////////////////////////////////////////////
ButtonGroup::ButtonGroup(QWidget *parent)
    : QWidget(parent)
    , _offset(4)
    , _lineWeight(4)
    , _interval(200)
    , _currentIndex(0)
    , _linePosition(LinePosition_Top)
    , _btnSize(QSize(80, 32))
    , _textColor(QColor(Qt::black))
    , _baseColor(QColor(Qt::white))
    , _lineColor(QColor(23,160,134))
    , _hoverColor(QColor(87,184,166).light(150))
    , _mode(QBoxLayout::RightToLeft)
    , _layout(new QBoxLayout(_mode))
    , _btnGroup(new QButtonGroup(this))
    , _animation(new QPropertyAnimation(this, ""))
{
    _initAnimation();
    connect(_btnGroup, SIGNAL(buttonClicked(int)),
            this, SLOT(_onButtonClicked(int)));
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
ButtonGroup::~ButtonGroup() {

}

////////////////////////////////////////////////////////////////////////////////
// 设置按键尺寸
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::setButtonSize(QSize buttonSize) {
    if (NULL == _btnGroup) {
        return;
    }

    foreach(QAbstractButton *button, _btnGroup->buttons()) {
        if (NULL == button) {
            continue;
        }
        button->setFixedSize(buttonSize);
    }

    _btnSize = buttonSize;
}

////////////////////////////////////////////////////////////////////////////////
// 设置布局模式
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::setLayoutMode(QBoxLayout::Direction mode) {
    if (NULL == _layout) {
        return;
    }

    _layout->setDirection(mode);
    _layout->setMargin(4);
    _layout->setSpacing(0);
}

////////////////////////////////////////////////////////////////////////////////
// 添加按键控件
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::addButtonItem(QAbstractButton *button, int id, bool isEnd) {
    if (NULL == button) {
        return;
    }

    QString back = QString("QPushButton{background-color:rgba(%1, %2, %3, 80);border:none;}")
            .arg(_baseColor.red()).arg(_baseColor.green()).arg(_baseColor.blue());
    QString hover = QString("QPushButton:hover{background-color:rgba(%1, %2, %3, 40);}")
            .arg(_hoverColor.red()).arg(_hoverColor.green()).arg(_hoverColor.blue());
    QString check = QString("QPushButton:pressed, QPushButton:checked{background-color:rgba(%1, %2, %3, 80);}")
            .arg(_lineColor.red()).arg(_lineColor.green()).arg(_lineColor.blue());

    QString style = QString("%1%2%3").arg(back).arg(hover).arg(check);
    button->setStyleSheet(style);

    _layout->addWidget(button);
    if (isEnd) {
        _layout->addStretch(0);
        setLayout(_layout);
    }

    _btnGroup->addButton(button, id);
}

////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::resizeEvent(QResizeEvent *e) {
    QWidget::resizeEvent(e);
}

////////////////////////////////////////////////////////////////////////////////
// 绘图
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::paintEvent(QPaintEvent *e) {
    QWidget::paintEvent(e);

    //根据不同的位置绘制线条区域,也可以改成绘制两点之间的距离
    int xPos = 0;
    int yPos = 0;
    int width = 0;
    int height = 0;

    switch (_linePosition) {
        case LinePosition_Top:
            xPos = _offset;
            yPos = 0;
            width = _btnSize.width();
            height = _lineWeight;
            break;
        case LinePosition_Bottom:
            xPos = _offset;
            yPos = this->height() - _lineWeight;
            width = _btnSize.width();
            height = _lineWeight;
            break;
        case LinePosition_Left:
            xPos = 0;
            yPos = _offset;
            width = _lineWeight;
            height = _btnSize.height();
            break;
        case LinePosition_Right:
            xPos = this->width() - _lineWeight;
            yPos = _offset;
            width = _lineWeight;
            height = _btnSize.height();
            break;
        default:
            break;
    }

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);

    //设置颜色
    painter.setPen(Qt::NoPen);
    painter.setBrush(_lineColor);
    painter.drawRect(xPos, yPos, width, height);
}

////////////////////////////////////////////////////////////////////////////////
// 响应按键事件
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::_onButtonClicked(int id) {
    if ((NULL == _btnGroup)
            || (NULL == _animation))
    {
        return;
    }

    _btnGroup->button(id)->setCheckable(true);
    _btnGroup->button(id)->setChecked(true);

    int offset = _currentIndex * _btnSize.width() + 4;
    int endOffset = id * _btnSize.width() + 4;

    if (_linePosition < LinePosition_Top) {
        offset = _currentIndex * _btnSize.height() + 4;
        endOffset = id * _btnSize.height() + 4;
    }

    _animation->setStartValue(offset);
    _animation->setEndValue(endOffset);
    _animation->start();

    _currentIndex = id;
}

////////////////////////////////////////////////////////////////////////////////
// 响应动画参数值改变
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::_onValueChange(QVariant index) {
    _offset = index.toInt();
    update();
}

////////////////////////////////////////////////////////////////////////////////
// 初始化动画
////////////////////////////////////////////////////////////////////////////////
void ButtonGroup::_initAnimation() {
    if (NULL == _animation) {
        return;
    }

    _animation->setDuration(_interval);
    connect(_animation, SIGNAL(valueChanged(QVariant)),
            this, SLOT(_onValueChange(QVariant)));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值