2016-09-26 7 views
1

Я использую библиотеку pyqtgraph для построения графика. Мне очень нравится взаимодействие с мышью на сюжете (зум, панорама, ...).pyqtgraph custom scaling issue

Для некоторых моих участков я хотел бы изменить поведение зума при прокрутке колесика мыши. Стандартная реализация представляет собой масштабирование как в x, так и в направлении y одновременно. Масштабирование в направлении x не имеет смысла на этих графиках, поэтому я хотел бы отключить это. Я попытался следующие:

################################################################### 
#                 # 
#      PLOTTING A LIVE GRAPH      # 
#     ----------------------------     # 
#                 # 
################################################################### 

import sys 
import os 
from PyQt4 import QtGui 
from PyQt4 import QtCore 
import pyqtgraph as pg 
import numpy as np 

# Override the pg.ViewBox class to add custom 
# implementations to the wheelEvent 
class CustomViewBox(pg.ViewBox): 
    def __init__(self, *args, **kwds): 
     pg.ViewBox.__init__(self, *args, **kwds) 
     #self.setMouseMode(self.RectMode) 


    def wheelEvent(self, ev, axis=None): 
     # 1. Pass on the wheelevent to the superclass, such 
     # that the standard zoomoperation can be executed. 
     pg.ViewBox.wheelEvent(ev,axis) 

     # 2. Reset the x-axis to its original limits 
     # 
     # [code not yet written] 
     # 

class CustomMainWindow(QtGui.QMainWindow): 

    def __init__(self): 

     super(CustomMainWindow, self).__init__() 

     # 1. Define look and feel of this window 
     self.setGeometry(300, 300, 800, 400) 
     self.setWindowTitle("pyqtgraph example") 

     self.FRAME_A = QtGui.QFrame(self) 
     self.FRAME_A.setStyleSheet("QWidget { background-color: %s }" % QtGui.QColor(210,210,235,255).name()) 
     self.LAYOUT_A = QtGui.QHBoxLayout() 
     self.FRAME_A.setLayout(self.LAYOUT_A) 
     self.setCentralWidget(self.FRAME_A) 

     # 2. Create the PlotWidget(QGraphicsView) 
     # ---------------------------------------- 
     self.vb = CustomViewBox() 
     self.plotWidget = pg.PlotWidget(viewBox=self.vb, name='myPlotWidget') 
     self.LAYOUT_A.addWidget(self.plotWidget) 
     self.plotWidget.setLabel('left', 'Value', units='V') 
     self.plotWidget.setLabel('bottom', 'Time', units='s') 
     self.plotWidget.setXRange(0, 10) 
     self.plotWidget.setYRange(0, 100) 

     # 3. Get the PlotItem from the PlotWidget 
     # ---------------------------------------- 
     self.plotItem = self.plotWidget.getPlotItem() 

     # 4. Get the PlotDataItem from the PlotItem 
     # ------------------------------------------ 
     # The plot() function adds a new plot and returns it. 
     # The function can be called on self.plotWidget or self.plotItem 
     self.plotDataItem = self.plotItem.plot() 
     self.plotDataItem.setPen((255, 240, 240)) 
     self.plotDataItem.setShadowPen(pg.mkPen((70, 70, 30), width=2, cosmetic=True)) 


     # 5. Create the x and y arrays 
     # ----------------------------- 
     n = np.linspace(0, 499, 500) 
     self.y = 50 + 5 * (np.sin(n/8.3)) + 7 * (np.sin(n/7.5)) - 5 * (np.sin(n/1.5)) 
     self.x = 10 * n/len(n) 
     self.plotDataItem.setData(x=self.x, y=self.y) 

     self.show() 


if __name__== '__main__': 
    app = QtGui.QApplication(sys.argv) 
    QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Plastique')) 
    myGUI = CustomMainWindow() 


    sys.exit(app.exec_()) 

Просто скопируйте и вставьте этот код в новый файл Python, и вы должны получить следующий вывод:

enter image description here

К сожалению сообщение об ошибке выскакивает на каждом MouseWheel событие:

Traceback (most recent call last): 
    File "pyTest.py", line 26, in wheelEvent 
    pg.ViewBox.wheelEvent(ev,axis) 
    File "C:\Anaconda3\lib\site-packages\pyqtgraph\graphicsItems\ViewBox\ViewBox.py", line 1206, in wheelEvent 
    mask = np.array(self.state['mouseEnabled'], dtype=np.float) 
AttributeError: 'QGraphicsSceneWheelEvent' object has no attribute 'state' 

Моя система выглядит следующим образом:

версия
  • Python: 3.5.2
  • PyQt версия: 4.11.4
  • Qt версия: 4.8.7
  • версия pyqtgraph: 0.9.10

ответ

1

Мой коллега отметил, что у меня есть добавить self в качестве первого аргумента при переопределении функции wheelEvent:

# Override the pg.ViewBox class to add custom 
# implementations to the wheelEvent 
class CustomViewBox(pg.ViewBox): 
    def __init__(self, *args, **kwds): 
     pg.ViewBox.__init__(self, *args, **kwds) 
     #self.setMouseMode(self.RectMode) 


    def wheelEvent(self, ev, axis=None): 
     print(str(self.viewRange())) 

     # 1. Pass on the wheelevent to the superclass, such 
     # that the standard zoomoperation can be executed. 
     pg.ViewBox.wheelEvent(self,ev,axis) # <- To override the function 
               properly, one should add 
               'self' as first argument 

     # 2. Reset the x-axis to its original limits 
     self.setXRange(0,10) 

Теперь она работает. Но единственным недостатком является следующая строка кода:

# 2. Reset the x-axis to its original limits 
    self.setXRange(0,10) 

Было бы лучше, чтобы сделать это:

def wheelEvent(self, ev, axis=None): 
    # 1. Determine initial x-range 
    initialRange = self.viewRange() 

    # 2. Call the superclass method for zooming in 
    pg.ViewBox.wheelEvent(self,ev,axis) 

    # 3. Reset the x-axis to its original limits 
    self.setXRange(initialRange[0][0],initialRange[0][1]) 

Проблема заключается в том, что функция self.viewRange() не возвращает [0,10], но [- 0,37, 10,37]. ViewBox добавляет некоторый запас слева и справа. Если вы продолжаете это делать, в конечном итоге эти поля будут со временем меняться: [-0.37, 10.37] -> [-0.74, 10.74] -> ...