在项目中使用QSlider,需求是:一边拖动slider读取滑块位置去设置一个处理的起始进度(读取),一边从处理的进度中送上来的值,来更新slider的滑块位置(写入)。这两个操作应该是互斥的,否则用户在拖动slider滑块时,又被送上来的值更新,滑块位置变来变去,体验非常不好。
这个问题的解决思路:从一个处理中送上来的进度值,不要直接更新slider滑块,而是去更新一个数值类型的全局变量。把更新slide滑块r的动作放到一个定时器中,靠定时器的开启和关闭来决定什么时候更新滑块的进度。
关闭定时器的动作放到:sliderPressed槽函数中;开启定时器的动作放到:sliderReleased槽函数中。因为sliderReleased槽函数鼠标抬起,可以直接取出滑块的位置。
还可以sliderReleased槽函数中开启一个延时去启动定时器,避免和过早的送上来的值冲突。
这类问题还有类似的,如一个线程不断获取数据,一个线程要更新界面上的控件,传统的解决是线程里发信号给要处理的界面控件(qt中),或者线程中直接更新界面控制值(vc中)。其实完全可以采用上面这种非常简单的思路来处理,而且非常安全。
程序框架如下:
//在sliderPressed中开启定时
void XXX::on_sliderReleased()
{
//独处slider滑块的值,去更新要处理的起始进度
int progress=ui->horizontalSlider->value()
//.....
//.....
//延时1s后执行开启定时器
QTimer::singleShot(1000, this, SLOT(delayFunc())); //
}
//在sliderPressed中关闭定时
void XXX::on_sliderPressed()
{
killTimer(timerId);
}
//延时1s后执行的动作
void XXX::delayFunc()
{
startTimer(timerId); //开启更新slider滑块的定时器
}
//定时器中更新滑块位置
void XXX::timerEvent(QTimerEvent *event)
{
if(event->timerId() == timerId)
{
ui->horizontalSlider->setValue(m_curSliderProgress);
}
}
// double m_curSliderProgress;
// m_curSliderProgress变量在别的地方被不断更新
// m_curSliderProgress <== 其他处理