Qt基础控件学习07 水平导航栏

模仿富途做一个水平导航栏。原理就是在QButtonGroup中加入QPushbutton,加上一定的动画和样式。

代码如下:

.h

#ifndef CHORIZONTALNAVBAR_H
#define CHORIZONTALNAVBAR_H

/*************************************/
/**功能:水平导航栏                    **/
/**作者:hao                         **/
/**日期:2020-04-27                  **/
/*************************************/

#include <QWidget>
#include <QButtonGroup>
#include <QPropertyAnimation>
#include <QPaintEvent>
#include <QPushButton>


class CHorizontalNavBar : public QWidget
{
    Q_OBJECT

public:
    explicit CHorizontalNavBar(QWidget *parent = nullptr);
    ~CHorizontalNavBar();

    void addButton(QPushButton* btn, int id);
    void addHorStretch();//在最后布局加一个弹簧
    
signals:
    void signal_currIndex(int);

protected:
    void paintEvent(QPaintEvent *e);
private slots:
    void onValueChanged(QVariant variant);
    void onButtonClicked(int index);

private: 
    void deleteLayout();

    int m_curIndex;
    int m_preIndex;
    int m_offset;
    int m_lineHeight;
    QColor m_lineColor;
    QSize m_btnSize;                  //按钮的尺寸

    QButtonGroup *m_btnGroup;
    QPropertyAnimation *m_animation;
    QList<QAbstractButton *> m_buttonList;  //按钮集合

};

#endif // CHORIZONTALNAVBAR_H

.cpp

#include "chorizontalnavbar.h"

#include <QLayoutItem>
#include <QVBoxLayout>
#include <QPainter>

CHorizontalNavBar::CHorizontalNavBar(QWidget *parent) :
    QWidget(parent)
  , m_curIndex(0)
  , m_preIndex(0)
  , m_offset(0)
  , m_lineHeight(1)
  , m_lineColor(QColor(	255,215,0))
  , m_btnSize(QSize(120,30))
{
    m_btnGroup = new QButtonGroup(this);
    connect(m_btnGroup, SIGNAL(buttonClicked(int)), SLOT(onButtonClicked(int)));

    m_animation = new QPropertyAnimation(this, "");
    m_animation->setDuration(200);
    connect(m_animation, SIGNAL(valueChanged(QVariant)), SLOT(onValueChanged(QVariant)));

    QHBoxLayout* layout = new QHBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, m_lineHeight);
    layout->setSpacing(0);
    setLayout(layout);

}

CHorizontalNavBar::~CHorizontalNavBar()
{

}

void CHorizontalNavBar::addButton(QPushButton *btn, int id)
{
    m_btnGroup->addButton(btn, id);
    m_buttonList.append(btn);
    layout()->addWidget(btn);
    m_btnSize = btn->size();

    QString style = QString("QPushButton{border:none;}"
                            "QPushButton:hover{color:rgb(%1, %2, %3);}"
                            "QPushButton:pressed, QPushButton:checked{color:rgba(%1, %2, %3, 150);}").arg(m_lineColor.red()).arg(m_lineColor.green()).arg(m_lineColor.blue());

    btn->setStyleSheet(style);
}

void CHorizontalNavBar::addHorStretch()
{
    static_cast<QHBoxLayout*>(layout())->addStretch();
}

void CHorizontalNavBar::paintEvent(QPaintEvent *e)
{
    QWidget::paintEvent(e);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing);

    painter.save();
    QPen pen;
    pen.setColor(QColor(169,169,169));
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawLine(0,height()-1,width(),height()-1);
    painter.restore();

    painter.save();
    painter.setPen(Qt::NoPen);
    painter.setBrush(m_lineColor);
    //画下边的线
    painter.drawRect(m_offset, this->height() - m_lineHeight, m_btnSize.width(), m_lineHeight);
    painter.restore();
}

void CHorizontalNavBar::onValueChanged(QVariant variant)
{
    m_offset = variant.toInt();
    update();
}

void CHorizontalNavBar::onButtonClicked(int index)
{
    m_btnGroup->button(index)->setChecked(true);
    m_preIndex = m_curIndex;
    m_curIndex = index;

    m_animation->setStartValue(m_preIndex * m_btnSize.width());
    m_animation->setEndValue(index * m_btnSize.width());

    m_animation->start();
    emit signal_currIndex(m_curIndex);
}

void CHorizontalNavBar::deleteLayout()
{
    //清除布局,包括布局内控件
    if (this->layout() != nullptr)
    {
        QLayoutItem *child;
        while ((child = this->layout()->takeAt(0)) != 0) {
            delete child->widget();
            delete child;
            child = nullptr;
        }
        m_buttonList.clear();
        delete this->layout();
        this->setLayout(nullptr);
    }
}

 

调用地方:

for (int index = 0; index < 5; ++index)
    {
        QPushButton *btn = new QPushButton;
        btn->setCheckable(true);
        QString keyStr = QString("界面_%1").arg(index);
        btn->setText(keyStr);
        btn->setFixedWidth(120);
        ui->widget_nav->addButton(btn, index);
    }
    ui->widget_nav->addHorStretch();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值