1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
import sys
from PySide6.QtCore import QTimer, Qt, Property, Slot
from PySide6.QtGui import QPainter, QPalette
from PySide6.QtWidgets import QApplication, QVBoxLayout, QWidget
from PySide6.QtStateMachine import QFinalState, QState, QStateMachine
class LightWidget(QWidget):
def __init__(self, color):
super().__init__()
self.color = color
self._on_val = False
def is_on(self):
return self._on_val
def set_on(self, on):
if self._on_val == on:
return
self._on_val = on
self.update()
@Slot()
def turn_off(self):
self.set_on(False)
@Slot()
def turn_on(self):
self.set_on(True)
def paintEvent(self, e):
if not self._on_val:
return
with QPainter(self) as painter:
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
painter.setBrush(self.color)
painter.drawEllipse(0, 0, self.width(), self.height())
on = Property(bool, is_on, set_on)
class TrafficLightWidget(QWidget):
def __init__(self):
super().__init__()
vbox = QVBoxLayout(self)
self._red_light = LightWidget(Qt.GlobalColor.red)
vbox.addWidget(self._red_light)
self._yellow_light = LightWidget(Qt.GlobalColor.yellow)
vbox.addWidget(self._yellow_light)
self._green_light = LightWidget(Qt.GlobalColor.green)
vbox.addWidget(self._green_light)
pal = QPalette()
pal.setColor(QPalette.ColorRole.Window, Qt.GlobalColor.black)
self.setPalette(pal)
self.setAutoFillBackground(True)
def create_light_state(light, duration, parent=None):
light_state = QState(parent)
timer = QTimer(light_state)
timer.setInterval(duration)
timer.setSingleShot(True)
timing = QState(light_state)
timing.entered.connect(light.turn_on)
timing.entered.connect(timer.start)
timing.exited.connect(light.turn_off)
done = QFinalState(light_state)
timing.addTransition(timer.timeout, done)
light_state.setInitialState(timing)
return light_state
class TrafficLight(QWidget):
def __init__(self):
super().__init__()
vbox = QVBoxLayout(self)
widget = TrafficLightWidget()
vbox.addWidget(widget)
vbox.setContentsMargins(0, 0, 0, 0)
machine = QStateMachine(self)
red_going_yellow = create_light_state(widget._red_light, 1000)
red_going_yellow.setObjectName('redGoingYellow')
yellow_going_green = create_light_state(widget._red_light, 1000)
yellow_going_green.setObjectName('yellowGoingGreen')
red_going_yellow.addTransition(red_going_yellow.finished,
yellow_going_green)
green_going_yellow = create_light_state(widget._yellow_light, 3000)
green_going_yellow.setObjectName('greenGoingYellow')
yellow_going_green.addTransition(yellow_going_green.finished,
green_going_yellow)
yellow_going_red = create_light_state(widget._green_light, 1000)
yellow_going_red.setObjectName('yellowGoingRed')
green_going_yellow.addTransition(green_going_yellow.finished,
yellow_going_red)
yellow_going_red.addTransition(yellow_going_red.finished,
red_going_yellow)
machine.addState(red_going_yellow)
machine.addState(yellow_going_green)
machine.addState(green_going_yellow)
machine.addState(yellow_going_red)
machine.setInitialState(red_going_yellow)
machine.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = TrafficLight()
widget.resize(110, 300)
widget.show()
sys.exit(app.exec())
|