【问题标题】:pyqt5 drawing lines with a button on a QGraphicsScenepyqt5 在 QGraphicsScene 上使用按钮绘制线条
【发布时间】:2020-05-04 16:35:12
【问题描述】:

我对 pyqt5 有疑问。我创建了一个带有背景图像的场景的窗口,重新实现了drawBackground。我还有一个按钮,允许我在场景中的某个位置添加一条线。问题是,如果我单击按钮来绘制线条,那么这条线将在具有自己背景的单独场景中绘制,而不是在我拥有的场景中绘制。似乎它创建了一个新场景来画线。这是我的代码:

import sys

from PyQt5 import QtGui
from PyQt5.QtGui import QImage
from PyQt5.QtWidgets import (QMainWindow, QGraphicsView, QPushButton, 
    QHBoxLayout, QVBoxLayout, QWidget, QApplication, QGraphicsScene)

class GraphicsScene(QGraphicsScene):

  def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self._image = QImage()

  @property
  def image(self):
    return self._image

  @image.setter
  def image(self, img):
    self._image = img
    self.update()

  def drawBackground(self, painter, rect):
    if self.image.isNull():
      super().drawBackground(painter, rect)
    else:
      painter.drawImage(rect, self._image)

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.title = "parcelDeliveryIta";
        self.top = 100
        self.left = 100
        self.width = 1500
        self.height = 900
        self.initUI()

    def initUI(self):

        self.scene = GraphicsScene(self)
        self.scene._image = QImage('Italy.png')
        view = QGraphicsView(self.scene, self)
        self.scene.setSceneRect(0, 0, view.width(), view.height())

        addLine = QPushButton('AddLine')
        addLine.clicked.connect(self.addLine)

        hbox = QHBoxLayout(self)
        hbox.addWidget(view)

        vbox = QVBoxLayout(self)
        vbox.addWidget(addLine)

        hbox.addLayout(vbox)

        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.setFixedSize(self.width, self.height)
        self.setLayout(hbox)
        self.show()

    def addLine(self):
        self.scene.addLine(0, 0, 100, 100)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

这是点击按钮时的结果:

可以看到,线条是用自己的背景绘制的,即我设置为场景背景的图像(上面的图像被裁剪以更好地显示线条) 感谢您的帮助。

【问题讨论】:

  • 你为什么说这条线是在一个单独的场景中绘制的,有它自己的背景,而不是在场景中?,除了显示该行为的图像之外,你能否展示该行为的图像?提供minimal reproducible example
  • 我已经修改了帖子,现在代码可以执行了,我还添加了一张显示问题的图片。感谢您的帮助!

标签: python qt pyqt5 qgraphicsview qgraphicsscene


【解决方案1】:

说明:

my previous solution 似乎不适合您的情况,因为the docs 指出:

void QGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)

使用painter绘制场景的背景, 在任何项目之前和前景被绘制。重新实现这个 功能为场景提供自定义背景。

所有的绘画都是在场景坐标中完成的。 rect参数是 暴露的矩形。

如果您只想为 背景,你可以调用 setBackgroundBrush() 代替。

另见 drawForeground() 和 drawItems()。

(强调我的)

该绘制也将用于绘制项目的底部,因此会导致该行为。


解决方案:

因此您将不得不求助于另一种解决方案,例如使用 QGraphicsPixmapItem 作为基础并使用该信息重新调整窗口的大小:

import sys

from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (
    QGraphicsView,
    QPushButton,
    QHBoxLayout,
    QVBoxLayout,
    QWidget,
    QApplication,
    QGraphicsScene,
)


class GraphicsView(QGraphicsView):
    def __init__(self, parent=None):
        super().__init__(parent)
        scene = QGraphicsScene(self)
        self.setScene(scene)
        self._pixmap_item = self.scene().addPixmap(QPixmap())
        self._pixmap_item.setZValue(-1)

    @property
    def pixmap(self):
        return self._pixmap_item.pixmap()

    @pixmap.setter
    def pixmap(self, pixmap):
        self._pixmap_item.setPixmap(pixmap)
        self.scene().setSceneRect(self._pixmap_item.boundingRect())

    def resizeEvent(self, event):
        if not self._pixmap_item.pixmap().isNull():
            self.fitInView(self._pixmap_item)
        super().resizeEvent(event)


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.title = "parcelDeliveryIta"
        self.top = 100
        self.left = 100
        self.width = 1500
        self.height = 900
        self.initUI()

    def initUI(self):

        self.view = GraphicsView(self)
        self.view.pixmap = QPixmap("Italy.png")

        addLine = QPushButton("AddLine")
        addLine.clicked.connect(self.addLine)

        hbox = QHBoxLayout(self)
        hbox.addWidget(self.view)

        vbox = QVBoxLayout()
        vbox.addWidget(addLine)

        hbox.addLayout(vbox)

        self.setWindowTitle(self.title)
        self.setGeometry(self.top, self.left, self.width, self.height)
        self.setFixedSize(self.width, self.height)
        self.show()

    def addLine(self):
        self.view.scene().addLine(0, 0, 100, 100)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())

【讨论】:

  • 谢谢伙计,你救了我的命 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-02
  • 2018-10-01
  • 2018-06-06
相关资源
最近更新 更多