网站制作公司备案,有注入漏洞的网站源码,全网热搜榜,怎么做没有后台程序的网站目标
实现带有左右两个控制柄的滑动条#xff1b;控件可设定最小值和最大值#xff1b;控件可设定控制柄的最小距离#xff1b; 效果演示 思路 1. 标准的Slider控件只有一个Handle#xff0c;所以想要通过改造QSlider来实现两个Handle是非常困难的#xff0c;“自绘”… 目标
实现带有左右两个控制柄的滑动条控件可设定最小值和最大值控件可设定控制柄的最小距离 效果演示 思路 1. 标准的Slider控件只有一个Handle所以想要通过改造QSlider来实现两个Handle是非常困难的“自绘”是一个更好的实现方案 2. 新建DoubleHandleSlider子类继承于QSlider重写paintEvent函数在该函数里面使用QPainter绘制出希望的控件样式 3. 根据需求Slider的滑槽有两种样式分别是①和②可以先绘制一层①然后再绘制一层②则可以实现 4. handle和tips的实现方法有两种一种是通过在painterEvent中绘制另一种是创建四个QLabel分别用作left handleright handleleft tips 和 right tips然后实时更新它们的位置我选择使用QLabel的方式因为这样可以更好的使用鼠标事件。 5. handle的移动方式会有两种一是点击滑槽二是拖拽handle a.第一种通过捕获滑槽的mouse pressed事件得到mouse的x值作为handle的x坐标值刷新显示 b. 通过捕获mouse moving事件实时得到mouse的x值作为handle的x值实时刷新显示 6. 因为有两个handle所以需要设定了以下规则 a. 在left handle 左侧点击滑槽设置left handle b. 在right handle 右侧点击滑槽设置right handle c. 在left handle 和 right handle 中间点击滑槽点击的位置更靠近哪个handle则设置哪个handle 7. handle值的设置需要满足以下规则 a. left handle 大于等于最小值 b. right handle 小于等于最大值 c. left handle 和right handle的距离值大于等于设定的距离值 主要细节 1.滑槽的绘制
void DoubleHandleSlider::paintEvent(QPaintEvent *event)
{Q_UNUSED(event);m_sliderWidth width()- m_rightHandle-width();//创建painterQPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);//创建penpen的作用时描边因为这里的样式是没有边的所以需要把pen的类型设为NoPenQPen pen;pen.setStyle(Qt::PenStyle::NoPen);painter.setPen(pen);//创建画刷滑槽是通过画刷绘制的所以这里要设定好滑槽的颜色QBrush brush(QColor(0x7D, 0x7D, 0x7D));painter.setBrush(brush);//创建painter 想要绘制的路径之所以要用这个方法是因为我们需要画出两端是圆弧形的滑槽最后两个参数控制了两端圆弧的实现QPainterPath painterPath;painterPath.addRoundedRect(0, 28, m_sliderWidth, 3, 3, 3);//绘制手柄的两边灰色滑动条painter.drawPath(painterPath);//画刷更换颜色继续画另一个滑槽brush.setColor(QColor(0xFF, 0x55, 0x57));painter.setBrush(brush);//计算left handle和right handle的位置同时也是另一个滑槽的两端位置float leftX m_sliderWidth* (float)(m_leftVal-m_minVal)/m_duration;float rightX m_sliderWidth* (float)(m_rightVal-m_minVal)/m_duration;QPainterPath painterPath2;painterPath2.addRoundedRect(leftX, 28, rightX- leftX, 3, 3, 3);//绘制两手柄中间亮色滑动条painter.drawPath(painterPath2);//刷新handle和tips的位置refreshPosition(leftX, rightX);
} 2.handle的移动
bool DoubleHandleSlider::eventFilter(QObject *watched, QEvent *event)
{if(watched m_leftHadle){if(event-type() QEvent::Enter){setCursor(QCursor(Qt::OpenHandCursor));m_mouseEnterType InLeftHandle;}else if(event-type() QEvent::Leave){setCursor(QCursor(Qt::OpenHandCursor));m_mouseEnterType NotInHandle;}}else if(watched m_rightHandle){if(event-type() QEvent::Enter){setCursor(QCursor(Qt::OpenHandCursor));m_mouseEnterType InRightHandle;}else if(event-type() QEvent::Leave){setCursor(QCursor(Qt::OpenHandCursor));m_mouseEnterType NotInHandle;}}else{return QWidget::eventFilter(watched, event);}return false;
} a. 在eventFilter判断鼠标所在位置的类型分别有NotInHandleInLefthandle和InRightHandle三种类型 b. 这里需要注意的是在创建handle时需要调用installEventFilter()才能捕获相应控件的事件 void DoubleHandleSlider::mousePressEvent(QMouseEvent *event)
{//判断鼠标是否在滑动条范围内if(event-pos().y() m_leftHadle-y() || event-pos().y() m_leftHadle-y() m_leftHadle-height())return;if(m_mouseEnterType NotInHandle){int handleDuration m_rightHandle-x()- m_leftHadle-x();//鼠标在左手柄的左边if(event-pos().x() m_leftHadle-x())refreshLeftVal(event-pos().x());//鼠标在右手柄的右边else if(event-pos().x() m_rightHandle-x())refreshRightVal(event-pos().x());//鼠标在两个手柄的中间但靠近左手柄else if(event-pos().x() m_leftHadle-pos().x() handleDuration/2)refreshLeftVal(event-pos().x());//鼠标在两个手柄的中间但更靠近有手柄else if(event-pos().x() m_leftHadle-pos().x() handleDuration/2)refreshRightVal(event-pos().x());update();}
} c.再在mousePressedEvent中根据类型处理当类型是NotInHandle时根据前面思路5.a和6的规则设置handle void DoubleHandleSlider::mouseMoveEvent(QMouseEvent *event)
{if(m_mouseEnterType InLeftHandle){refreshLeftVal(event-pos().x());update();}else if(m_mouseEnterType InRightHandle){refreshRightVal(event-pos().x());update();}
}void DoubleHandleSlider::refreshLeftVal(float x)
{//重新计算左值m_leftVal m_duration* x/m_sliderWidth m_minVal;
// qDebug() m_leftVal;if(m_leftVal m_minVal)m_leftVal m_minVal;else if(m_leftVal m_rightVal- m_handleIntervalVal)m_leftVal m_rightVal- m_handleIntervalVal;emit valueChanged(m_leftVal, m_rightVal);
}void DoubleHandleSlider::refreshRightVal(float x)
{//重新计算右值m_rightVal m_duration* x/m_sliderWidth m_minVal;
// qDebug() m_rightVal;if(m_rightVal m_maxVal)m_rightVal m_maxVal;else if(m_rightVal m_leftVal m_handleIntervalVal)m_rightVal m_leftVal m_handleIntervalVal;emit valueChanged(m_leftVal, m_rightVal);
} d. 根据在eventFilter中得到的鼠标所在位置的类型在mouseMovingEvent中用mouse的x值按思路5.b和6的规则更新handle值 其它 1. tips 只需要跟随handle位置变化而变化即可 2. 在handle的移动实现中只是更新handle的值并没有直接更新handle的位置handle的位置更新是在paintEvent()调用的是根据handle的值换算出来位置值这样就跟滑槽的绘制保持了同步性 ---------------------------【Demo完整代码】-----------------------------------