在PyQtGraph中绘制矩形

4

我正试图使用pyqtgraph在由设计师创建的窗口中绘制矩形,以显示2D数组中的数据。是否有一种方法可以绘制矩形并将其保存到2D数组中,以便稍后更新其颜色?我尝试遵循自定义绘图示例,但仍然出现以下错误:

AttributeError: 'QRectF' object has no attribute 'zValue'

def Draw2DSquare(self):
    self.picture = QtGui.QPicture()
    p = QtGui.QPainter(self.picture)
    p.setPen(pg.mkPen('w'))
    p.drawLine(QtCore.QPointF(0, 0), QtCore.QPointF(1, 1))
    p.setBrush(pg.mkBrush('g'))
    p.drawRect(QtCore.QRectF(0, 0, 4.5, 4.5))
    p.end()
    self.graphWidget_2D.addItem(QtCore.QRectF(self.picture.boundingRect()))

我不知道这是否是最好的方法。有更简单的方法画一个矩形吗?

这是我的Python文件:

import time
from PyQt5 import QtWidgets, uic, QtGui, QtCore
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import sys
import numpy as np
from PyQt5.QtGui import QIcon, QKeySequence
from PyQt5.QtWidgets import QAction

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        # Load the UI Page
        uic.loadUi('help.ui', self)
        self.showMaximized()
        self.Draw2DSquare()

    def Draw2DSquare(self):
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('w'))
        p.drawLine(QtCore.QPointF(0, 0), QtCore.QPointF(1, 1))
        p.setBrush(pg.mkBrush('g'))
        p.drawRect(QtCore.QRectF(0, 0, 4.5, 4.5))
        p.end()
        self.graphWidget_2D.addItem(QtCore.QRectF(self.picture.boundingRect()))

def main():
    app = QtWidgets.QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

这是我的 UI 文件,文件名为 help.ui。

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>1120</width>
    <height>833</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout_2">
    <item row="0" column="0">
     <widget class="PlotWidget" name="graphWidget_2D" native="true"/>
    </item>
    <item row="0" column="1">
     <widget class="GLViewWidget" name="graphWidget_3D" native="true"/>
    </item>
    <item row="1" column="0">
     <spacer name="horizontalSpacer">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>40</width>
        <height>20</height>
       </size>
      </property>
     </spacer>
    </item>
    <item row="1" column="1">
     <spacer name="horizontalSpacer_2">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>40</width>
        <height>20</height>
       </size>
      </property>
     </spacer>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>1120</width>
     <height>21</height>
    </rect>
   </property>
   <widget class="QMenu" name="menuFile">
    <property name="title">
     <string>File</string>
    </property>
    <addaction name="actionFile"/>
    <addaction name="actionOpen"/>
    <addaction name="actionSave"/>
    <addaction name="separator"/>
    <addaction name="actionOptions"/>
    <addaction name="separator"/>
    <addaction name="actionExit"/>
   </widget>
   <addaction name="menuFile"/>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
  <action name="actionOpen">
   <property name="text">
    <string>Open</string>
   </property>
  </action>
  <action name="actionFile">
   <property name="text">
    <string>File</string>
   </property>
  </action>
  <action name="actionOptions">
   <property name="text">
    <string>Options</string>
   </property>
  </action>
  <action name="actionSave">
   <property name="text">
    <string>Save</string>
   </property>
  </action>
  <action name="actionExit">
   <property name="text">
    <string>Exit</string>
   </property>
  </action>
 </widget>
 <customwidgets>
  <customwidget>
   <class>PlotWidget</class>
   <extends>QWidget</extends>
   <header>pyqtgraph.h</header>
   <container>1</container>
  </customwidget>
  <customwidget>
   <class>GLViewWidget</class>
   <extends>QWidget</extends>
   <header>pyqtgraph.opengl.h</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

抱歉,我只是为了满足要求而添加了代码。 - user169808
1个回答

3
addItem方法期望传入一个图形项,正如文档所指出的那样:

addItem(item, *args, **kargs)

图形项添加到视图盒中。如果该项具有绘图数据(PlotDataItem、PlotCurveItem、ScatterPlotItem),则可以将其包含在PlotItem执行的分析中。

(强调我的)

但是你传递的是一个不是图形项的QRectF。你可以使用QGraphicsRectItem,但场景的坐标与视图盒的坐标不匹配,因此你需要基于GraphicsObject实现一个自定义图形项(我已经参考了官方示例the official example):

import sys

from PyQt5 import QtCore, QtGui, QtWidgets, uic

import pyqtgraph as pg


class RectItem(pg.GraphicsObject):
    def __init__(self, rect, parent=None):
        super().__init__(parent)
        self._rect = rect
        self.picture = QtGui.QPicture()
        self._generate_picture()

    @property
    def rect(self):
        return self._rect

    def _generate_picture(self):
        painter = QtGui.QPainter(self.picture)
        painter.setPen(pg.mkPen("w"))
        painter.setBrush(pg.mkBrush("g"))
        painter.drawRect(self.rect)
        painter.end()

    def paint(self, painter, option, widget=None):
        painter.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QtCore.QRectF(self.picture.boundingRect())


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # Load the UI Page
        uic.loadUi("help.ui", self)
        self.showMaximized()
        self.draw_2d_square()

    def draw_2d_square(self):
        rect_item = RectItem(QtCore.QRectF(0, 0, 4.5, 4.5))
        self.graphWidget_2D.addItem(rect_item)


def main():
    app = QtWidgets.QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

enter image description here


谢谢,只有一个快速的问题。我该如何将rect_item保存到nump数组中?因为我尝试使用a = np.ones((5,5,5))创建数组并将rect_item保存到a[0][0][0],但它引发了类型错误:float()参数必须是字符串或数字,而不是'RectItem'。谢谢 - user169808
@user169808 rect_item不是数据或数字集合,而是一个允许您绘制矩形元素的对象,我不明白您希望将其转换为numpy后想要做什么。 - eyllanesc
我只想将它保存到一个数组中。使用numpy更方便,但我将创建一个本地的Python数组。 - user169808
正如我所指出的:你不能在numpy中保存一个item,但你可以将QRect保存在一个数组中,因为它是一个数值,可以用来创建一个新的Item,如果你想要恢复它。 - eyllanesc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接