选项条使用水平设计,可支持多个选项设置,和Combobox的功能类似。
switch_control.h
#ifndef SWITCH_CONTROL
#define SWITCH_CONTROL
#include <QWidget>
class SwitchControl : public QWidget
{
Q_OBJECT
public:
explicit SwitchControl(QWidget *parent = 0);
void setSwitchIndex(int index);
int switchIndex();
void setSwitchItems(const QStringList &list);
void setBackgroundColor(QColor color);
protected:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *);
void focusInEvent(QFocusEvent *);
void focusOutEvent(QFocusEvent *);
void mousePressEvent(QMouseEvent *event);
QSize sizeHint() const;
QSize minimumSizeHint() const;
signals:
void toggled(int);
private:
int getIndexByPos(const QPoint &pos);
private:
QColor m_background;
QColor m_focusColor;
int m_borderWidth;
qint16 m_margin;
int m_borderRadius;
QString m_leftText;
QString m_rightText;
int m_seletedIndex;
QStringList m_indexItems;
};
#endif // SWITCH_CONTROL
switch_control.cpp
#include <QPainter>
#include <QMouseEvent>
#include <QtCore/qmath.h>
#include "switch_control.h"
#include <QApplication>
SwitchControl::SwitchControl(QWidget *parent)
: QWidget(parent),
m_background("#343434"),
m_focusColor("#4189D3"),
m_borderWidth(2),
m_margin(3),
m_borderRadius(5),
m_seletedIndex(0)
{
}
void SwitchControl::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setPen(Qt::NoPen);
painter.setRenderHint(QPainter::Antialiasing);
// 设置使能与不使能控件时,控件的透明度
if (isEnabled())
{
painter.setOpacity(1);
}
else
{
painter.setOpacity(0.5);
}
/* 绘制聚焦矩形 */
if (hasFocus())
{
painter.setBrush(m_focusColor);
int margin = m_margin - m_borderWidth;
QRectF rectF = QRectF(margin, margin, width()-2*margin, height()-2*margin);
painter.drawRoundedRect(rectF, m_borderRadius, m_borderRadius);
}
/* 绘制背景 */
painter.setBrush(m_background);
QRectF rectF = QRectF(m_margin, m_margin, width()-2*m_margin, height()-2*m_margin);
painter.drawRoundedRect(rectF, m_borderRadius, m_borderRadius);
/* 绘制滑块 */
int area_num = m_indexItems.count(); // 总共有多少区域
int handle_magin = m_margin; // 滑块外边距
int handle_w = (width()-2*handle_magin)/area_num; // 滑块宽度
int handle_h = height()-2*handle_magin; // 滑块高度
int remain_right_w = width() - (2*handle_magin + handle_w*(area_num-1)); // 最后一个滑块的宽度
int handle_y = handle_magin; // 开始绘制滑块的y坐标
int draw_x = handle_magin + m_seletedIndex*handle_w; // 开始绘制的x坐标
if (area_num == 0)
{
return;
}
// 设置渐变色区域
QLinearGradient linearArea;
linearArea.setSpread(QGradient::PadSpread); //渐变色默认显示模式:指定区域渐变
linearArea.setColorAt(0, "#ffb3e6");
linearArea.setColorAt(1, "#fc96DB");
linearArea.setStart(QPointF(draw_x, handle_y));
linearArea.setFinalStop(QPointF(draw_x+handle_w, handle_y+handle_h));
painter.setBrush(linearArea);
// 绘制滑块
if (m_seletedIndex==0 || m_seletedIndex==area_num-1)
{
// 边缘滑块需要做圆角矩形
QPainterPath path;
path.setFillRule(Qt::WindingFill); //设置填充方式
if (m_seletedIndex==0)
{
// 左边为圆角矩形,右边为直角矩形
rectF = QRectF(draw_x, handle_y, handle_w, handle_h);
path.addRoundedRect(rectF, m_borderRadius, m_borderRadius);
rectF = QRectF(draw_x+handle_w/2+1, handle_y, handle_w/2, handle_h);
path.addRect(rectF);
}
else
{
// 左边为直角矩形,右边为圆角矩形
rectF = QRectF(draw_x, handle_y, remain_right_w, handle_h);
path.addRoundedRect(rectF, m_borderRadius, m_borderRadius);
rectF = QRectF(draw_x, handle_y, remain_right_w/2, handle_h);
path.addRect(rectF);
}
painter.drawPath(path.simplified());
}
else
{
rectF = QRectF(draw_x, handle_y, handle_w, handle_h);
painter.drawRect(rectF);
}
/* 绘制文本 */
QFont m_font(font());
for (int ii=0; ii<area_num; ii++)
{
QColor textColor = (ii == m_seletedIndex) ? QColor("#242424") : QColor("#545454");
m_font.setBold((ii == m_seletedIndex) ? false : true);
painter.setFont(m_font);
painter.setPen(textColor);
QRectF rect;
int area_w = (ii == area_num-1) ? remain_right_w : handle_w;
rect = QRectF(handle_magin+ii*handle_w, handle_y, area_w, handle_h);
painter.drawText(rect, Qt::AlignCenter, m_indexItems.at(ii));
}
}
void SwitchControl::keyPressEvent(QKeyEvent *event)
{
if (false == isEnabled() || (m_indexItems.count() == 0)) return;
if (event->key() == Qt::Key_Left)
{
int index = m_seletedIndex;
if (index == 0)
{
index = m_indexItems.count() - 1;
}
else
{
index -= 1;
}
setSwitchIndex(index);
}
else if (event->key() == Qt::Key_Right)
{
int index = m_seletedIndex;
if (index == m_indexItems.count() - 1)
{
index = 0;
}
else
{
index += 1;
}
setSwitchIndex(index);
}
}
void SwitchControl::focusInEvent(QFocusEvent *)
{
update();
}
void SwitchControl::focusOutEvent(QFocusEvent *)
{
update();
}
// 鼠标按下事件
void SwitchControl::mousePressEvent(QMouseEvent *event)
{
if (false == isEnabled() || (0 == m_indexItems.count())) return;
if ((event->type() == QMouseEvent::MouseButtonPress) && (event->button() == Qt::LeftButton))
{
int index = getIndexByPos(event->pos());
setSwitchIndex(index);
}
}
int SwitchControl::getIndexByPos(const QPoint &pos)
{
int x = pos.x();
if (x < m_margin || x > (m_margin+width())) return -1;
int total = m_indexItems.count();
int per_width = width()/total;
return x/per_width;
}
// 设置背景颜色
void SwitchControl::setBackgroundColor(QColor color)
{
m_background = color;
}
void SwitchControl::setSwitchIndex(int index)
{
if (index < 0 || (index > m_indexItems.count()-1)) return;
if (m_seletedIndex == index) return;
m_seletedIndex = index;
if (isVisible())
{
update();
}
emit toggled(index);
}
int SwitchControl::switchIndex()
{
return m_seletedIndex;
}
void SwitchControl::setSwitchItems(const QStringList &list)
{
m_indexItems = list;
QFontMetrics fm(qApp->font());
int maxWidth = 42;
for (int ii=0; ii<list.count(); ii++)
{
// 内边距设置为15
int width = fm.width(list.at(ii)) + 30;
if (width > maxWidth)
{
maxWidth = width;
}
}
setMinimumWidth(list.count() * maxWidth + m_margin*2);
if (isVisible())
{
update();
}
}
// 默认大小
QSize SwitchControl::sizeHint() const
{
return minimumSizeHint();
}
// 最小大小
QSize SwitchControl::minimumSizeHint() const
{
return QSize(100, 44);
}