добавление QGraphicsLineItem в Scene / View в pyqt / pyqtgraph - PullRequest
2 голосов
/ 25 марта 2020

Я пытаюсь создать собственную границу для графа в pyqtgraph. Я делаю это, добавляя QGraphicsLineItem к сцене / графическому представлению (ViewBox в pyqtgraph), но у меня проблемы с любым подходом. Добавление 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)

enter image description here enter image description here

Я видел, что GraphicsView обрабатывает все изменения размера, и пытался добавить элемент непосредственно в GraphicView:

upperplot.getViewBox().addItem(topline)

работает, за исключением того, что линия теперь сосредоточена вокруг Y = 0 , не сверху слева. Интересно, что с осью X все в порядке.

enter image description here

Мне кажется, что это простое решение, но я не могу найти ответ на этот вопрос - я не уверен если это проблема с отображением Scene в View или с выравниванием сцены в окне просмотра, но у меня не было успехов с этим. Любая помощь будет высоко ценится.

Минимальный воспроизводимый пример:

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)

дает:

enter image description here

вместо:

enter image description here

1 Ответ

1 голос
/ 25 марта 2020

Одним из возможных решений является реализация пользовательского 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>
)
...