PySide:无法让QPainter()保存状态并在新paintEvent中恢复

2 投票
2 回答
1063 浏览
提问于 2025-04-17 07:56

我正在尝试用PySide制作一个非常简单的图像创建工具。但是在绘制东西时遇到了一些麻烦。

这是我脚本中负责绘图区域的部分:

class Area(QWidget):

   global x1
   global y1
   global x2
   global y2
   try:
      x1
   except NameError:
      x1=0
   try:
      y1
   except NameError:
      y1=0

   try:
      x2
   except NameError:
      x2=100
   try:
      y2
   except NameError:
      y2=100

   def mousePressEvent(self, me):
      global x1     
      global y1
      x1 = me.x()
      y1 = me.y()

   def mouseMoveEvent(self, mo):
      global x2
      global y2
      x2 = mo.x()
      y2 = mo.y()
      self.update()

   def paintEvent(self, pe):
      global paint
      paint = QPainter()
      paint.begin(self)
      paint.drawLine(x1,y1,x2,y2)
      paint.save()
      paint.restore()

blankarea = Area()
blankarea.show()

基本上,这段脚本的作用就是根据鼠标事件来画线。不过,每当鼠标点击事件发生时(也就是开始画线的时候),它会把之前画的线给擦掉,即使我使用了QPainter.save()和QPainter.restore()。这可能是什么原因呢?

2 个回答

1

你为什么要在一个 QWidget 上进行绘图呢?明明有整个 图形视图框架 可以使用呢?

下面是一个简单的画线的例子:

from PySide import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.view = View(self)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.view)

class View(QtGui.QGraphicsView):
    def __init__(self, parent):
        QtGui.QGraphicsView.__init__(self, parent)
        self.setScene(QtGui.QGraphicsScene(self))
        self.setSceneRect(QtCore.QRectF(self.viewport().rect()))

    def mousePressEvent(self, event):
        self._start = event.pos()

    def mouseReleaseEvent(self, event):
        start = QtCore.QPointF(self.mapToScene(self._start))
        end = QtCore.QPointF(self.mapToScene(event.pos()))
        self.scene().addItem(
            QtGui.QGraphicsLineItem(QtCore.QLineF(start, end)))

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.resize(640, 480)
    window.show()
    sys.exit(app.exec_())
1

paintEvent()这个方法每次被调用时,都会把整个小部件重新绘制一遍。之前的绘图结果会被新的绘图结果完全覆盖。

如果你想实现你所描述的效果,就需要把所有的点都记录下来,每次都把这些点的完整序列绘制出来。

根据文档的说明:

当绘制事件发生时,更新的区域通常已经被清空,所以你是在小部件的背景上进行绘制。

撰写回答