Qt步骤条

引言

步骤条用于用户操作引导是必不可少的,能够为用户植入相关的操作步骤,避免大段的说明文档以及后期的相关培训,是一种成本较低效果较好的交互语言。

针对上述需求进行实现,实现效果如下图所示:

在这里插入图片描述

代码实现

最小的单元是StepIconLabel 控制item左侧的数字显示,重写paintEvent进行绘制,背景通过椭圆而成,文字应为需要控制选中状态,所以没有使用样式表,也是通过自绘完成。目前没有对外开发设置颜色接口,使用中可更具需求进行添加。

再者是StepItemWidget列表中的排布的item,由左侧数字和按钮组成,对外接口有设置setNumber和setName,顾名思义就是设置左侧数字以及按钮名称,其中按钮名称代表各步骤名称。

最后则是StepListWidget,通过setStepList填充每一步的名称,item中的按钮点击后也会触发当前选中步骤切换,也可通过函数进行切换,setCurrentStep主要用于需要初始化当前选中状态的情况。setMaxVisibleItems可设置最大显示数量,默认最大显示数量为6个。

#include <QWidget>
#include <QLabel>
class QPushButton;
class QHBoxLayout;

class StepIconLabel : public QLabel
{
    Q_OBJECT
public:
    explicit StepIconLabel(QWidget *parent = nullptr);

    void setChecked(bool checked);
    void setFontSize(int pixelSize);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    bool m_checked;
    int m_fontSize;
};

class StepItemWidget : public QWidget
{
    Q_OBJECT
public:
    explicit StepItemWidget(QWidget *parent = nullptr);

    void setNumber(quint32 number);
    void setName(const QString& nameStr);

    // 设置选中状态
    void setChecked(bool checked);

signals:
    void sig_btnClicked(quint32 number);

private:
    StepIconLabel* m_numberLabel;
    QPushButton* m_itemBtn;

    quint32 m_number;
};

class StepListWidget : public QWidget
{
    Q_OBJECT
public:
    explicit StepListWidget(QWidget *parent = nullptr);

    void setStepList(const QStringList strList);
    void setCurrentStep(int number);

    void setMaxVisibleItems(int maxItems);

signals:
    void sig_btnClicked(quint32 number);

private slots:
    void slot_toLeft();
    void slot_toRigit();
    void slot_btnClicked(quint32 number);

private:
    void refreshVisible();

private:
    QList<StepItemWidget*> m_itemList;
    QList<QWidget*> m_lineList;

    QPushButton* m_leftBtn;
    QPushButton* m_rightBtn;
    int m_maxItems;
    int m_currentIndex;

    QHBoxLayout* m_itemLayout;
};

cpp实现

#include <QPushButton>
#include <QHBoxLayout>
#include <QPainter>
#include <QPaintEvent>

///
StepIconLabel::StepIconLabel(QWidget *parent)
    : QLabel(parent)
    , m_checked(false)
    , m_fontSize(12)
{

}


void StepIconLabel::setChecked(bool checked)
{
    if (m_checked != checked) {
        m_checked = checked;
        update();
    }
}

void StepIconLabel::setFontSize(int pixelSize)
{
    if (m_fontSize != pixelSize) {
        m_fontSize = pixelSize;
        update();
    }
}

void StepIconLabel::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制背景
    painter.save();
    if (m_checked) {
        painter.setBrush(QColor(0,186,218));
        painter.setPen(QColor(0,186,218));
    }
    else {
        painter.setBrush(Qt::NoBrush);
        painter.setPen(QColor(93,93,93));
    }
    painter.drawEllipse(event->rect().marginsAdded(QMargins(-1, -1, -1, -1)));
    painter.restore();


    // 绘制文字
    painter.save();
    auto tmpFont = painter.font();
    tmpFont.setPixelSize(m_fontSize);
    painter.setFont(tmpFont);
    if (m_checked) {
        painter.setPen(QColor(255,255,255,200));
    }
    else {
        painter.setPen(QColor(93,93,93));
    }
    painter.drawText(event->rect(), Qt::AlignCenter, text());
    painter.restore();
}

///
StepItemWidget::StepItemWidget(QWidget *parent)
    : QWidget(parent)
    , m_number(0)
{
    m_numberLabel = new StepIconLabel(this);
    m_numberLabel->setFixedSize(16, 16);

    m_itemBtn = new QPushButton(this);
    m_itemBtn->setObjectName("btn_only_word_white");
    m_itemBtn->setStyleSheet("QPushButton#btn_only_word_white {\
                                color: rgba(255,255,255,0.80);\
                                background: transparent;\
                                border-radius: 0px;\
                                padding-left: 0px; \
                                padding-right: 0px;\
                              }\
                              QPushButton#btn_only_word_white:hover {\
                                color: rgb(37,207,230);\
                              }\
                              QPushButton#btn_only_word_white:pressed {\
                                color: rgb(0,146,179);\
                              }\
                              QPushButton#btn_only_word_white:disabled {\
                                color: rgb(22,74,86);\
                              }");

    connect(m_itemBtn, &QPushButton::clicked, this, [this]{
        emit sig_btnClicked(m_number);
    });

    auto mainLayout = new QHBoxLayout(this);
    mainLayout->setSpacing(8);
    mainLayout->addWidget(m_numberLabel);
    mainLayout->addWidget(m_itemBtn);
}

void StepItemWidget::setNumber(quint32 number)
{
    m_number = number;
    m_numberLabel->setText(QString::number(number + 1));
}

void StepItemWidget::setName(const QString &nameStr)
{
    m_itemBtn->setText(nameStr);
}

void StepItemWidget::setChecked(bool checked)
{
    m_numberLabel->setChecked(checked);
}

///
StepListWidget::StepListWidget(QWidget *parent)
    : QWidget(parent)
    , m_maxItems(6)
    , m_currentIndex(0)
{
    setAttribute(Qt::WA_StyledBackground);
    setStyleSheet("StepListWidget{background-color: rgb(32,32,34);}");

    m_itemLayout = new QHBoxLayout;
    m_itemLayout->setSpacing(8);

    m_leftBtn = new QPushButton("<", this);
    m_leftBtn->setFixedSize(16, 16);
    m_leftBtn->setVisible(false);
    connect(m_leftBtn, &QPushButton::clicked, this, &StepListWidget::slot_toLeft);

    m_rightBtn = new QPushButton(">", this);
    m_rightBtn->setFixedSize(16, 16);
    m_rightBtn->setVisible(false);
    connect(m_rightBtn, &QPushButton::clicked, this, &StepListWidget::slot_toRigit);

    auto mainLayout = new QHBoxLayout(this);
    mainLayout->setSpacing(8);
    mainLayout->addSpacing(15);
    mainLayout->addWidget(m_leftBtn);
    mainLayout->addLayout(m_itemLayout);
    mainLayout->addWidget(m_rightBtn);
    mainLayout->addSpacing(15);
    mainLayout->addStretch();
}

void StepListWidget::setStepList(const QStringList strList)
{
    // 清空原控件
    QLayoutItem *child;
    while ((child = m_itemLayout->takeAt(0)) != 0) {
        delete child->widget();
        delete child;
    }
    m_itemList.clear();
    m_lineList.clear();

    for(QString itemStr : strList){
        auto itemWidget = new StepItemWidget(this);
        itemWidget->setName(itemStr);
        itemWidget->setNumber(m_itemList.count());
        connect(itemWidget, &StepItemWidget::sig_btnClicked, this, &StepListWidget::slot_btnClicked);

        m_itemList << itemWidget;
        m_itemLayout->addWidget(itemWidget);

        if(itemStr != strList.last()){
            auto lineWidget = new QLabel(this);
            lineWidget->setStyleSheet(QString("QLabel{background: transparent; border: 1px solid rgb(93,93,93);}"));
            lineWidget->setFixedSize(20, 1);

            m_lineList << lineWidget;
            m_itemLayout->addWidget(lineWidget);
        }
    }

    refreshVisible();
}

void StepListWidget::setCurrentStep(int number)
{
    for (int i = 0; i < m_itemList.count(); i++) {
        m_itemList.at(i)->setChecked(number == i);
    }
}

void StepListWidget::setMaxVisibleItems(int maxItems)
{
    m_maxItems = maxItems;
    refreshVisible();
}

void StepListWidget::slot_toLeft()
{
    m_currentIndex--;
    refreshVisible();
}

void StepListWidget::slot_toRigit()
{
    m_currentIndex++;
    refreshVisible();
}

void StepListWidget::slot_btnClicked(quint32 number)
{
    setCurrentStep(number);

    emit sig_btnClicked(number);
}

void StepListWidget::refreshVisible()
{
    if(m_itemList.count() < m_maxItems){
        m_leftBtn->setVisible(false);
        m_rightBtn->setVisible(false);
    }
    else{
        m_leftBtn->setVisible(m_currentIndex != 0);
        m_rightBtn->setVisible(m_currentIndex != m_itemList.count() - m_maxItems);
    }

    // item的显示隐藏
    for(int i=0; i<m_itemList.count(); i++){
        if(i >= m_currentIndex && i < m_currentIndex + m_maxItems){
            m_itemList.at(i)->setVisible(true);
        }
        else{
            m_itemList.at(i)->setVisible(false);
        }
    }

    // 分割线的显示隐藏
    for(int i=0; i<m_lineList.count(); i++){
        if(m_itemList.count() > 1 && i >= m_currentIndex && i < m_currentIndex + m_maxItems - 1){
            m_lineList.at(i)->setVisible(true);
        }
        else{
            m_lineList.at(i)->setVisible(false);
        }
    }
}

外部调用示例

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    auto listWidget = new StepListWidget(this);
    listWidget->setStepList(QStringList() << "step1" << "step2" << "step3" << "step4" << "step5" << "step6" << "step7" << "step8");

    setCentralWidget(listWidget);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Arui丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值