aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2021-04-18 18:58:18 +0200
committerChristian Tismer <tismer@stackless.com>2022-01-24 19:29:23 +0100
commit3c3595e1e196204bfaec8c5f82db7f0fc84a1702 (patch)
treed6f9f64af8feb64c4d09960add362b806dea19b3
parent9b4d1f76128bc46a5ea85d33ce67f81029b8017e (diff)
PyPySide: handle QPainter correctly with GC
While testing the examples with PyPy, a number of examples used QPainter without explicitly calling painter.end() and crashed. This works in standard Python, but leaves the painter open in other implementations, because the implicit deletion of objects when going out of scope does not work in the wrapper when garbage collection is used. Fixed by providing the missing painter.end() calls. This problem should finally be fixed by making QPainter a context manager. The same approach was taken by Python.org and the file open/close functions. The context manager was needed for implementations like IronPython, Jython and PyPy. [ChangeLog][PySide6] The examples were adapted to PyPy's need to close QPainter, explicitly. Eventually, we may turn this into a context manager. Change-Id: I18eeeff7df800bafce91a1e5c98c469aa3bcc41b Pick-to: 6.2 Task-number: PYSIDE-535 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--examples/corelib/threads/mandelbrot.py4
-rw-r--r--examples/designer/taskmenuextension/tictactoe.py3
-rw-r--r--examples/multimedia/audiosource/audiosource.py4
-rw-r--r--examples/quick3d/intro/main.py1
-rw-r--r--examples/widgetbinding/wigglywidget.py3
-rw-r--r--examples/widgets/animation/easing/easing.py1
-rw-r--r--examples/widgets/codeeditor/codeeditor.py3
-rw-r--r--examples/widgets/draganddrop/draggableicons/draggableicons.py3
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.py2
-rw-r--r--examples/widgets/itemviews/stardelegate/stareditor.py2
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing.py2
-rw-r--r--examples/widgets/painting/concentriccircles/concentriccircles.py3
-rw-r--r--examples/widgets/state-machine/rogue/rogue.py2
-rw-r--r--examples/widgets/state-machine/trafficlight/trafficlight.py2
-rw-r--r--examples/widgets/tetrix/tetrix.py4
-rw-r--r--examples/widgets/tutorials/cannon/t10.py2
-rw-r--r--examples/widgets/tutorials/cannon/t11.py2
-rw-r--r--examples/widgets/tutorials/cannon/t12.py2
-rw-r--r--examples/widgets/tutorials/cannon/t13.py2
-rw-r--r--examples/widgets/tutorials/cannon/t14.py2
-rw-r--r--examples/widgets/tutorials/cannon/t8.py2
-rw-r--r--examples/widgets/tutorials/cannon/t9.py2
22 files changed, 53 insertions, 0 deletions
diff --git a/examples/corelib/threads/mandelbrot.py b/examples/corelib/threads/mandelbrot.py
index c95966119..70658dc58 100644
--- a/examples/corelib/threads/mandelbrot.py
+++ b/examples/corelib/threads/mandelbrot.py
@@ -260,6 +260,8 @@ class MandelbrotWidget(QWidget):
painter.setPen(Qt.white)
painter.drawText(self.rect(), Qt.AlignCenter,
"Rendering initial image, please wait...")
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
return
if self._cur_scale == self._pixmap_scale:
@@ -292,6 +294,8 @@ class MandelbrotWidget(QWidget):
painter.setPen(Qt.white)
painter.drawText((self.width() - text_width) / 2,
metrics.leading() + metrics.ascent(), text)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def resizeEvent(self, event):
self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
diff --git a/examples/designer/taskmenuextension/tictactoe.py b/examples/designer/taskmenuextension/tictactoe.py
index ce806426f..c4fe16e10 100644
--- a/examples/designer/taskmenuextension/tictactoe.py
+++ b/examples/designer/taskmenuextension/tictactoe.py
@@ -150,6 +150,9 @@ class TicTacToe(QWidget):
painter.drawLine(0, self.height(), self.width(), 0)
self._turn_number = 9
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
+
def _cell_rect(self, position):
h_margin = self.width() / 30
v_margin = self.height() / 30
diff --git a/examples/multimedia/audiosource/audiosource.py b/examples/multimedia/audiosource/audiosource.py
index d61aaae7e..8f11e5c4b 100644
--- a/examples/multimedia/audiosource/audiosource.py
+++ b/examples/multimedia/audiosource/audiosource.py
@@ -119,12 +119,16 @@ class RenderArea(QWidget):
painter.drawRect(frame)
if self.m_level == 0.0:
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
return
pos: int = round((frame.width() - 1) * self.m_level)
painter.fillRect(
frame.left() + 1, frame.top() + 1, pos, frame.height() - 1, Qt.red
)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
class InputTest(QWidget):
diff --git a/examples/quick3d/intro/main.py b/examples/quick3d/intro/main.py
index 050f9d632..c3189fb23 100644
--- a/examples/quick3d/intro/main.py
+++ b/examples/quick3d/intro/main.py
@@ -38,6 +38,7 @@
##
#############################################################################
+import os
import sys
from pathlib import Path
from PySide6.QtCore import QUrl
diff --git a/examples/widgetbinding/wigglywidget.py b/examples/widgetbinding/wigglywidget.py
index 482415ae6..11f4a81a5 100644
--- a/examples/widgetbinding/wigglywidget.py
+++ b/examples/widgetbinding/wigglywidget.py
@@ -99,6 +99,9 @@ class WigglyWidget(QWidget):
painter.drawText(x, y - dy, str(c))
x += metrics.horizontalAdvance(c)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
+
def timerEvent(self, event):
if event.timerId() == self._timer.timerId():
self._step += 1
diff --git a/examples/widgets/animation/easing/easing.py b/examples/widgets/animation/easing/easing.py
index ba7f2d363..a7bff7842 100644
--- a/examples/widgets/animation/easing/easing.py
+++ b/examples/widgets/animation/easing/easing.py
@@ -218,6 +218,7 @@ class Window(QWidget):
item.setText(curve_name)
self._ui.easingCurvePicker.addItem(item)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
painter.end()
def start_animation(self):
diff --git a/examples/widgets/codeeditor/codeeditor.py b/examples/widgets/codeeditor/codeeditor.py
index f5f119000..bfe92c4a8 100644
--- a/examples/widgets/codeeditor/codeeditor.py
+++ b/examples/widgets/codeeditor/codeeditor.py
@@ -106,6 +106,9 @@ class CodeEditor(QPlainTextEdit):
bottom = top + self.blockBoundingRect(block).height()
block_number += 1
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
+
@Slot()
def update_line_number_area_width(self, newBlockCount):
self.setViewportMargins(self.line_number_area_width(), 0, 0, 0)
diff --git a/examples/widgets/draganddrop/draggableicons/draggableicons.py b/examples/widgets/draganddrop/draggableicons/draggableicons.py
index f8411de2e..5fe6590e7 100644
--- a/examples/widgets/draganddrop/draggableicons/draggableicons.py
+++ b/examples/widgets/draganddrop/draggableicons/draggableicons.py
@@ -152,6 +152,9 @@ class DragWidget(QFrame):
child.show()
child.setPixmap(pixmap)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
+
if __name__ == "__main__":
app = QApplication(sys.argv)
diff --git a/examples/widgets/graphicsview/diagramscene/diagramscene.py b/examples/widgets/graphicsview/diagramscene/diagramscene.py
index b068a8253..aca95ccb9 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramscene.py
+++ b/examples/widgets/graphicsview/diagramscene/diagramscene.py
@@ -242,6 +242,8 @@ class DiagramItem(QGraphicsPolygonItem):
painter.setPen(QPen(Qt.black, 8))
painter.translate(125, 125)
painter.drawPolyline(self._my_polygon)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
return pixmap
def contextMenuEvent(self, event):
diff --git a/examples/widgets/itemviews/stardelegate/stareditor.py b/examples/widgets/itemviews/stardelegate/stareditor.py
index 8431f4a38..9e3a5f4df 100644
--- a/examples/widgets/itemviews/stardelegate/stareditor.py
+++ b/examples/widgets/itemviews/stardelegate/stareditor.py
@@ -72,6 +72,8 @@ class StarEditor(QWidget):
""" Paint the editor, offloading the work to the StarRating class. """
painter = QPainter(self)
self.star_rating.paint(painter, self.rect(), self.palette(), isEditable=True)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def mouseMoveEvent(self, event):
""" As the mouse moves inside the editor, track the position and
diff --git a/examples/widgets/painting/basicdrawing/basicdrawing.py b/examples/widgets/painting/basicdrawing/basicdrawing.py
index d7849b0cc..a0d5bda7c 100644
--- a/examples/widgets/painting/basicdrawing/basicdrawing.py
+++ b/examples/widgets/painting/basicdrawing/basicdrawing.py
@@ -164,6 +164,8 @@ class RenderArea(QWidget):
painter.setPen(self.palette().dark().color())
painter.setBrush(Qt.NoBrush)
painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
id_role = Qt.UserRole
diff --git a/examples/widgets/painting/concentriccircles/concentriccircles.py b/examples/widgets/painting/concentriccircles/concentriccircles.py
index d3df51099..2786396cb 100644
--- a/examples/widgets/painting/concentriccircles/concentriccircles.py
+++ b/examples/widgets/painting/concentriccircles/concentriccircles.py
@@ -95,6 +95,9 @@ class CircleWidget(QWidget):
painter.drawEllipse(QRect(-diameter / 2,
-diameter / 2, diameter, diameter))
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
+
class Window(QWidget):
def __init__(self):
diff --git a/examples/widgets/state-machine/rogue/rogue.py b/examples/widgets/state-machine/rogue/rogue.py
index c8e4565ba..255785f95 100644
--- a/examples/widgets/state-machine/rogue/rogue.py
+++ b/examples/widgets/state-machine/rogue/rogue.py
@@ -180,6 +180,8 @@ class MainWindow(QMainWindow):
painter.drawText(QPoint(x_pos, y_pos), self.map[x][y])
x_pos += font_width
painter.drawText(QPoint(self.pX * font_width, (self.pY + 2) * font_height), '@')
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def move_player(self, direction):
if direction == self.left:
diff --git a/examples/widgets/state-machine/trafficlight/trafficlight.py b/examples/widgets/state-machine/trafficlight/trafficlight.py
index 0d7fcd15c..b5e975cfc 100644
--- a/examples/widgets/state-machine/trafficlight/trafficlight.py
+++ b/examples/widgets/state-machine/trafficlight/trafficlight.py
@@ -78,6 +78,8 @@ class LightWidget(QWidget):
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(self.color)
painter.drawEllipse(0, 0, self.width(), self.height())
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
on = Property(bool, is_on, set_on)
diff --git a/examples/widgets/tetrix/tetrix.py b/examples/widgets/tetrix/tetrix.py
index 3b4d32cca..c70e634b4 100644
--- a/examples/widgets/tetrix/tetrix.py
+++ b/examples/widgets/tetrix/tetrix.py
@@ -236,6 +236,8 @@ class TetrixBoard(QFrame):
self.draw_square(painter, rect.left() + x * self.square_width(),
board_top + (TetrixBoard.board_height - y - 1) * self.square_height(),
self._cur_piece.shape())
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def keyPressEvent(self, event):
if not self._is_started or self._is_paused or self._cur_piece.shape() == Piece.NoShape:
@@ -359,6 +361,8 @@ class TetrixBoard(QFrame):
pixmap = QPixmap(dx * self.square_width(), dy * self.square_height())
painter = QPainter(pixmap)
painter.fillRect(pixmap.rect(), self.nextPieceLabel.palette().background())
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
for int in range(4):
x = self._next_piece.x(i) - self._next_piece.min_x()
diff --git a/examples/widgets/tutorials/cannon/t10.py b/examples/widgets/tutorials/cannon/t10.py
index ed3d9fce3..98b5f57fe 100644
--- a/examples/widgets/tutorials/cannon/t10.py
+++ b/examples/widgets/tutorials/cannon/t10.py
@@ -138,6 +138,8 @@ class CannonField(QWidget):
painter.drawPie(QRect(-35, -35, 70, 70), 0, 90 * 16)
painter.rotate(-self._current_angle)
painter.drawRect(QRect(33, -4, 15, 8))
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def cannon_rect(self):
result = QRect(0, 0, 50, 50)
diff --git a/examples/widgets/tutorials/cannon/t11.py b/examples/widgets/tutorials/cannon/t11.py
index f297a14b4..ea8e53a8e 100644
--- a/examples/widgets/tutorials/cannon/t11.py
+++ b/examples/widgets/tutorials/cannon/t11.py
@@ -164,6 +164,8 @@ class CannonField(QWidget):
self.paint_cannon(painter)
if self._auto_shoot_timer.isActive():
self.paint_shot(painter)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def paint_shot(self, painter):
painter.setPen(Qt.NoPen)
diff --git a/examples/widgets/tutorials/cannon/t12.py b/examples/widgets/tutorials/cannon/t12.py
index f2c6ea08c..98b2ff248 100644
--- a/examples/widgets/tutorials/cannon/t12.py
+++ b/examples/widgets/tutorials/cannon/t12.py
@@ -205,6 +205,8 @@ class CannonField(QWidget):
self.paint_shot(painter)
self.paint_target(painter)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def paint_shot(self, painter):
painter.setPen(Qt.NoPen)
diff --git a/examples/widgets/tutorials/cannon/t13.py b/examples/widgets/tutorials/cannon/t13.py
index aa00825aa..3ac05f435 100644
--- a/examples/widgets/tutorials/cannon/t13.py
+++ b/examples/widgets/tutorials/cannon/t13.py
@@ -232,6 +232,8 @@ class CannonField(QWidget):
self.paint_shot(painter)
if not self._game_ended:
self.paint_target(painter)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def paint_shot(self, painter):
painter.setPen(Qt.NoPen)
diff --git a/examples/widgets/tutorials/cannon/t14.py b/examples/widgets/tutorials/cannon/t14.py
index 0e8318ebe..8a3fe98e8 100644
--- a/examples/widgets/tutorials/cannon/t14.py
+++ b/examples/widgets/tutorials/cannon/t14.py
@@ -256,6 +256,8 @@ class CannonField(QWidget):
self.paint_shot(painter)
if not self._game_ended:
self.paint_target(painter)
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
def paint_shot(self, painter):
painter.setPen(Qt.NoPen)
diff --git a/examples/widgets/tutorials/cannon/t8.py b/examples/widgets/tutorials/cannon/t8.py
index cc54194cf..b02a049cc 100644
--- a/examples/widgets/tutorials/cannon/t8.py
+++ b/examples/widgets/tutorials/cannon/t8.py
@@ -117,6 +117,8 @@ class CannonField(QWidget):
def paintEvent(self, event):
painter = QPainter(self)
painter.drawText(200, 200, f"Angle = {self._current_angle}")
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
class MyWidget(QWidget):
diff --git a/examples/widgets/tutorials/cannon/t9.py b/examples/widgets/tutorials/cannon/t9.py
index 36dcf8fb1..f18144310 100644
--- a/examples/widgets/tutorials/cannon/t9.py
+++ b/examples/widgets/tutorials/cannon/t9.py
@@ -124,6 +124,8 @@ class CannonField(QWidget):
painter.drawPie(QRect(-35, -35, 70, 70), 0, 90 * 16)
painter.rotate(-self._current_angle)
painter.drawRect(QRect(33, -4, 15, 8))
+ # QPainter needs an explicit end() in PyPy. This will become a context manager in 6.3.
+ painter.end()
class MyWidget(QWidget):