/tmp/snapshot-pyside-6.2-rel/pyside-setup/examples/widgets/state-machine/rogue¶
(You can also check this code in the repository)
import sys
from PySide6.QtCore import (QEvent, QPoint, QRandomGenerator, QSize, Qt,
Property)
from PySide6.QtGui import QFont, QFontMetrics, QFontDatabase, QPainter
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtStateMachine import (QEventTransition, QFinalState,
QKeyEventTransition, QState, QStateMachine)
class MovementTransition(QEventTransition):
def __init__(self, window):
super().__init__(window, QEvent.KeyPress)
self.window = window
def eventTest(self, event):
if (event.type() == QEvent.StateMachineWrapped and
event.event().type() == QEvent.KeyPress):
key = event.event().key()
return (key == Qt.Key_2 or key == Qt.Key_8 or
key == Qt.Key_6 or key == Qt.Key_4)
return False
def onTransition(self, event):
key = event.event().key()
if key == Qt.Key_4:
self.window.move_player(self.window.left)
if key == Qt.Key_8:
self.window.move_player(self.window.Up)
if key == Qt.Key_6:
self.window.move_player(self.window.right)
if key == Qt.Key_2:
self.window.move_player(self.window.down)
class Custom(QState):
def __init__(self, parent, mw):
super().__init__(parent)
self.mw = mw
def onEntry(self, e):
print(self.mw.status)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.pX = 5
self.pY = 5
self.width = 35
self.height = 20
self._status_str = ''
font = QFont()
if 'Monospace' in QFontDatabase.families():
font = QFont('Monospace', 12)
else:
for family in QFontDatabase.families():
if QFontDatabase.isFixedPitch(family):
font = QFont(family, 12)
self.setFont(font)
self.setup_map()
self.build_machine()
self.show()
def setup_map(self):
self.map = []
generator = QRandomGenerator().global_()
for x in range(self.width):
column = []
for y in range(self.height):
if (x == 0 or x == self.width - 1 or y == 0 or
y == self.height - 1 or generator.bounded(0, 40) == 0):
column.append('#')
else:
column.append('.')
self.map.append(column)
def build_machine(self):
machine = QStateMachine(self)
input_state = Custom(machine, self)
# this line sets the status
self.status = 'hello!'
# however this line does not
input_state.assignProperty(self, 'status', 'Move the rogue with 2, 4, 6, and 8')
machine.setInitialState(input_state)
machine.start()
transition = MovementTransition(self)
input_state.addTransition(transition)
quit_state = QState(machine)
quit_state.assignProperty(self, 'status', 'Really quit(y/n)?')
yes_transition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Y)
self._final_state = QFinalState(machine)
yes_transition.setTargetState(self._final_state)
quit_state.addTransition(yes_transition)
no_transition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_N)
no_transition.setTargetState(input_state)
quit_state.addTransition(no_transition)
quit_transition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Q)
quit_transition.setTargetState(quit_state)
input_state.addTransition(quit_transition)
machine.setInitialState(input_state)
machine.finished.connect(qApp.quit)
machine.start()
def sizeHint(self):
metrics = QFontMetrics(self.font())
return QSize(metrics.horizontalAdvance('X') * self.width,
metrics.height() * (self.height + 1))
def paintEvent(self, event):
metrics = QFontMetrics(self.font())
painter = QPainter(self)
font_height = metrics.height()
font_width = metrics.horizontalAdvance('X')
painter.fillRect(self.rect(), Qt.black)
painter.setPen(Qt.white)
y_pos = font_height
painter.drawText(QPoint(0, y_pos), self.status)
for y in range(self.height):
y_pos += font_height
x_pos = 0
for x in range(self.width):
if y == self.pY and x == self.pX:
x_pos += font_width
continue
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:
if self.map[self.pX - 1][self.pY] != '#':
self.pX -= 1
elif direction == self.right:
if self.map[self.pX + 1][self.pY] != '#':
self.pX += 1
elif direction == self.Up:
if self.map[self.pX][self.pY - 1] != '#':
self.pY -= 1
elif direction == self.down:
if self.map[self.pX][self.pY + 1] != '#':
self.pY += 1
self.repaint()
def get_status(self):
return self._status_str
def set_status(self, status):
self._status_str = status
self.repaint()
status = Property(str, get_status, set_status)
Up = 0
down = 1
left = 2
right = 3
width = 35
height = 20
if __name__ == '__main__':
app = QApplication(sys.argv)
main_win = MainWindow()
sys.exit(app.exec())
© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.