QT 选项条设计

选项条使用水平设计,可支持多个选项设置,和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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值