分段控制器在前端交互使用较为广泛,相比 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");

