如何修改现有的由QT设计器生成的PlotWidget的viewbox?

问题描述 投票:0回答:1

我需要从图中选择并获取两个图形的数据,我找到了一个示例,其中创建了一个自定义视图框,然后创建一个像 pw = pg.PlotWidget(viewBox=vb) 这样的图,但是我不知道当我们将绘图作为 Qt Creator 推广的 pyqtgraph 小部件时,如何做到这一点。下面是我在论坛中找到的示例(链接:https://groups.google.com/forum/#!topic/pyqtgraph/pTrem1RCKSw) 这是代码(完美运行)

import numpy as np
import pyqtgraph as pg
from pyqtgraph.Point import Point
from pyqtgraph.graphicsItems.ItemGroup import ItemGroup
from pyqtgraph.Qt import QtGui, QtCore
from matplotlib.mlab import inside_poly
from pyqtgraph.graphicsItems import ScatterPlotItem


class ChildGroup(ItemGroup):
    sigItemsChanged = QtCore.Signal()
    def __init__(self, parent):
        ItemGroup.__init__(self, parent)
        # excempt from telling view when transform changes
        self._GraphicsObject__inform_view_on_change = False
    def itemChange(self, change, value):
        ret = ItemGroup.itemChange(self, change, value)
        if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange:
            self.sigItemsChanged.emit()   
        return ret

class MyViewBox(pg.ViewBox):
      
    def mouseDragEvent(self, ev):
        
        if ev.button() == QtCore.Qt.RightButton:
            ev.ignore()    
        else:
            pg.ViewBox.mouseDragEvent(self, ev)
         
        ev.accept() 
        pos = ev.pos()
        if ev.button() == QtCore.Qt.RightButton:
            
            if ev.isFinish():  
                self.rbScaleBox.hide()
                self.ax = QtCore.QRectF(Point(ev.buttonDownPos(ev.button())), Point(pos))
                self.ax = self.childGroup.mapRectFromParent(self.ax) 
                self.Coords =  self.ax.getCoords()  
                self.getdataInRect()
                self.changePointsColors()
            else:
                self.updateScaleBox(ev.buttonDownPos(), ev.pos())
           
    def getdataInRect(self):
        # Get the data from the Graphicsitem
        self.getDataItem()
        x = self.dataxy[0]
        y = self.dataxy[1]
        # Rect Edges
        Xbl = (self.Coords[0],self.Coords[1]) # bottom left
        Xbr = (self.Coords[2],self.Coords[1]) # bottom right
        Xtr = (self.Coords[2],self.Coords[3]) # top right
        Xtl = (self.Coords[0],self.Coords[3]) # top left
        #Make a list of [(x0,y0),(x1,y1) ...]
        self.xy = list()
        for i in x:
                tmp = (x[i],y[i])
                self.xy.append(tmp)            
        self.insideIndex = inside_poly(self.xy,[Xbl, Xbr, Xtr, Xtl])    
                 
    def getDataItem(self):
        
        self.ObjItemList = pg.GraphicsScene.items(self.scene(),self.ax)
        self.dataxy = self.ObjItemList[0].listDataItems()[0].getData()
       
    def changePointsColors(self):
        
        print(self.xy)
        print(self.insideIndex)
                  
app = QtGui.QApplication([])
mw = QtGui.QMainWindow()
mw.resize(800,500)
mw.show()

vb = MyViewBox()
pw = pg.PlotWidget(viewBox=vb) 

a  = np.array([0,1,2,3,4,5,6,7,8,9,10])
b  = np.array([0,1,2,3,4,5,6,7,8,9,10])

curve0 = pw.plot(a,b, clickable=True, symbol = '+')

mw.setCentralWidget(pw)

# Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

如何将之前的代码改编为 PlotWidget“Plot1”?

class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
    pg.setConfigOption('background', 'w')
    QtWidgets.QMainWindow.__init__(self)
    Ui_MainWindow.__init__(self)
    self.setupUi(self)

    self.Plot1.plotItem.showGrid(True, True, 0.7)

    self.Plot1.setLabel('left', 'q1')
    self.Plot1.setLabel('bottom', 'Time', units='s')
    self.Plot1.setTitle(title='q1')

    pen = pg.mkPen({'color': "FF0000", 'width': 2})
    pen1 = pg.mkPen({'color': "00FF00", 'width': 2})
    self.Plot1.addLegend()
    self.q1z = self.Plot1.plot(pen = pen, name = 'Trace 1')
    self.q1k = self.Plot1.plot(pen = pen1, name = 'Trace 2')

这里是文件 Sample.ui

有人可以帮助我吗?

python pyqt pyqt5 qt-designer pyqtgraph
1个回答
1
投票

解决方案是创建一个继承自 PlotWidget 的类,并具有一个到 MyViewBox 的视图框,然后提升该小部件:

plotwidget.py

import numpy as np

import pyqtgraph as pg
from pyqtgraph.Qt import QtGui, QtCore


try:
    from matplotlib.mlab import inside_poly
except ImportError:
    # https://matplotlib.org/3.1.0/api/api_changes.html
    # mlab.inside_poly has been removed in matplotlib 3.1.0
    from matplotlib.path import Path

    def inside_poly(points, verts):
        poly = Path(verts)
        return [idx for idx, p in enumerate(points) if poly.contains_point(p)]


class ChildGroup(pg.ItemGroup):
    sigItemsChanged = QtCore.Signal()

    def __init__(self, parent):
        super(ChildGroup, self).__init__(parent)
        # excempt from telling view when transform changes
        self._GraphicsObject__inform_view_on_change = False

    def itemChange(self, change, value):
        ret = ItemGroup.itemChange(self, change, value)
        if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange:
            self.sigItemsChanged.emit()
        return ret


class MyViewBox(pg.ViewBox):
    def mouseDragEvent(self, ev):

        if ev.button() == QtCore.Qt.RightButton:
            ev.ignore()
        else:
            pg.ViewBox.mouseDragEvent(self, ev)

        ev.accept()
        pos = ev.pos()
        if ev.button() == QtCore.Qt.RightButton:
            if ev.isFinish():
                self.rbScaleBox.hide()
                self.ax = QtCore.QRectF(
                    pg.Point(ev.buttonDownPos(ev.button())), pg.Point(pos)
                )
                self.ax = self.childGroup.mapRectFromParent(self.ax)
                self.Coords = self.ax.getCoords()
                self.getdataInRect()
                self.changePointsColors()
            else:
                self.updateScaleBox(ev.buttonDownPos(), ev.pos())

    def getdataInRect(self):
        # Get the data from the Graphicsitem
        self.getDataItem()
        x = self.dataxy[0]
        y = self.dataxy[1]
        # Rect Edges
        Xbl = (self.Coords[0], self.Coords[1])  # bottom left
        Xbr = (self.Coords[2], self.Coords[1])  # bottom right
        Xtr = (self.Coords[2], self.Coords[3])  # top right
        Xtl = (self.Coords[0], self.Coords[3])  # top left
        # Make a list of [(x0,y0),(x1,y1) ...]
        self.xy = list()
        for i in x:
            tmp = (x[i], y[i])
            self.xy.append(tmp)
        self.insideIndex = inside_poly(self.xy, [Xbl, Xbr, Xtr, Xtl])

    def getDataItem(self):

        self.ObjItemList = pg.GraphicsScene.items(self.scene(), self.ax)
        self.dataxy = self.ObjItemList[0].listDataItems()[0].getData()

    def changePointsColors(self):
        print(self.xy)
        print(self.insideIndex)


class MyPlotWidget(pg.PlotWidget):
    def __init__(self, parent=None):
        super(MyPlotWidget, self).__init__(parent, viewBox=MyViewBox())

示例.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>487</width>
    <height>368</height>
   </rect>
  </property>
  <property name="palette">
   <palette>
    <active>
     <colorrole role="Base">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>255</red>
        <green>255</green>
        <blue>255</blue>
       </color>
      </brush>
     </colorrole>
     <colorrole role="Window">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>86</red>
        <green>86</green>
        <blue>86</blue>
       </color>
      </brush>
     </colorrole>
    </active>
    <inactive>
     <colorrole role="Base">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>255</red>
        <green>255</green>
        <blue>255</blue>
       </color>
      </brush>
     </colorrole>
     <colorrole role="Window">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>86</red>
        <green>86</green>
        <blue>86</blue>
       </color>
      </brush>
     </colorrole>
    </inactive>
    <disabled>
     <colorrole role="Base">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>86</red>
        <green>86</green>
        <blue>86</blue>
       </color>
      </brush>
     </colorrole>
     <colorrole role="Window">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>86</red>
        <green>86</green>
        <blue>86</blue>
       </color>
      </brush>
     </colorrole>
    </disabled>
   </palette>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <property name="leftMargin">
    <number>30</number>
   </property>
   <property name="topMargin">
    <number>40</number>
   </property>
   <property name="rightMargin">
    <number>40</number>
   </property>
   <property name="bottomMargin">
    <number>30</number>
   </property>
   <item>
    <widget class="MyPlotWidget" name="Plot1">
     <property name="autoFillBackground">
      <bool>false</bool>
     </property>
     <property name="backgroundBrush">
      <brush brushstyle="SolidPattern">
       <color alpha="255">
        <red>0</red>
        <green>0</green>
        <blue>0</blue>
       </color>
      </brush>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>MyPlotWidget</class>
   <extends>QGraphicsView</extends>
   <header>plotwidget</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>
pyuic5 Sample.ui -o sample.py -x

main.py

from PyQt5 import QtWidgets

import pyqtgraph as pg

from sample import Ui_Dialog


class MyApp(QtWidgets.QDialog, Ui_Dialog):
    def __init__(self, parent=None):
        super(MyApp, self).__init__(parent)
        pg.setConfigOption("background", "w")
        self.setupUi(self)
        self.Plot1.plotItem.showGrid(True, True, 0.7)
        self.Plot1.setLabel("left", "q1")
        self.Plot1.setLabel("bottom", "Time", units="s")
        self.Plot1.setTitle(title="q1")

        pen = pg.mkPen({"color": "FF0000", "width": 2})
        pen1 = pg.mkPen({"color": "00FF00", "width": 2})
        self.Plot1.addLegend()
        self.q1z = self.Plot1.plot(pen=pen, name="Trace 1")
        self.q1k = self.Plot1.plot(pen=pen1, name="Trace 2")


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MyApp()
    w.show()
    sys.exit(app.exec_())
├── main.py
├── plotwidget.py
├── sample.py
└── Sample.ui
© www.soinside.com 2019 - 2024. All rights reserved.