Pyqt6 QgraphicsView: Zoom at Mouse Position сбрасывается в центр с индивидуальным панорамированиемPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Pyqt6 QgraphicsView: Zoom at Mouse Position сбрасывается в центр с индивидуальным панорамированием

Сообщение Anonymous »

Описание задачи < /h2>
Я реализую пользовательский pyqt6 qgraphicsview с функциональностью масштабирования и панорамирования. Когда я увеличиваю или выходя, используя колесо мыши, представление правильно масштабируется, но затем немедленно сбрасываюсь на центр сцены вместо того, чтобы поддерживать положение под курсором мыши.import sys
from PyQt6 import QtCore, QtGui, QtWidgets
import math

class CustomGraphicsView(QtWidgets.QGraphicsView):
def __init__(self):
super().__init__()

# Setup scene
self.scene = QtWidgets.QGraphicsScene()
self.setScene(self.scene)

# Add some items to the scene
for i in range(10):
for j in range(10):
rect = QtWidgets.QGraphicsRectItem(i*100, j*100, 50, 50)
self.scene.addItem(rect)

# Center point in red
center = QtWidgets.QGraphicsEllipseItem(-10, -10, 20, 20)
center.setBrush(QtGui.QBrush(QtGui.QColor(255, 0, 0)))
self.scene.addItem(center)

# Zoom settings
self._zoom = 0
self.MAX_ZOOM = 10
self.MIN_ZOOM = -10

# Set very large scene rect
self.setSceneRect(-float("inf"), -float("inf"), float("inf"), float("inf"))

# Configure view
self.setTransformationAnchor(QtWidgets.QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setDragMode(QtWidgets.QGraphicsView.DragMode.RubberBandDrag)
self.setMouseTracking(True)

# Panning settings
self._ctrlLeftDrag = False
self._lastDragPoint = QtCore.QPoint()

# Set initial scrollbar ranges
self.updateScrollBarRanges()

def wheelEvent(self, event: QtGui.QWheelEvent):
zoomInFactor = 1.25
zoomOutFactor = 1 / zoomInFactor

# Get the scene position before scaling
oldPos = self.mapToScene(event.position().toPoint())

# Determine zoom direction
if event.angleDelta().y() > 0:
zoomFactor = zoomInFactor
new_zoom = self._zoom + 1
else:
zoomFactor = zoomOutFactor
new_zoom = self._zoom - 1

# Check zoom limits
if new_zoom > self.MAX_ZOOM or new_zoom < self.MIN_ZOOM:
return

# Apply zoom
self.scale(zoomFactor, zoomFactor)
self._zoom = new_zoom

# Get the new position under mouse after scaling
newPos = self.mapToScene(event.position().toPoint())

# Move scene to delta to keep mouse position fixed
delta = newPos - oldPos
self.translate(delta.x(), delta.y())

# Adjust scrollbar ranges based on zoom level
self.updateScrollBarRanges()

def updateScrollBarRanges(self):
# Get current transform scale
scale = self.transform().m11()

# Base range that stays within 32-bit integer limits
MAX_RANGE = 2000000000

# Calculate new range based on scale
adjusted_range = int(min(MAX_RANGE * (1 / scale), MAX_RANGE))

# Set new ranges for both scrollbars
self.horizontalScrollBar().setRange(-adjusted_range, adjusted_range)
self.verticalScrollBar().setRange(-adjusted_range, adjusted_range)

def mousePressEvent(self, event: QtGui.QMouseEvent):
# Check for Ctrl + Left Button for panning
if (event.modifiers() == QtCore.Qt.KeyboardModifier.ControlModifier and
event.button() == QtCore.Qt.MouseButton.LeftButton):
self._ctrlLeftDrag = True
self._lastDragPoint = event.pos()
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ClosedHandCursor))
event.accept()
return
# Middle mouse button for panning
elif event.button() == QtCore.Qt.MouseButton.MiddleButton:
self._ctrlLeftDrag = True
self._lastDragPoint = event.pos()
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ClosedHandCursor))
event.accept()
return
super().mousePressEvent(event)

def mouseMoveEvent(self, event: QtGui.QMouseEvent):
if self._ctrlLeftDrag:
delta = event.pos() - self._lastDragPoint
self._lastDragPoint = event.pos()

# Use horizontal and vertical scrollbars for smooth scrolling
self.horizontalScrollBar().setValue(
self.horizontalScrollBar().value() - delta.x()
)
self.verticalScrollBar().setValue(
self.verticalScrollBar().value() - delta.y()
)
event.accept()
return
super().mouseMoveEvent(event)

def mouseReleaseEvent(self, event: QtGui.QMouseEvent):
if ((event.button() == QtCore.Qt.MouseButton.LeftButton or
event.button() == QtCore.Qt.MouseButton.MiddleButton) and
self._ctrlLeftDrag):
self._ctrlLeftDrag = False
self.viewport().unsetCursor()
event.accept()
return
super().mouseReleaseEvent(event)

def keyPressEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key.Key_Control:
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.OpenHandCursor))
super().keyPressEvent(event)

def keyReleaseEvent(self, event: QtGui.QKeyEvent):
if event.key() == QtCore.Qt.Key.Key_Control:
self.viewport().unsetCursor()
super().keyReleaseEvent(event)

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
view = CustomGraphicsView()
view.show()
view.resize(800, 600)
sys.exit(app.exec())
< /code>
проблема < /h2>
при запуске этого кода: < /p>
  • Используйте колесо мыши для увеличения или выхода < /li>
    Изначально изначально anchor
What I've Tried
I've attempted several approaches:

[*]Disabling transformation anchors and manually applying translations
[*]Blocking scrollbar signals during range updates
[*]Saving view center points and Восстановление их < /li>
Установка настройки якорями на заказ (в настоящее время используется Anchorundermouse) < /li>
< /ul>
Ни одно из этих решений не сработало - представление все еще сбрасывается в центр сцены после увеличения, в то время как правильно применять уровень Zoom. < /p>
. Необходимо оставаться под положением курсора мыши
[*] Ctrl+левый щелчок и паннинг среднего щелчка должен продолжать работать
[*] Директор прокрутки необходимо обновляться во время увеличения для больших сцен
. /> Вопрос < /h2>
Как я могу реализовать функцию qgraphicsview Zoom, которая поддерживает позицию курсора в качестве точки якоря Zoom без сброса в центр сцены, при правильном обновлении прокрутки диапазоны и сохранения моей пользовательской функциональности? /> pyqt6 6.5.0 < /li>
python 3.10 < /li>
< /ul>
Я заметил, что проблема возникает, когда полосы прокрутки не имеют места прокрутки. < /p.>

Подробнее здесь: https://stackoverflow.com/questions/795 ... omized-pan
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Pyqt6 QgraphicsView: Zoom at Mouse Position сбрасывается в центр с индивидуальным панорамированием
    Anonymous » » в форуме Python
    0 Ответы
    71 Просмотры
    Последнее сообщение Anonymous
  • Vuetify: justify-position/align-position vs justify="position"/align="position"
    Anonymous » » в форуме CSS
    0 Ответы
    75 Просмотры
    Последнее сообщение Anonymous
  • В чем разница в Mouse.OverrideCursor и Mouse.SetCursor
    Anonymous » » в форуме C#
    0 Ответы
    51 Просмотры
    Последнее сообщение Anonymous
  • В чем разница в Mouse.OverrideCursor и Mouse.SetCursor
    Anonymous » » в форуме C#
    0 Ответы
    46 Просмотры
    Последнее сообщение Anonymous
  • Raycast от камеры до Mouse Position в Game World
    Anonymous » » в форуме C#
    0 Ответы
    4 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»