ユーザーが qslider のどこかをクリックしたときにステップする代わりに、スライダーをその位置にジャンプさせたいと思います。これはどのように実装できますか?
12 に答える
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);
}
};
私もこれが必要で、スパイクソリューションを試しましたが、次の2つが欠けています:
- 反転した外観
- ハンドルのピッキング (マウスがハンドルの上にある場合、直接ジャンプする必要はありません)
したがって、レビューしたコードは次のとおりです。
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);
}
QStyle.sliderValueFromPosition() を使用した Python での簡単な実装を次に示します。
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()))
次のコードは実際にはハックですが、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;
}
}
// ...
}
おもう、
QStyle::sliderValueFromPosition() 関数を使用できます。
http://qt-project.org/doc/qt-5/qstyle.html#sliderValueFromPosition
私はこれをネットで検索しようとしていて、これを行うよりスマートな方法をQtに期待していましたが、残念ながら大きな助けはありませんでした(適切に検索していなかった可能性があります)
Qtクリエーターでこれを行いました:
- ヘッダーに eventFilter を追加します (QObject と QEvent を引数として取ります) (ブール型の戻り値)
- コンストラクターで初期化します。たとえば、スライダーが HSlider の場合は、ui->HSlider->installEventFilter(this); です。
定義では:
を。オブジェクトが次のようなスライダー タイプであるかどうかを確認します。
ui->HSlider == Object
b. 次のようなマウスクリックイベントを確認します。
QEvent::MouseButtonPress == event->type
c. 上記のすべてのパスが、スライダーでマウスイベントを取得したことを意味する場合は、次のようにします:定義では:
ui->HSlider->setValue( Qcursor::pos().x() - firstval ); return QMainWindow::eventFilter(object, event);
注: fistVal : Cursur の位置を 0 = スライダーの初期位置に出力することで取り出すことができます ( の助けを借りてQCursor::pos().x()
)
お役に立てれば
簡単な方法は、 から派生さQSlider
せて再実装mousePressEvent(....)
し、 を使用してマーカーの位置を設定することsetSliderPosition(int)
です。
私もこの問題に遭遇しました。私の解決策を以下に示します。
slider->installEventFilter(this);
---
bool MyDialog::eventFilter(QObject *object, QEvent *event)
{
if (object == slider && slider->isEnabled())
{
if (event->type() == QEvent::MouseButtonPress)
{
auto mevent = static_cast<QMouseEvent *>(event);
qreal value = slider->minimum() + (slider->maximum() - slider->minimum()) * mevent->localPos().x() / slider->width();
if (mevent->button() == Qt::LeftButton)
{
slider->setValue(qRound(value));
}
event->accept();
return true;
}
if (event->type() == QEvent::MouseMove)
{
auto mevent = static_cast<QMouseEvent *>(event);
qreal value = slider->minimum() + (slider->maximum() - slider->minimum()) * mevent->localPos().x() / slider->width();
if (mevent->buttons() & Qt::LeftButton)
{
slider->setValue(qRound(value));
}
event->accept();
return true;
}
if (event->type() == QEvent::MouseButtonDblClick)
{
event->accept();
return true;
}
}
return QDialog::eventFilter(object, event);
}
QSlider のこれらのイベント ハンドラをオーバーライドすることもできます。
QSlider::mousePressedEvent
QSlider::mouseMoveEvent
QSlider::mouseDoubleClickEvent