天天看点

QT自定义控件--滑动选择器

文章目录

  • ​​一、前言​​
  • ​​二、效果展示​​
  • ​​三、控件分析​​
  • ​​四、原理详解​​
  • ​​五、关键代码​​

一、前言

这是基于Qt实现的自定义滑动选择器,滑动选择器支持两种模式:水平模式和垂直模式,可自行设置。另外提供了接口可设置各类颜色、选择器值域等。

在这里提供了​​下载链接​​。

二、效果展示

QT自定义控件--滑动选择器

三、控件分析

滑动选择器,是一个可以在通过控件上左右滑动,然后左右两侧数据会随之左右滚动并标记(颜色突出)出当前值,来进行选择值的一个控件。我们可以把它拆分为三部分:背景框、分隔线、数字,所以我们可以把绘制过程分为三部分,绘制背景框、绘制分割线、绘制数字。

四、原理详解

五、关键代码

void SlidingSelector::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);

    paint_frame(&painter);
    paint_parting_line(&painter);

    int Width = width()-1;
    int Height = height()-1;

    if(mode == Horizontal)
    {
        if(mouse_move_length >= Width/4 && Current_num > MIN_NUM)
        {
            mouse_Press += Width/4;
            mouse_move_length -= Width/4;
            Current_num -= 1;
        }
        if(mouse_move_length <= -Width/4 && Current_num < MAX_NUM)
        {
            mouse_Press -= Width/4;
            mouse_move_length += Width/4;
            Current_num += 1;
        }

        //中间数字
        paint_num(&painter,Current_num,mouse_move_length,1);

        //两侧数字1
        if(Current_num != MIN_NUM)
            paint_num(&painter,Current_num-1,mouse_move_length-Width/4,0);
        if(Current_num != MAX_NUM)
            paint_num(&painter,Current_num+1,mouse_move_length+Width/4,0);

        //两侧数字2,超出则不显示
        if(mouse_move_length >= 0 && Current_num-2 >= MIN_NUM)
            paint_num(&painter,Current_num-2,mouse_move_length-Width/2,0);
        if(mouse_move_length <= 0 && Current_num+2 <= MAX_NUM)
            paint_num(&painter,Current_num+2,mouse_move_length+Width/2,0);
    }
    else
    {
        if(mouse_move_length >= Height/4 && Current_num > MIN_NUM)
        {
            mouse_Press += Height/4;
            mouse_move_length -= Height/4;
            Current_num -= 1;
        }
        if(mouse_move_length <= -Height/4 && Current_num < MAX_NUM)
        {
            mouse_Press -= Height/4;
            mouse_move_length += Height/4;
            Current_num += 1;
        }

        //中间数字
        paint_num(&painter,Current_num,mouse_move_length,1);

        //上下数字1
        if(Current_num != MIN_NUM)
            paint_num(&painter,Current_num-1,mouse_move_length-Height/4,0);
        if(Current_num != MAX_NUM)
            paint_num(&painter,Current_num+1,mouse_move_length+Height/4,0);

        //上下数字2,超出则不显示
        if(mouse_move_length >= 0 && Current_num-2 >= MIN_NUM)
            paint_num(&painter,Current_num-2,mouse_move_length-Height/2,0);
        if(mouse_move_length <= 0 && Current_num+2 <= MAX_NUM)
            paint_num(&painter,Current_num+2,mouse_move_length+Height/2,0);
    }

}

void SlidingSelector::paint_frame(QPainter *painter)
{
    painter->save();

    painter->setPen(Qt::NoPen);
    painter->setBrush(frame_color);

    painter->drawRect(space,space,width()-space*2,height()-space*2);

    painter->restore();
}

void SlidingSelector::paint_num(QPainter *painter,int num,int mouse_move_length,int mid)
{
    painter->save();

    int Width = width()-1;
    int Height = height()-1;

    if(mode == Horizontal)
    {
        int size = qAbs((Width - qAbs(mouse_move_length))/num_size);//像素尺寸
        int width = Width/2-3*qAbs(mouse_move_length);//数字框宽度
        int x = Width/2+mouse_move_length-width/2;//数字框x坐标

        QFont font;
        font.setPixelSize(size);
        painter->setFont(font);
        if(mid == 1)
            painter->setPen(currentNum_color);
        else
            painter->setPen(besideNum_color);

        painter->drawText(QRectF(x,0,width,Height),Qt::AlignCenter,QString::number(num));
    }
    else
    {
        int size = qAbs((Height - qAbs(mouse_move_length))/num_size);//像素尺寸
        int height = Height/2-3*qAbs(mouse_move_length);//数字框宽度
        int y = Height/2+mouse_move_length-height/2;//数字框x坐标

        QFont font;
        font.setPixelSize(size);
        painter->setFont(font);
        if(mid == 1)
            painter->setPen(currentNum_color);
        else
            painter->setPen(besideNum_color);

        painter->drawText(QRectF(0,y,Width,height),Qt::AlignCenter,QString::number(num));
    }

    painter->restore();

}

void SlidingSelector::paint_parting_line(QPainter *painter)
{
    painter->save();

    QPen pen;
    pen.setBrush(partingLine_color);
    pen.setWidth(4);
    pen.setCapStyle(Qt::RoundCap);
    pen.setStyle(Qt::SolidLine);
    painter->setPen(pen);

    if(mode == Horizontal)
    {
        int up_down_space=height()/10;
        QPoint line_left_up=QPoint(space+(width()-space*2)/3,space+up_down_space);
        QPoint line_left_down=QPoint(space+(width()-space*2)/3,height()-space-up_down_space);
        QPoint line_right_up=QPoint(space+((width()-space*2)/3)*2,space+up_down_space);
        QPoint line_right_down=QPoint(space+((width()-space*2)/3)*2,height()-space-up_down_space);
        painter->drawLine(line_left_up,line_left_down);//绘制左侧分割线
        painter->drawLine(line_right_up,line_right_down);//绘制右侧分割线
    }
    else
    {
        int up_down_space=width()/10;
        QPoint line_left_up=QPoint(space+up_down_space,space+(height()-space*2)/3);
        QPoint line_left_down=QPoint(space+(width()-space*2)-up_down_space,space+(height()-space*2)/3);
        QPoint line_right_up=QPoint(space+up_down_space,space+((height()-space*2)/3)*2);
        QPoint line_right_down=QPoint(space+(width()-space*2)-up_down_space,space+((height()-space*2)/3)*2);
        painter->drawLine(line_left_up,line_left_down);//绘制左侧分割线
        painter->drawLine(line_right_up,line_right_down);//绘制右侧分割线
    }

    painter->restore();

}