PySide6 Timing-UnterschiedePython

Python-Programme
Anonymous
 PySide6 Timing-Unterschiede

Post by Anonymous »

(Aktualisiert, um eine zusätzliche Methode zum Ändern der Beschriftungsfarbe hinzuzufügen und zusätzliches Timing für das ursprüngliche MWE hinzuzufügen. Neue Version hinzugefügt, die eine von @ekhumoro vorgeschlagene Szene verwendet).
Ich erstelle ein Beschriftungsraster, dessen Hintergrundfarben ich dann kontinuierlich ändern kann, wenn sich die Werte der Rasterposition ändern. Ich habe drei verschiedene Möglichkeiten, die Beschriftung an die bestimmte Rasterposition zu bringen und dann ihre Farbe zu ändern. ChangeBox1 und ChangeBox2 verwenden Stylesheets und ChangeBox3 ändert die Palette direkt.
Wenn ich diese Routinen in der Klasseninit-Funktion aufrufe, werden sie wesentlich schneller ausgeführt, als wenn ich sie nach dem Anzeigen des Fensters aufrufe.
Warum?
Man kann sehen, dass das direkte Ändern der Palette durch changeBox3 ziemlich konsistent ist, unabhängig davon, wann es aufgerufen wird. Könnte dies ein Unterschied darin sein, wie QT ein Stylesheet nach der Instanziierung des Widgets verarbeitet (oder pyside übersetzt)?
Ich verwende Python 3.10.15

Code: Select all

Average execution time of changeBox1 in init over 500 runs: 1.0947501286864281e-06 seconds
Average execution time of changeBox2 in init over 500 runs: 4.599159583449364e-07 seconds
Average execution time of changeBox3 in init over 500 runs: 2.514749765396118e-06 seconds
Average execution time of changeBox1 after window.show over 500 runs: 1.4484249986708164e-05 seconds
Average execution time of changeBox2 after window.show over 500 runs: 1.4263415709137917e-05 seconds
Average execution time of changeBox3 after window.show over 500 runs: 2.624250017106533e-06 seconds
Average execution time of myLabel1 over 500 runs: 1.668350026011467e-05 seconds
Average execution time of myLabel2 over 500 runs: 1.4353999868035316e-05 seconds

Hier ist mein MWE:

Code: Select all

import sys
import timeit

from PySide6.QtCore import QSize, Qt
from PySide6.QtGui import QColor, QFont, QPalette
from PySide6.QtWidgets import (
QApplication,
QGridLayout,
QLabel,
QMainWindow,
QWidget,
)

arrows = ["\u2191", "\u2193", "\u2192", "\u2190"]

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

self.setWindowTitle("My App")
self.setMinimumSize(QSize(400, 300))

self.layout = QGridLayout()
self.layout.setSpacing(3)

xMax = 4
yMax = 5
steps = xMax * yMax
midStep = steps // 2 + 1
cStep = 255 // midStep
cRed = 255
cGreen = 0
cBlue = 0
self.labels = {}
for b in range(steps):
label = f"T{b}\n{arrows[b % 4]}"
(x,y) = divmod(b, xMax)
color = f"{cRed:02x}{cGreen:02x}{cBlue:02x}"
self.labels[(x, y)] = self.addBox(color, label, x, y)

if b <  midStep:
cGreen += cStep
else:
cRed -= cStep

widget = QWidget()
widget.setLayout(self.layout)
self.setCentralWidget(widget)

runs = 500
time1 = timeit.timeit(lambda: self.changeBox1(2, 2), number=runs)
time2 = timeit.timeit(lambda: self.changeBox2(1, 1), number=runs)
time3 = timeit.timeit(lambda: self.changeBox3(0, 0), number=runs)

print(
f"Average execution time of changeBox1 in init over {runs} runs: {time1 / runs} seconds"
)
print(
f"Average execution time of changeBox2 in init over {runs} runs: {time2 / runs} seconds"
)
print(
f"Average execution time of changeBox3 in init over {runs} runs: {time3 / runs} seconds"
)

# Find the fastest way to change the color of a specific widget

def changeBoxColor(self):
self.changeBox1(2, 2)
self.changeBox2(1, 1)
self.changeBox3(0, 0)

runs = 500
time1 = timeit.timeit(lambda: self.changeBox1(2, 2), number=runs)
time2 = timeit.timeit(lambda: self.changeBox2(1, 1), number=runs)
time3 = timeit.timeit(lambda: self.changeBox3(0, 0), number=runs)

print(
f"Average execution time of changeBox1 after window.show over {runs} runs: {time1 / runs} seconds"
)
print(
f"Average execution time of changeBox2 after window.show over {runs} runs: {time2 / runs} seconds"
)
print(
f"Average execution time of changeBox3 after window.show over {runs} runs: {time3 / runs} seconds"
)

def myLabelTimer(self):
runs = 500
time1 = timeit.timeit(lambda: self.myLabel1("f0f0f0", "Test"), number=runs)
time2 = timeit.timeit(lambda: self.myLabel2("f0f0f0", "Test"), number=runs)

print(
f"Average execution time of myLabel1 over {runs} runs: {time1 / runs} seconds"
)
print(
f"Average execution time of myLabel2 over {runs} runs: {time2 / runs} seconds"
)

def myLabel1(self, color, text):
tBox = QLabel(text)
tBox.setAutoFillBackground(True)
tBox.setAlignment(Qt.AlignCenter)
tBox.setStyleSheet(f"background: #{color}; font-style: bold; font-size: 24pt")

return tBox

def myLabel2(self, color, text):
tBox = QLabel(text)
tBox.setAutoFillBackground(True)
tBox.setAlignment(Qt.AlignCenter)
palette = tBox.palette()
palette.setColor(QPalette.Window, QColor(f"#{color}"))
tBox.setPalette(palette)
font = QFont()
font.setPointSize(24)
font.setWeight(QFont.Bold)
tBox.setFont(font)

return tBox

def addBox(self, color, text, x, y):
box = self.myLabel2(color, text)
self.layout.addWidget(box, x, y)

return box

def changeBox1(self, x, y):
cell = self.layout.itemAtPosition(x, y).widget()
cell.setStyleSheet(
f"background: #{'0000ff'}; font-style: bold; font-size: 24pt"
)

def changeBox2(self, x, y):
self.labels[(x, y)].setStyleSheet(
f"background: #{'00f0ff'}; font-style: bold;  font-size: 24pt"
)

def changeBox3(self, x, y):
palette = self.labels[(x, y)].palette()
palette.setColor(QPalette.Window, QColor("#0080ff"))
self.labels[(x, y)].setPalette(palette)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
window.changeBoxColor()
window.myLabelTimer()
app.exec()
Der Vollständigkeit halber ist hier eine Version mit Szene und Ansicht gemäß @ekhumoro:

Code: Select all

import sys
import timeit

from PySide6.QtCore import QSize, QPoint, Qt
from PySide6.QtGui import QColor, QFont, QPalette
from PySide6.QtWidgets import (
QApplication,
QLabel,
QWidget,
QGraphicsScene,
QGraphicsView,
QHBoxLayout,
)

arrows = ["\u2191", "\u2193", "\u2192", "\u2190"]

class Window(QWidget):

xMax    : int = 4
yMax    : int = 5
boxSize : int = 75
labels  = {}

def __init__(self):
super().__init__()

self.setWindowTitle("My App")
self.setMinimumSize(QSize(self.xMax * self.boxSize, self.yMax * self.boxSize ))

self.scene = QGraphicsScene(0, 0, self.xMax * self.boxSize, self.yMax * self.boxSize)

label = self.label("0000ff", "Test",QPoint(self.boxSize,self.boxSize))

self.scene.addWidget(label)
self.buildGrid()

# Define our layout.
view = QGraphicsView(self.scene)

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

self.setLayout(hbox)

def label(self, color, text, pos : QPoint):
tBox: QLabel = QLabel(text)
tBox.setFixedSize(self.boxSize,self.boxSize)
tBox.setAutoFillBackground(True)
tBox.setAlignment(Qt.AlignCenter)

palette = tBox.palette()
palette.setColor(QPalette.Window, QColor(f"#{color}"))
tBox.setPalette(palette)

font = QFont()
font.setPointSize(24)
font.setWeight(QFont.Bold)
tBox.setFont(font)

tBox.move(pos)

return tBox

def buildGrid(self):

steps = self.xMax * self.yMax
midStep = steps // 2 + 1
cStep = 255 // midStep
cRed = 255
cGreen = 0
cBlue = 0
for b in range(steps):
label = f"T{b}\n{arrows[b % 4]}"
(y,x) = divmod(b, self.xMax)
color = f"{cRed:02x}{cGreen:02x}{cBlue:02x}"
self.labels[(x, y)] = self.label(color, label, QPoint(x * self.boxSize,y * self.boxSize))
self.scene.addWidget(self.labels[(x, y)])

if b < midStep:
cGreen += cStep
else:
cRed -= cStep

def changeBox(self, x, y):
palette = self.labels[(x, y)].palette()
palette.setColor(QPalette.Window, QColor("#0080ff"))
self.labels[(x, y)].setPalette(palette)

app = QApplication(sys.argv)
window = Window()
window.show()
window.changeBox(0, 0)

runs = 500
time1 = timeit.timeit(lambda: window.changeBox(2, 2), number=runs)
print(
f"Average execution time of changeBox in init over {runs} runs: {time1 / runs} seconds"
)

app.exec()

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post