Я реализовал поворотный виджет в Qt. Когда пользователь щелкает поворотное устройство, курсор мыши скрывается, и перетаскивание мыши влево / вниз поворачивает поворотное устройство против часовой стрелки, а перетаскивание мыши вправо / вверх поворачивает поворотное устройство по часовой стрелке. Когда мышь отпущена, курсор мыши устанавливается в исходное положение щелчка. Реализовано так:
void RotaryWidget::mousePressEvent(QMouseEvent *MouseEvent)
{
mMousePos = QCursor::pos();
mPreviousPos = MouseEvent->pos();
setCursor(Qt::BlankCursor);
}
void RotaryWidget::mouseReleaseEvent(QMouseEvent *MouseEvent)
{
QCursor::setPos(mMousePos);
unsetCursor();
}
void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
// Use DeltaPos to move my rotary
mPreviousPos = MouseEvent->pos();
}
Преимущество этого состоит в том, что, когда есть несколько вращающихся в ряд, пользователь быстрее может вносить изменения.
В приведенном выше коде есть ошибка, заключающаяся в том, что, если курсор достигает края экрана, мышь нельзя перемещать, поэтому поворотный элемент не перемещается. Однако пользователь не может видеть курсор, поэтому это проблема. Я изменился mouseMoveEvent
починить это:
void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
if(MouseEvent->globalPos() == mMousePos)
{
mPreviousPos = mapFromGlobal(mMousePos);
return;
}
else
{
QCursor::setPos(mMousePos);
}
QPoint DeltaPos = MouseEvent->pos() - mPreviousPos;
// Use DeltaPos to move my rotary
mPreviousPos = MouseEvent->pos();
}
По сути, каждый раз, когда мышь перемещается, вычисляется изменение, а затем курсор возвращается в исходное положение нажатия (чтобы он никогда не мог исчезнуть с экрана). if
вверху убедитесь, что мы не будем постоянно устанавливать положение мыши в исходное положение снова и снова.
Это прекрасно работает на устройствах без сенсорного экрана, но на устройствах с сенсорным экраном, QCursor::setPos()
не работает, потому что я не могу программно установить положение пальца на экране!
Я не смог придумать решение, которое удовлетворяло бы всем требованиям, которые я описал. Если бы был способ определить, использует ли пользователь сенсорный экран, это можно было бы исправить, но я не могу найти такую функцию в Qt.
Вместо того, чтобы пытаться навести мышь на позицию щелчка, вы можете проверить, находится ли мышь на краю или за краем, и если это так, используйте постоянное приращение для дельты (последнее движение):
void RotaryWidget::mouseMoveEvent(QMouseEvent *MouseEvent)
{
QPoint DeltaPos;
if(!isInsideWindow(MouseEvent))
{
DeltaPos = mPrevDeltaPos;
}
else
{
DeltaPos = MouseEvent->pos() - mPreviousPos;
mPrevDeltaPos = DeltaPos;
// Use DeltaPos to move my rotary
mPreviousPos = MouseEvent->pos();
}
}
РЕДАКТИРОВАТЬ:
Другим вариантом будет вычисление базы DeltaPos по глобальным координатам мыши, а не по локальным координатам относительно окна 0 — поскольку интерес представляет только разница между двумя координатами мыши, положение не нужно привязывать к окну. В этом случае виджет будет работать как на сенсорном, так и на управляемом мышью экране, как и предполагалось — независимо от того, как курсор расположен относительно оконной рамы, одинаковые движения мыши / пальца изменят ориентацию одинаково.
Других решений пока нет …