aboutsummaryrefslogtreecommitdiffstats
path: root/examples/corelib/threads/mandelbrot.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/corelib/threads/mandelbrot.py')
-rw-r--r--examples/corelib/threads/mandelbrot.py163
1 files changed, 63 insertions, 100 deletions
diff --git a/examples/corelib/threads/mandelbrot.py b/examples/corelib/threads/mandelbrot.py
index c95966119..4689813d4 100644
--- a/examples/corelib/threads/mandelbrot.py
+++ b/examples/corelib/threads/mandelbrot.py
@@ -1,44 +1,6 @@
-
-#############################################################################
-##
-## Copyright (C) 2013 Riverbank Computing Limited.
-## Copyright (C) 2016 The Qt Company Ltd.
-## Contact: http://www.qt.io/licensing/
-##
-## This file is part of the Qt for Python examples of the Qt Toolkit.
-##
-## $QT_BEGIN_LICENSE:BSD$
-## You may use this file under the terms of the BSD license as follows:
-##
-## "Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions are
-## met:
-## * Redistributions of source code must retain the above copyright
-## notice, this list of conditions and the following disclaimer.
-## * Redistributions in binary form must reproduce the above copyright
-## notice, this list of conditions and the following disclaimer in
-## the documentation and/or other materials provided with the
-## distribution.
-## * Neither the name of The Qt Company Ltd nor the names of its
-## contributors may be used to endorse or promote products derived
-## from this software without specific prior written permission.
-##
-##
-## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2013 Riverbank Computing Limited.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
"""PySide6 port of the corelib/threads/mandelbrot example from Qt v5.x, originating from PyQt"""
@@ -47,7 +9,7 @@ import sys
from PySide6.QtCore import (Signal, QMutex, QElapsedTimer, QMutexLocker,
QPoint, QPointF, QSize, Qt, QThread,
- QWaitCondition)
+ QWaitCondition, Slot)
from PySide6.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
from PySide6.QtWidgets import QApplication, QWidget
@@ -68,7 +30,7 @@ INFO_KEY = 'info'
HELP = ("Use mouse wheel or the '+' and '-' keys to zoom. Press and "
- "hold left mouse button to scroll.")
+ "hold left mouse button to scroll.")
class RenderThread(QThread):
@@ -91,7 +53,8 @@ class RenderThread(QThread):
self.abort = False
for i in range(RenderThread.colormap_size):
- self.colormap.append(self.rgb_from_wave_length(380.0 + (i * 400.0 / RenderThread.colormap_size)))
+ self.colormap.append(
+ self.rgb_from_wave_length(380.0 + (i * 400.0 / RenderThread.colormap_size)))
def stop(self):
self.mutex.lock()
@@ -102,18 +65,17 @@ class RenderThread(QThread):
self.wait(2000)
def render(self, centerX, centerY, scale_factor, resultSize):
- locker = QMutexLocker(self.mutex)
-
- self._center_x = centerX
- self._center_y = centerY
- self._scale_factor = scale_factor
- self._result_size = resultSize
-
- if not self.isRunning():
- self.start(QThread.LowPriority)
- else:
- self.restart = True
- self.condition.wakeOne()
+ with QMutexLocker(self.mutex):
+ self._center_x = centerX
+ self._center_y = centerY
+ self._scale_factor = scale_factor
+ self._result_size = resultSize
+
+ if not self.isRunning():
+ self.start(QThread.LowPriority)
+ else:
+ self.restart = True
+ self.condition.wakeOne()
def run(self):
timer = QElapsedTimer()
@@ -171,7 +133,8 @@ class RenderThread(QThread):
if num_iterations < max_iterations:
image.setPixel(x + half_width, y + half_height,
- self.colormap[num_iterations % RenderThread.colormap_size])
+ self.colormap[
+ num_iterations % RenderThread.colormap_size])
all_black = False
else:
image.setPixel(x + half_width, y + half_height, qRgb(0, 0, 0))
@@ -185,7 +148,8 @@ class RenderThread(QThread):
if elapsed > 2000:
elapsed /= 1000
unit = 's'
- text = f"Pass {curpass+1}/{NUM_PASSES}, max iterations: {max_iterations}, time: {elapsed}{unit}"
+ text = (f"Pass {curpass + 1}/{NUM_PASSES}, "
+ f"max iterations: {max_iterations}, time: {elapsed}{unit}")
image.setText(INFO_KEY, text)
self.rendered_image.emit(image, scale_factor)
curpass += 1
@@ -253,45 +217,45 @@ class MandelbrotWidget(QWidget):
self._info = ''
def paintEvent(self, event):
- painter = QPainter(self)
- painter.fillRect(self.rect(), Qt.black)
-
- if self.pixmap.isNull():
+ with QPainter(self) as painter:
+ painter.fillRect(self.rect(), Qt.black)
+
+ if self.pixmap.isNull():
+ painter.setPen(Qt.white)
+ painter.drawText(self.rect(), Qt.AlignCenter,
+ "Rendering initial image, please wait...")
+ return
+
+ if self._cur_scale == self._pixmap_scale:
+ painter.drawPixmap(self._pixmap_offset, self.pixmap)
+ else:
+ scale_factor = self._pixmap_scale / self._cur_scale
+ new_width = int(self.pixmap.width() * scale_factor)
+ new_height = int(self.pixmap.height() * scale_factor)
+ new_x = self._pixmap_offset.x() + (self.pixmap.width() - new_width) / 2
+ new_y = self._pixmap_offset.y() + (self.pixmap.height() - new_height) / 2
+
+ painter.save()
+ painter.translate(new_x, new_y)
+ painter.scale(scale_factor, scale_factor)
+ exposed, _ = painter.transform().inverted()
+ exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
+ painter.drawPixmap(exposed, self.pixmap, exposed)
+ painter.restore()
+
+ text = HELP
+ if self._info:
+ text += ' ' + self._info
+ metrics = painter.fontMetrics()
+ text_width = metrics.horizontalAdvance(text)
+
+ painter.setPen(Qt.NoPen)
+ painter.setBrush(QColor(0, 0, 0, 127))
+ painter.drawRect((self.width() - text_width) / 2 - 5, 0, text_width + 10,
+ metrics.lineSpacing() + 5)
painter.setPen(Qt.white)
- painter.drawText(self.rect(), Qt.AlignCenter,
- "Rendering initial image, please wait...")
- return
-
- if self._cur_scale == self._pixmap_scale:
- painter.drawPixmap(self._pixmap_offset, self.pixmap)
- else:
- scale_factor = self._pixmap_scale / self._cur_scale
- new_width = int(self.pixmap.width() * scale_factor)
- new_height = int(self.pixmap.height() * scale_factor)
- new_x = self._pixmap_offset.x() + (self.pixmap.width() - new_width) / 2
- new_y = self._pixmap_offset.y() + (self.pixmap.height() - new_height) / 2
-
- painter.save()
- painter.translate(new_x, new_y)
- painter.scale(scale_factor, scale_factor)
- exposed, _ = painter.transform().inverted()
- exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
- painter.drawPixmap(exposed, self.pixmap, exposed)
- painter.restore()
-
- text = HELP
- if self._info:
- text += ' ' + self._info
- metrics = painter.fontMetrics()
- text_width = metrics.horizontalAdvance(text)
-
- painter.setPen(Qt.NoPen)
- painter.setBrush(QColor(0, 0, 0, 127))
- painter.drawRect((self.width() - text_width) / 2 - 5, 0, text_width + 10,
- metrics.lineSpacing() + 5)
- painter.setPen(Qt.white)
- painter.drawText((self.width() - text_width) / 2,
- metrics.leading() + metrics.ascent(), text)
+ painter.drawText((self.width() - text_width) / 2,
+ metrics.leading() + metrics.ascent(), text)
def resizeEvent(self, event):
self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
@@ -340,6 +304,7 @@ class MandelbrotWidget(QWidget):
delta_y = (self.height() - self.pixmap.height()) / 2 - self._pixmap_offset.y()
self.scroll(delta_x, delta_y)
+ @Slot(QImage, float)
def update_pixmap(self, image, scale_factor):
if not self._last_drag_pos.isNull():
return
@@ -354,15 +319,13 @@ class MandelbrotWidget(QWidget):
def zoom(self, zoomFactor):
self._cur_scale *= zoomFactor
self.update()
- self.thread.render(self._center_x, self._center_y, self._cur_scale,
- self.size())
+ self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
def scroll(self, deltaX, deltaY):
self._center_x += deltaX * self._cur_scale
self._center_y += deltaY * self._cur_scale
self.update()
- self.thread.render(self._center_x, self._center_y, self._cur_scale,
- self.size())
+ self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
if __name__ == '__main__':