2016-09-26 720 views
1

我使用pyqtgraph庫進行繪圖。我非常喜歡情節上的鼠標交互(縮放,平移,...)。pyqtgraph自定義縮放問題

對於我的一些情節,我想在滾動鼠標滾輪時更改縮放行爲。標準實現是同時在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

不幸的是一條錯誤消息,在每一個鼠標滾輪彈出事件:

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

我collegue指出,我有要重寫wheelEvent功能時添加self作爲第一個參數:

# 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] -> ...