Qt 实现自定义分段控制器

分段控制器在前端交互使用较为广泛,相比 Qt 常用的下拉框、单选框、复选框,选择交互上更为便捷,样式上更加简洁可控,使用 Qt 实现带类似功能的控件,可复用到选项需求的功能开发,提高软件质量。

功能包括选项输入、样式接口、默认选中、互斥检测、结果回传,以 https://forgeglobal.com/ 网站的实现为参考。

QSegmentedWidget.h

cpp 复制代码
class QSegmentedWidget : public QWidget
{
    Q_OBJECT

public:
    QSegmentedWidget(QWidget *parent = nullptr);
    ~QSegmentedWidget();
    bool eventFilter(QObject *watched, QEvent *event);

    void setSource(QStringList lst, QString ss);

    void setHoverColor(QString color)
    {
        hoverColor = color;
        updateColor();
    }

    void setHoverTextColor(QString color)
    {
        hoverTextColor = color;
        updateColor();
    }

    void setCheckColor(QString color)
    {
        checkColor = color;
        updateColor();
    }

private slots:
    void setChecked();

    void updateColor()
    {
        btnStyleNormal = QString("QPushButton{background-color: rgb(255,255,255);color: rgb(95,110,124); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-radius:0px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%2);}").arg(hoverColor).arg(hoverTextColor);

        btnStyleCheck = QString("QPushButton{background-color: rgb(%2);color: rgb(247,249,250); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-radius:0px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%3);}").arg(hoverColor).arg(checkColor).arg(hoverTextColor);

        btnStyleNormalFirst = QString("QPushButton{background-color: rgb(255,255,255);color: rgb(95,110,124); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-top-left-radius: 5px;border-top-right-radius: 0px;border-bottom-left-radius: 5px;border-bottom-right-radius: 0px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%2);}").arg(hoverColor).arg(hoverTextColor);

        btnStyleCheckFirst = QString("QPushButton{background-color: rgb(%2);color: rgb(247,249,250); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-top-left-radius: 5px;border-top-right-radius: 0px;border-bottom-left-radius: 5px;border-bottom-right-radius: 0px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%3);}").arg(hoverColor).arg(checkColor).arg(hoverTextColor);

        btnStyleNormalLast = QString("QPushButton{background-color: rgb(255,255,255);color: rgb(95,110,124); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-top-left-radius: 0px;border-top-right-radius: 5px;border-bottom-left-radius: 0px;border-bottom-right-radius: 5px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%2);}").arg(hoverColor).arg(hoverTextColor);

        btnStyleCheckLast = QString("QPushButton{background-color: rgb(%2);color: rgb(247,249,250); font: 14pt \"Microsoft YaHei\"; border: 1px solid;border-top-left-radius: 0px;border-top-right-radius: 5px;border-bottom-left-radius: 0px;border-bottom-right-radius: 5px;}QPushButton:hover{background-color: rgb(%1);color: rgb(%3);}").arg(hoverColor).arg(checkColor).arg(hoverTextColor);
    }

signals:
    void emitChecked(QString ss);

private:
    QString hoverColor = "30,36,42";
    QString hoverTextColor = "247,249,250";
    QString checkColor = "30,36,42";
    QStringList sourceLst;
    QList<QPushButton*> btnLst;
    QHBoxLayout *layout = nullptr;
    QString btnStyleNormal;
    QString btnStyleCheck;
    QString btnStyleNormalFirst;
    QString btnStyleCheckFirst;
    QString btnStyleNormalLast;
    QString btnStyleCheckLast;
    QPushButton *curBtn = nullptr;
    QPixmap pixmap;
};

QSegmentedWidget.cpp

cpp 复制代码
#include <QSvgRenderer>
QPixmap svg2Pixmap(QString svg)
{
    QSvgRenderer render;
    render.load(svg);

    QPixmap pix(render.defaultSize());
    pix.fill(Qt::transparent);

    QPainter painter(&pix);
    painter.setRenderHints(QPainter::Antialiasing);
    render.render(&painter);

    return pix;
}

QSegmentedWidget::QSegmentedWidget(QWidget *parent)
    : QWidget(parent)
{
    layout = new QHBoxLayout;
    layout->setSpacing(0);
    setLayout(layout);

    updateColor();

    pixmap = svg2Pixmap("check.svg");
}

QSegmentedWidget::~QSegmentedWidget()
{

}

bool QSegmentedWidget::eventFilter(QObject *watched, QEvent *event)
{
    Q_UNUSED(watched);

    if (event->type() == QEvent::Enter)
    {
        setCursor(Qt::PointingHandCursor);
        return true;
    }

    if (event->type() == QEvent::Leave)
    {
        setCursor(Qt::ArrowCursor);
        return true;
    }

    return false;
}

void QSegmentedWidget::setSource(QStringList lst, QString cc)
{
    curBtn = nullptr;

    foreach (QPushButton* btn, btnLst)
    {
        layout->removeWidget(btn);
        delete btn;
    }

    btnLst.clear();

    sourceLst = lst;

    foreach (QString data, lst)
    {
        QPushButton *btn = new QPushButton(data);
        btn->setFixedSize(90, 50);
        btn->setObjectName(data);
        if (data == sourceLst.first())
        {
            btn->setStyleSheet(btnStyleNormalFirst);
        }
        else if (data == sourceLst.last())
        {
            btn->setStyleSheet(btnStyleNormalLast);
        }
        else
        {
            btn->setStyleSheet(btnStyleNormal);
        }
        btn->installEventFilter(this);
        connect(btn, SIGNAL(clicked(bool)), this, SLOT(setChecked()));
        layout->addWidget(btn);
        btnLst.append(btn);
    }

    if (lst.contains(cc))
    {
        foreach (QPushButton* btn, btnLst)
        {
            if (btn->objectName() == cc)
            {
                btn->click();
                break;
            }
        }
    }
    else
    {
        btnLst[0]->click();
    }
}

void QSegmentedWidget::setChecked()
{
    QPushButton *btn = qobject_cast<QPushButton *>(sender());
    if (curBtn == btn)
    {
        return;
    }

    btn->setIcon(QIcon(pixmap));

    QString data = btn->objectName();
    if (data == sourceLst.first())
    {
        btn->setStyleSheet(btnStyleCheckFirst);
    }
    else if (data == sourceLst.last())
    {
        btn->setStyleSheet(btnStyleCheckLast);
    }
    else
    {
        btn->setStyleSheet(btnStyleCheck);
    }

    if (curBtn != nullptr)
    {
        curBtn->setIcon(QIcon());
        QString data = curBtn->objectName();
        if (data == sourceLst.first())
        {
            curBtn->setStyleSheet(btnStyleNormalFirst);
        }
        else if (data == sourceLst.last())
        {
            curBtn->setStyleSheet(btnStyleNormalLast);
        }
        else
        {
            curBtn->setStyleSheet(btnStyleNormal);
        }
    }

    curBtn = btn;

    emit emitChecked(btn->objectName());
}

check.svg

css 复制代码
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M4.33,8.92l-2.92-3.06c-.33-.34-.84-.34-1.17,0-.33.34-.33.88,0,1.22l3.49,3.67c.33.34.85.34,1.18,0L13.76,1.48c.33-.34.33-.88,0-1.22-.33-.34-.84-.34-1.17,0L4.33,8.92Z" fill="#F7F9FA"></path></svg>

setSource选项输入和默认选中、set**Color样式接口、emitChecked结果回传。

cpp 复制代码
segmentedWidget = new QSegmentedWidget;
connect(segmentedWidget, SIGNAL(emitChecked(QString)), this, SLOT(segmentedChecked(QString)));
QStringList lst;
lst.append("7D");
lst.append("1M");
lst.append("3M");
lst.append("6M");
lst.append("1Y");
lst.append("ALL");
segmentedWidget->setSource(lst, "6M");

void MainWindow::segmentedChecked(QString cc)
{
    qDebug() << cc;
}

QStringList lst;
lst.append("Mon");
lst.append("Tue");
lst.append("Wed");
lst.append("Thu");
lst.append("Fri");
lst.append("Sat");
lst.append("Sun");
segmentedWidget->setHoverColor("64,158,255");
segmentedWidget->setHoverTextColor("96,98,102");
segmentedWidget->setCheckColor("64,158,255");
segmentedWidget->setSource(lst, "Wed");
相关推荐
爱喝雪碧的可乐1 小时前
【Redis 毁灭计划】7 大高危操作打崩线上服务!从缓存雪崩到数据库宕机,90% 程序员都踩过的坑
开发语言·网络·redis·php
Xpower 171 小时前
OpenClaw Token 优化的技术方案与实践:OpenSpace 自进化 Skill 引擎
java·开发语言·人工智能
南宫萧幕1 小时前
基于最优控制理论的 HEV 能量管理:从物理建模到 VMD-PPO 强化学习环境构建
开发语言·人工智能·matlab·simulink·控制
froginwe111 小时前
Memcached get 命令详解
开发语言
李日灐1 小时前
<4>Linux 权限:从 Shell 核心原理 到 权限体系的底层逻辑 详解
linux·运维·服务器·开发语言·后端·面试·权限
renhongxia12 小时前
计算机视觉实战:图像去噪模型训练与应用
开发语言·人工智能·机器学习·计算机视觉·prompt
寒秋花开曾相惜2 小时前
(学习笔记)4.1 Y86-64指令集体系结构(4.1.6 一些Y86-64指令 )
linux·运维·服务器·开发语言·笔记·学习·安全
誰能久伴不乏2 小时前
Qt 混合编程核心原理:C++ 与 QML 通信机制详解
linux·c++·qt·架构·状态模式
城管不管2 小时前
EasyExcel
java·开发语言·后端·easyexcel