在 pyqt/pyqtgraph 中将 QGraphicsLineItem 添加到 Scene/View
adding QGraphicsLineItem to Scene/View in pyqt / pyqtgraph
我正在尝试为 pyqtgraph 中的图形制作自定义边框。我这样做是通过将 QGraphicsLineItem 添加到场景/图形视图(pyqtgraph 中的 ViewBox),但是这两种方法都遇到了麻烦。将 QGraphicsLineItem 添加到场景中可以得到我想要的结果(围绕顶部和右侧轴的边框),但它不会缩放:
upperplot = graphics_layout_widget.addPlot(0, 0, 1, 1)
self.curve_upper = upperplot.plot(np.linspace(0,0,8192),
np.linspace(0,0,8192), # loaded_file.data.vm_array[0]
pen=plotpen)
tl = upperplot.getViewBox().boundingRect().topLeft()
tr = upperplot.getViewBox().boundingRect().topRight()
topline = QtGui.QGraphicsLineItem(tl.x(), tl.y(), tr.x(), tr.y())
topline.setParentItem(upperplot.getViewBox())
topline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
upperplot.getViewBox().scene().addItem(topline)
我看到 GraphicsView 处理所有大小调整,并尝试将项目直接添加到 GraphicView:
upperplot.getViewBox().addItem(topline)
除了该行现在以 Y = 0 为中心,而不是左上角外,其他都有效。有趣的是X轴没问题。
我觉得这是一个简单的解决方案,但我一生都找不到答案 - 我不确定将场景映射到视图或视图框中的场景对齐是否有问题,但我已经两者都没有成功。任何帮助将不胜感激。
最小可重现示例:
from PyQt5 import QtWidgets, QtGui
import pyqtgraph as pg
import numpy as np
class UiMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(UiMainWindow, self).__init__()
# set mainwindow + widgets
self.mainwidget = QtWidgets.QWidget(self)
self.mainwidget_gridlayout = QtWidgets.QGridLayout(self.mainwidget)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainwidget_gridlayout)
self.graphics_layout_widget = pg.GraphicsLayoutWidget() # contains a graphicsview
self.graphics_layout_widget.setBackground('w')
pg.setConfigOption('foreground', 'k')
self.mainwidget_gridlayout.addWidget(self.graphics_layout_widget)
# make plot
plotpen = pg.mkPen(color='k', width=1)
self.upperplot = self.graphics_layout_widget.addPlot(0, 0, 1, 1)
self.curve_upper = self.upperplot.plot(np.linspace(0, 100, 8192),
np.linspace(0, 0, 8192),
pen=plotpen)
# draw top border line
QtWidgets.QApplication.processEvents() # I could not get the boundingRect of the ViewBox without drawing first
tl = self.upperplot.getViewBox().boundingRect().topLeft()
tr = self.upperplot.getViewBox().boundingRect().topRight()
br = self.upperplot.getViewBox().boundingRect().bottomRight()
topline = QtGui.QGraphicsLineItem(tl.x(), tl.y(), tr.x(), tr.y())
topline.setParentItem(self.upperplot.getViewBox())
topline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
rightline = QtGui.QGraphicsLineItem(tr.x(), tr.y(), br.x(), br.y())
rightline.setParentItem(self.upperplot.getViewBox())
rightline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
self.upperplot.getViewBox().addItem(topline) # correct scaling, but Y axis is centered as zero
self.upperplot.getViewBox().addItem(rightline)
# vs
# self.upperplot.getViewBox().scene().addItem(topline) # correct position, but cannot scale
# self.upperplot.getViewBox().scene().addItem(rightline)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mw = UiMainWindow()
mw.show()
sys.exit(app.exec_())
边界更新:
self.upperplot.getViewBox().setBorder(color=(211, 211, 211), width=10)
给出:
而不是:
一种可能的解决方案是通过自定义绘制来实现自定义 ViewBox:
class CustomViewBox(pg.ViewBox):
def paint(self, p, opt, widget):
super().paint(p, opt, widget)
r = QtCore.QRectF(self.boundingRect())
p.save()
tl = r.topLeft()
tr = r.topRight()
br = r.bottomRight()
pen = pg.mkPen(color=(211, 211, 211), width=10)
p.setPen(pen)
p.drawLine(tl, tr)
p.drawLine(tr, br)
p.restore()
self.upperplot = self.graphics_layout_widget.addPlot(
0, 0, 1, 1, <b>viewBox=CustomViewBox()</b>
)
我正在尝试为 pyqtgraph 中的图形制作自定义边框。我这样做是通过将 QGraphicsLineItem 添加到场景/图形视图(pyqtgraph 中的 ViewBox),但是这两种方法都遇到了麻烦。将 QGraphicsLineItem 添加到场景中可以得到我想要的结果(围绕顶部和右侧轴的边框),但它不会缩放:
upperplot = graphics_layout_widget.addPlot(0, 0, 1, 1)
self.curve_upper = upperplot.plot(np.linspace(0,0,8192),
np.linspace(0,0,8192), # loaded_file.data.vm_array[0]
pen=plotpen)
tl = upperplot.getViewBox().boundingRect().topLeft()
tr = upperplot.getViewBox().boundingRect().topRight()
topline = QtGui.QGraphicsLineItem(tl.x(), tl.y(), tr.x(), tr.y())
topline.setParentItem(upperplot.getViewBox())
topline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
upperplot.getViewBox().scene().addItem(topline)
我看到 GraphicsView 处理所有大小调整,并尝试将项目直接添加到 GraphicView:
upperplot.getViewBox().addItem(topline)
除了该行现在以 Y = 0 为中心,而不是左上角外,其他都有效。有趣的是X轴没问题。
我觉得这是一个简单的解决方案,但我一生都找不到答案 - 我不确定将场景映射到视图或视图框中的场景对齐是否有问题,但我已经两者都没有成功。任何帮助将不胜感激。
最小可重现示例:
from PyQt5 import QtWidgets, QtGui
import pyqtgraph as pg
import numpy as np
class UiMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(UiMainWindow, self).__init__()
# set mainwindow + widgets
self.mainwidget = QtWidgets.QWidget(self)
self.mainwidget_gridlayout = QtWidgets.QGridLayout(self.mainwidget)
self.setCentralWidget(QtGui.QWidget(self))
self.centralWidget().setLayout(self.mainwidget_gridlayout)
self.graphics_layout_widget = pg.GraphicsLayoutWidget() # contains a graphicsview
self.graphics_layout_widget.setBackground('w')
pg.setConfigOption('foreground', 'k')
self.mainwidget_gridlayout.addWidget(self.graphics_layout_widget)
# make plot
plotpen = pg.mkPen(color='k', width=1)
self.upperplot = self.graphics_layout_widget.addPlot(0, 0, 1, 1)
self.curve_upper = self.upperplot.plot(np.linspace(0, 100, 8192),
np.linspace(0, 0, 8192),
pen=plotpen)
# draw top border line
QtWidgets.QApplication.processEvents() # I could not get the boundingRect of the ViewBox without drawing first
tl = self.upperplot.getViewBox().boundingRect().topLeft()
tr = self.upperplot.getViewBox().boundingRect().topRight()
br = self.upperplot.getViewBox().boundingRect().bottomRight()
topline = QtGui.QGraphicsLineItem(tl.x(), tl.y(), tr.x(), tr.y())
topline.setParentItem(self.upperplot.getViewBox())
topline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
rightline = QtGui.QGraphicsLineItem(tr.x(), tr.y(), br.x(), br.y())
rightline.setParentItem(self.upperplot.getViewBox())
rightline.setPen(pg.mkPen(color=(211, 211, 211), width=10))
self.upperplot.getViewBox().addItem(topline) # correct scaling, but Y axis is centered as zero
self.upperplot.getViewBox().addItem(rightline)
# vs
# self.upperplot.getViewBox().scene().addItem(topline) # correct position, but cannot scale
# self.upperplot.getViewBox().scene().addItem(rightline)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mw = UiMainWindow()
mw.show()
sys.exit(app.exec_())
边界更新:
self.upperplot.getViewBox().setBorder(color=(211, 211, 211), width=10)
给出:
而不是:
一种可能的解决方案是通过自定义绘制来实现自定义 ViewBox:
class CustomViewBox(pg.ViewBox):
def paint(self, p, opt, widget):
super().paint(p, opt, widget)
r = QtCore.QRectF(self.boundingRect())
p.save()
tl = r.topLeft()
tr = r.topRight()
br = r.bottomRight()
pen = pg.mkPen(color=(211, 211, 211), width=10)
p.setPen(pen)
p.drawLine(tl, tr)
p.drawLine(tr, br)
p.restore()
self.upperplot = self.graphics_layout_widget.addPlot(
0, 0, 1, 1, <b>viewBox=CustomViewBox()</b>
)