#python #pyside2 #pyqtgraph
#python #pyside2 #pyqtgraph
Вопрос:
Я использую ImageView для отображения 2D-фрагментов 3D-тома (данные МРТ-сканирования) и хотел бы изменить привязки мыши, чтобы они были более интуитивно понятными для пользователя. По умолчанию колесо мыши изменяет масштаб / масштаб изображения. Вместо этого я хотел бы, чтобы колесо переключалось на следующий / предыдущий фрагмент — для перемещения вперед или назад по серии 2D-изображений, составляющих объем 3D. В документации используется ось z как время — так что там она будет двигаться вперед / назад во времени.
Я не вижу никаких простых методов переопределения событий мыши pyqtgraph, и я не вижу, как это сделать в PySide2. Кажется, в этой виртуальной функции grabMouseEvent() есть подсказки, но я не знаю, как переопределить захват колеса.
Это мой минимальный рабочий код для создания моего окна и 50 кадров данных с шумом 100×100 пикселей:
from PySide2.QtWidgets import QApplication
from PySide2.QtWidgets import QMainWindow
from PySide2.QtWidgets import QWidget
from PySide2.QtWidgets import QHBoxLayout
import pyqtgraph as pg
import numpy as np
import sys
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.cw = QWidget(self)
self.cw.setAutoFillBackground(True)
self.setCentralWidget(self.cw)
self.layout = QHBoxLayout()
self.cw.setLayout(self.layout)
self.DcmImgWidget = MyImageWidget(parent=self)
self.layout.addWidget(self.DcmImgWidget)
self.show()
class MyImageWidget(pg.ImageView):
def __init__(self, parent):
super().__init__()
self._parent = parent
self.ui.histogram.hide()
self.ui.roiBtn.hide()
self.ui.menuBtn.hide()
# 50 frames of 100x100 random noise
img = np.random.normal(size=(50, 100, 100))
self.setImage(img)
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Он очень хорошо прокручивается с помощью полосы прокрутки под изображением.
Как я могу переопределить события колеса мыши в объектах PyQtGraph?
Ответ №1:
Возможное решение состоит в том, чтобы перехватить событие колеса GraphicsView через фильтр событий и предотвратить передачу события, а затем использовать информацию о событии для выдачи сигнала, указывающего, переходить ли на следующую страницу или на предыдущую.
import sys
from PySide2.QtCore import QObject, QEvent, Signal
from PySide2.QtWidgets import (
QApplication,
QHBoxLayout,
QMainWindow,
QWidget,
)
import pyqtgraph as pg
import numpy as np
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.DcmImgWidget = MyImageWidget()
self.cw = QWidget()
self.cw.setAutoFillBackground(True)
self.setCentralWidget(self.cw)
layout = QHBoxLayout(self.cw)
layout.addWidget(self.DcmImgWidget)
class Helper(QObject):
changed = Signal(bool)
def __init__(self, widget):
super().__init__(widget)
self._widget = widget
self.widget.installEventFilter(self)
@property
def widget(self):
return self._widget
def eventFilter(self, obj, event):
if obj is self.widget and event.type() == QEvent.Wheel:
self.changed.emit(event.angleDelta().y() > 0)
return True
return super().eventFilter(obj, event)
class MyImageWidget(pg.ImageView):
def __init__(self, parent=None):
super().__init__(parent)
self.ui.histogram.hide()
self.ui.roiBtn.hide()
self.ui.menuBtn.hide()
# 50 frames of 100x100 random noise
img = np.random.normal(size=(50, 100, 100))
self.setImage(img)
gv = self.ui.graphicsView
helper = Helper(gv.viewport())
helper.changed.connect(self.change_page)
def change_page(self, state):
self.jumpFrames(1 if state else -1)
def main():
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Комментарии:
1. Спасибо! Мне потребовалось некоторое время, чтобы посмотреть, что вы там сделали — позвольте мне проверить мое понимание — вспомогательная функция создает новый сигнал «изменен», который используется, когда событие колеса мыши поступает в «eventFilter». Затем ‘self.changed.emit’ передает результат bool ‘(event.angleDelta().y() > 0)’ в качестве аргумента подключенному методу ‘change_page’. Итак, чтобы фиксировать и обрабатывать щелчки мыши и перетаскивания, я предполагаю, что я должен создать новый сигнал, условия eventFilter и соответствующий метод slot в ‘MyImageWidget’ …?