From 6a63ff5d0be54a2299142774509ad49582e35ca5 Mon Sep 17 00:00:00 2001 From: Alexandre RIO Date: Mon, 18 Aug 2025 21:30:26 +0200 Subject: [PATCH] use logging and cleanup --- README.md | 8 +++- grid/ui/items.py | 17 ++++--- grid/ui/light.py | 115 ---------------------------------------------- grid/ui/window.py | 5 ++ screenshot.png | Bin 0 -> 23101 bytes 5 files changed, 23 insertions(+), 122 deletions(-) delete mode 100644 grid/ui/light.py create mode 100644 screenshot.png diff --git a/README.md b/README.md index df63262..cb1c23d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,13 @@ I just like this FFX game design idea and I want to test some python tools I hav No clear roadmap, just 2D graphics fun -# Roadmap ideas +# Progress + +If you want an idea and the latest render + +![latest render of the program](./screenshot.png) + +## Roadmap ideas - [ ] seeded RNG - [ ] pattern: classic circles, line to connect far away patterns diff --git a/grid/ui/items.py b/grid/ui/items.py index 4d1ea83..eabd73d 100644 --- a/grid/ui/items.py +++ b/grid/ui/items.py @@ -1,3 +1,5 @@ +import logging + from PySide6.QtCore import QRectF, Qt from PySide6.QtGui import QBrush, QPainter, QPen from PySide6.QtWidgets import ( @@ -28,10 +30,8 @@ class SphereGraphicsItem(QGraphicsEllipseItem): ) self.x_pos = x_pos - self.SPHERE_WIDTH / 2 self.y_pos = y_pos - self.SPHERE_WIDTH / 2 - print(f"sphere at {self.x_pos}:{self.y_pos}") + logging.debug(f"sphere at {self.x_pos}:{self.y_pos}") - # self.setPos(self.x_pos - self.SPHERE_WIDTH/2, self.y_pos - self.SPHERE_WIDTH/2) - # super().moveBy(x_pos - center.x(), y_pos - center.y()) brush = QBrush(Qt.GlobalColor.darkBlue) self.setBrush(brush) pen = QPen(Qt.GlobalColor.blue) @@ -74,8 +74,13 @@ class ArcGraphicsItem(QGraphicsItem): self.angle_end = angle_end self.draw_angle_start = int(angle_start / 16) self.draw_angle_end = int(angle_end * 16) - print( - f"arc from {self.x_pos}:{self.y_pos} of {self.width} {self.angle_start}° {self.angle_end}°" + logging.debug( + "arc from %s:%s of %s from %s° to %s°", + self.x_pos, + self.y_pos, + self.width, + self.angle_start, + self.angle_end, ) def paint( @@ -107,7 +112,7 @@ class LineGraphicsItem(QGraphicsItem): parent: QGraphicsItem | None = ..., ) -> None: super().__init__(parent) - print(f"line from {begin_x}:{begin_y} to {end_x}:{end_y}") + logging.debug(f"line from {begin_x}:{begin_y} to {end_x}:{end_y}") self.begin_x = begin_x self.begin_y = begin_y self.end_x = end_x diff --git a/grid/ui/light.py b/grid/ui/light.py deleted file mode 100644 index a057c82..0000000 --- a/grid/ui/light.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2010 velociraptor Genjix -# Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause - -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.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.red) - vbox.addWidget(self._red_light) - self._yellow_light = LightWidget(Qt.yellow) - vbox.addWidget(self._yellow_light) - self._green_light = LightWidget(Qt.green) - vbox.addWidget(self._green_light) - pal = QPalette() - pal.setColor(QPalette.Window, Qt.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()) diff --git a/grid/ui/window.py b/grid/ui/window.py index 6f5c7d5..2edfa64 100644 --- a/grid/ui/window.py +++ b/grid/ui/window.py @@ -1,3 +1,4 @@ +import logging import sys from PySide6.QtGui import QPainter @@ -33,6 +34,10 @@ class Window(QWidget): self.show() +logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", +) app = QApplication(sys.argv) w = Window() app.exec() diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..d467bfc5c6debd8cbc91e961d96a76ac3f7e0879 GIT binary patch literal 23101 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 literal 0 HcmV?d00001