Mic*_*cka 26
在所有版本的@spyke @Massimo Callegari和@Ben(滑块位置对于整个区域都不正确)出现问题后,我在QSlider源代码中找到了一些Qt Style功能:QStyle::SH_Slider_AbsoluteSetButtons.
您必须创建一个非常烦人的新QStyle,或者ProxyStyle如http://www.qtcentre.org/threads/9208-QSlider-step-customize?p=49035#post49035中的用户jpn所示使用
我添加了另一个构造函数并修复了拼写错误,但使用了原始源代码的其余部分.
#include <QProxyStyle>
class MyStyle : public QProxyStyle
{
public:
using QProxyStyle::QProxyStyle;
int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const
{
if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
return (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
return QProxyStyle::styleHint(hint, option, widget, returnData);
}
};
Run Code Online (Sandbox Code Playgroud)
现在,您可以在滑块构造函数中设置滑块的样式(如果滑块是从QSlider派生的):
setStyle(new MyStyle(this->style()));
Run Code Online (Sandbox Code Playgroud)
或者它应该以这种方式工作,如果它是一个标准的QSlider:
standardSlider.setStyle(new MyStyle(standardSlider->style()));
Run Code Online (Sandbox Code Playgroud)
所以你使用该元素的原始样式,但如果要求QStyle::SH_Slider_AbsoluteSetButtons"属性",你可以根据需要返回;)
也许你必须在滑块删除时销毁这些代理方式,尚未测试.
Sca*_*ode 22
好吧,我怀疑Qt是否具有此功能的直接功能.
尝试使用自定义小部件.这应该工作!
尝试以下逻辑
class MySlider : public QSlider
{
protected:
void mousePressEvent ( QMouseEvent * event )
{
if (event->button() == Qt::LeftButton)
{
if (orientation() == Qt::Vertical)
setValue(minimum() + ((maximum()-minimum()) * (height()-event->y())) / height() ) ;
else
setValue(minimum() + ((maximum()-minimum()) * event->x()) / width() ) ;
event->accept();
}
QSlider::mousePressEvent(event);
}
};
Run Code Online (Sandbox Code Playgroud)
Mas*_*ari 19
我也需要这个并尝试spyke解决方案,但它缺少两件事:
所以,这是经过审核的代码:
void MySlider::mousePressEvent ( QMouseEvent * event )
{
QStyleOptionSlider opt;
initStyleOption(&opt);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
if (event->button() == Qt::LeftButton &&
sr.contains(event->pos()) == false)
{
int newVal;
if (orientation() == Qt::Vertical)
newVal = minimum() + ((maximum()-minimum()) * (height()-event->y())) / height();
else
newVal = minimum() + ((maximum()-minimum()) * event->x()) / width();
if (invertedAppearance() == true)
setValue( maximum() - newVal );
else
setValue(newVal);
event->accept();
}
QSlider::mousePressEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*Ben 15
Massimo Callegari的答案几乎是正确的,但newVal的计算忽略了滑块手柄的宽度.当您尝试在滑块末端附近单击时,会出现此问题.
以下代码修复了水平滑块的问题
double halfHandleWidth = (0.5 * sr.width()) + 0.5; // Correct rounding
int adaptedPosX = event->x();
if ( adaptedPosX < halfHandleWidth )
adaptedPosX = halfHandleWidth;
if ( adaptedPosX > width() - halfHandleWidth )
adaptedPosX = width() - halfHandleWidth;
// get new dimensions accounting for slider handle width
double newWidth = (width() - halfHandleWidth) - halfHandleWidth;
double normalizedPosition = (adaptedPosX - halfHandleWidth) / newWidth ;
newVal = minimum() + ((maximum()-minimum()) * normalizedPosition);
Run Code Online (Sandbox Code Playgroud)
小智 9
这是python中使用QStyle.sliderValueFromPosition()的一个简单实现:
class JumpSlider(QtGui.QSlider):
def mousePressEvent(self, ev):
""" Jump to click position """
self.setValue(QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), ev.x(), self.width()))
def mouseMoveEvent(self, ev):
""" Jump to pointer position while moving """
self.setValue(QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), ev.x(), self.width()))
Run Code Online (Sandbox Code Playgroud)
下面的代码实际上是一个hack,但它没有子类化QSlider它工作正常.您唯一需要做的就是将QSlider valueChanged信号连接到您的容器.
注意1:您必须在滑块中设置pageStep> 0
注意2:它仅适用于水平,从左到右的滑块(您应该将"sliderPosUnderMouse"的计算更改为使用垂直方向或倒置外观)
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
// ...
connect(ui->mySlider, SIGNAL(valueChanged(int)),
this, SLOT(mySliderValueChanged(int)));
// ...
}
void MainWindow::mySliderValueChanged(int newPos)
{
// Make slider to follow the mouse directly and not by pageStep steps
Qt::MouseButtons btns = QApplication::mouseButtons();
QPoint localMousePos = ui->mySlider->mapFromGlobal(QCursor::pos());
bool clickOnSlider = (btns & Qt::LeftButton) &&
(localMousePos.x() >= 0 && localMousePos.y() >= 0 &&
localMousePos.x() < ui->mySlider->size().width() &&
localMousePos.y() < ui->mySlider->size().height());
if (clickOnSlider)
{
// Attention! The following works only for Horizontal, Left-to-right sliders
float posRatio = localMousePos.x() / (float )ui->mySlider->size().width();
int sliderRange = ui->mySlider->maximum() - ui->mySlider->minimum();
int sliderPosUnderMouse = ui->mySlider->minimum() + sliderRange * posRatio;
if (sliderPosUnderMouse != newPos)
{
ui->mySlider->setValue(sliderPosUnderMouse);
return;
}
}
// ...
}
Run Code Online (Sandbox Code Playgroud)