Refactor sudoku graphic components
parent
371dd810ca
commit
1a4b7a730a
|
@ -1,15 +1,11 @@
|
||||||
from PyQt5.QtGui import QPainter, QBrush, QPen, QColor, QFont
|
from PyQt5.QtGui import QPainter, QBrush, QPen, QColor, QFont
|
||||||
from PyQt5.Qt import QApplication, QTimer
|
|
||||||
from PyQt5.QtWidgets import (QGraphicsScene, QGraphicsWidget, QGraphicsItem,
|
from PyQt5.QtWidgets import (QGraphicsScene, QGraphicsWidget, QGraphicsItem,
|
||||||
QGraphicsLineItem, QGraphicsRectItem, QGraphicsObject,
|
QGraphicsLineItem, QGraphicsRectItem, QGraphicsObject,
|
||||||
QGraphicsItemGroup, QGraphicsPathItem)
|
QGraphicsItemGroup, QGraphicsPathItem)
|
||||||
from PyQt5.QtCore import (QAbstractAnimation, QObject, QPointF, Qt, QRectF, QLineF,
|
from PyQt5.QtCore import (QAbstractAnimation, QObject, QPointF, Qt, QRectF, QLineF,
|
||||||
QPropertyAnimation, pyqtProperty, pyqtSignal, QSizeF)
|
QPropertyAnimation, pyqtProperty, pyqtSignal, QSizeF)
|
||||||
from graphic_components import buttons
|
|
||||||
from general.extras import bound_value
|
from graphic_components import sudoku_graphics as sdk_grap
|
||||||
from gameplay import sudoku_gameplay as sdk
|
|
||||||
import numpy as np
|
|
||||||
import sys, math
|
|
||||||
|
|
||||||
|
|
||||||
class BoxBoard(QGraphicsWidget):
|
class BoxBoard(QGraphicsWidget):
|
||||||
|
@ -46,7 +42,7 @@ class BoxBoard(QGraphicsWidget):
|
||||||
painter.drawLine(line)
|
painter.drawLine(line)
|
||||||
|
|
||||||
def sizeHint(self, which, constraint=None):
|
def sizeHint(self, which, constraint=None):
|
||||||
return(QSizeF(self.width+10, self.height+10))
|
return QSizeF(self.width+10, self.height+10)
|
||||||
|
|
||||||
|
|
||||||
class GameBoard(BoxBoard):
|
class GameBoard(BoxBoard):
|
||||||
|
@ -54,11 +50,11 @@ class GameBoard(BoxBoard):
|
||||||
def __init__(self, width, height, parent=None):
|
def __init__(self, width, height, parent=None):
|
||||||
super().__init__(width, height, parent)
|
super().__init__(width, height, parent)
|
||||||
|
|
||||||
self.gamegrid = SudokuGrid(self.width, self.height, parent=self)
|
self.gamegrid = sdk_grap.SudokuGrid(self.width, self.height, parent=self)
|
||||||
self.numring = NumberRing(parent=self)
|
self.numring = sdk_grap.NumberRing(parent=self)
|
||||||
|
|
||||||
self.gamegrid.update()
|
self.gamegrid.buttonClicked.connect(self.show_number_ring)
|
||||||
self.numring.update()
|
self.numring.connect_button_signals(self.select_ring_number)
|
||||||
|
|
||||||
def show_number_ring(self, x=0, y=0):
|
def show_number_ring(self, x=0, y=0):
|
||||||
if not self.gamegrid.selected:
|
if not self.gamegrid.selected:
|
||||||
|
@ -74,169 +70,3 @@ class GameBoard(BoxBoard):
|
||||||
val = 0
|
val = 0
|
||||||
self.gamegrid.replace_cell_number(int(val))
|
self.gamegrid.replace_cell_number(int(val))
|
||||||
self.show_number_ring()
|
self.show_number_ring()
|
||||||
|
|
||||||
class SudokuGrid(QGraphicsObject):
|
|
||||||
# Prepare the signal
|
|
||||||
buttonClicked = pyqtSignal(float, float)
|
|
||||||
|
|
||||||
def __init__(self, width, height, parent=None):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
self.default_pen = QPen()
|
|
||||||
self.default_pen.setColor(Qt.white)
|
|
||||||
self.default_pen.setWidth(1)
|
|
||||||
|
|
||||||
self.thick_pen = QPen()
|
|
||||||
self.thick_pen.setColor(Qt.white)
|
|
||||||
self.thick_unit = 5
|
|
||||||
self.thick_pen.setWidth(self.thick_unit)
|
|
||||||
|
|
||||||
self.horiz_gridlines = []
|
|
||||||
self.vert_gridlines = []
|
|
||||||
|
|
||||||
self.thinlines = []
|
|
||||||
self.thicklines = []
|
|
||||||
|
|
||||||
self.cell_width = self.width / 9
|
|
||||||
self.cell_height = self.height /9
|
|
||||||
|
|
||||||
for i in range(1, 9):
|
|
||||||
delta_h = self.cell_height * i
|
|
||||||
delta_w = self.cell_width * i
|
|
||||||
if i%3 == 0:
|
|
||||||
self.thicklines.append(QLineF(0, delta_h, self.width, delta_h))
|
|
||||||
self.thicklines.append(QLineF(delta_w, 0, delta_w, self.height))
|
|
||||||
else:
|
|
||||||
self.thinlines.append(QLineF(0, delta_h, self.width, delta_h))
|
|
||||||
|
|
||||||
self.thinlines.append(QLineF(delta_w, 0, delta_w, self.height))
|
|
||||||
|
|
||||||
self.sudoku_grid = sdk.SudokuSystem()
|
|
||||||
self.grid_painter = NumberPainter(self, self.sudoku_grid)
|
|
||||||
|
|
||||||
self.mouse_w = 0
|
|
||||||
self.mouse_h = 0
|
|
||||||
self.selection_unit = 8
|
|
||||||
self.selection_pen = QPen()
|
|
||||||
self.selection_pen.setColor(Qt.white)
|
|
||||||
self.selection_pen.setWidth(self.selection_unit)
|
|
||||||
self.selection_box = QRectF(0, 0, self.cell_width, self.cell_height)
|
|
||||||
|
|
||||||
self.setAcceptHoverEvents(True)
|
|
||||||
self.setAcceptedMouseButtons(Qt.LeftButton)
|
|
||||||
|
|
||||||
self.selected = False
|
|
||||||
|
|
||||||
def replace_cell_number(self, val):
|
|
||||||
self.sudoku_grid.replace_cell_number(self.mouse_h, self.mouse_w, val)
|
|
||||||
self.grid_painter.update()
|
|
||||||
|
|
||||||
def boundingRect(self):
|
|
||||||
return QRectF(-5, -5, self.width+10, self.height+10)
|
|
||||||
|
|
||||||
# Reimplemented paint
|
|
||||||
def paint(self, painter, style, widget=None):
|
|
||||||
painter.setPen(self.default_pen)
|
|
||||||
for line in self.thinlines:
|
|
||||||
painter.drawLine(line)
|
|
||||||
|
|
||||||
painter.setPen(self.thick_pen)
|
|
||||||
for line in self.thicklines:
|
|
||||||
painter.drawLine(line)
|
|
||||||
|
|
||||||
painter.setPen(self.selection_pen)
|
|
||||||
painter.drawRect(self.selection_box)
|
|
||||||
|
|
||||||
def hoverMoveEvent(self, event):
|
|
||||||
box_w = bound_value(0, int(event.pos().x()/self.cell_width), 8)
|
|
||||||
box_h = bound_value(0, int(event.pos().y() / self.cell_height), 8)
|
|
||||||
if not self.selected:
|
|
||||||
if box_w != self.mouse_w or box_h != self.mouse_h:
|
|
||||||
self.mouse_w = box_w
|
|
||||||
self.mouse_h = box_h
|
|
||||||
self.selection_box.moveTopLeft(QPointF(box_w*self.cell_width, box_h*self.cell_height))
|
|
||||||
self.update()
|
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
|
||||||
w = (self.mouse_w + 0.5) * self.cell_width - 5
|
|
||||||
h = (self.mouse_h + 0.5) * self.cell_height + 5
|
|
||||||
|
|
||||||
if not self.sudoku_grid.get_cell_status(self.mouse_h, self.mouse_w) == sdk.FIXED:
|
|
||||||
self.buttonClicked.emit(w, h)
|
|
||||||
|
|
||||||
|
|
||||||
class NumberPainter(QGraphicsItem):
|
|
||||||
def __init__(self, parent, grid):
|
|
||||||
super().__init__(parent=parent)
|
|
||||||
self.parent = parent
|
|
||||||
self.sudoku_grid = grid
|
|
||||||
self.default_pen = QPen()
|
|
||||||
self.default_pen.setColor(Qt.white)
|
|
||||||
self.default_pen.setWidth(1)
|
|
||||||
|
|
||||||
self.invalid_pen = QPen()
|
|
||||||
self.invalid_pen.setColor(Qt.lightGray)
|
|
||||||
self.invalid_unit = 8
|
|
||||||
self.invalid_pen.setWidth(self.invalid_unit)
|
|
||||||
|
|
||||||
def paint(self, painter, style, widget=None):
|
|
||||||
for i in range(9):
|
|
||||||
for j in range(9):
|
|
||||||
self._draw_number_cell(i, j, painter)
|
|
||||||
|
|
||||||
def boundingRect(self):
|
|
||||||
return QRectF(-5, -5, self.parent.width+10, self.parent.height+10)
|
|
||||||
|
|
||||||
def _draw_number_cell(self, w, h, painter):
|
|
||||||
val = self.sudoku_grid.get_cell_number(h, w)
|
|
||||||
if val == 0:
|
|
||||||
val = ''
|
|
||||||
else:
|
|
||||||
if self.sudoku_grid.get_cell_status(h, w) == sdk.VALID:
|
|
||||||
painter.setPen(self.default_pen)
|
|
||||||
else:
|
|
||||||
painter.setPen(self.invalid_pen)
|
|
||||||
|
|
||||||
painter.drawText((w+0.5)*self.parent.cell_width-5,
|
|
||||||
(h+0.5)*self.parent.cell_height+5,
|
|
||||||
str(val))
|
|
||||||
|
|
||||||
|
|
||||||
class NumberRing(QGraphicsItem):
|
|
||||||
|
|
||||||
def __init__(self, parent= None):
|
|
||||||
super().__init__(parent = parent)
|
|
||||||
|
|
||||||
self.setVisible(False)
|
|
||||||
self.radius = 48
|
|
||||||
self.cell_width = 24
|
|
||||||
self.cell_height = 24
|
|
||||||
|
|
||||||
self.cell_buttons = []
|
|
||||||
for i in range(10):
|
|
||||||
cell_x = self.radius * np.sin(np.deg2rad(360/10*i)) - self.cell_width/2
|
|
||||||
cell_y = - self.radius * np.cos(np.deg2rad(360 / 10 * i)) - self.cell_height/2
|
|
||||||
if i == 0:
|
|
||||||
cell_string = 'X'
|
|
||||||
else:
|
|
||||||
cell_string = str(i)
|
|
||||||
btn = buttons.animBox(cell_x, cell_y, self.cell_width,
|
|
||||||
self.cell_height, cell_string, self)
|
|
||||||
|
|
||||||
self.cell_buttons.append(btn)
|
|
||||||
|
|
||||||
def boundingRect(self):
|
|
||||||
return QRectF(-5, -5, self.cell_width+self.radius*2+10,
|
|
||||||
self.cell_height + self.radius * 2 + 10)
|
|
||||||
|
|
||||||
# Reimplemented paint
|
|
||||||
def paint(self, painter, style, widget=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def connect_button_signals(self, func):
|
|
||||||
for btn in self.cell_buttons:
|
|
||||||
btn.buttonClicked.connect(func)
|
|
||||||
|
|
||||||
#def mousePressEvent(self, event):
|
|
||||||
# print('Yes')
|
|
||||||
|
|
|
@ -1 +1,177 @@
|
||||||
# Put all Sudoku related graphics here
|
# Put all Sudoku related graphics here
|
||||||
|
from PyQt5.QtGui import QPainter, QBrush, QPen, QColor, QFont
|
||||||
|
from PyQt5.QtWidgets import QGraphicsItem, QGraphicsObject
|
||||||
|
from PyQt5.QtCore import (QAbstractAnimation, QPointF, Qt, QRectF, QLineF,
|
||||||
|
QPropertyAnimation, pyqtProperty, pyqtSignal)
|
||||||
|
|
||||||
|
from gameplay import sudoku_gameplay as sdk
|
||||||
|
from general.extras import bound_value
|
||||||
|
from graphic_components import buttons
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
class NumberPainter(QGraphicsItem):
|
||||||
|
def __init__(self, parent, grid):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self.parent = parent
|
||||||
|
self.sudoku_grid = grid
|
||||||
|
self.default_pen = QPen()
|
||||||
|
self.default_pen.setColor(Qt.white)
|
||||||
|
self.default_pen.setWidth(1)
|
||||||
|
|
||||||
|
self.invalid_pen = QPen()
|
||||||
|
self.invalid_pen.setColor(Qt.lightGray)
|
||||||
|
self.invalid_unit = 8
|
||||||
|
self.invalid_pen.setWidth(self.invalid_unit)
|
||||||
|
|
||||||
|
def paint(self, painter, style, widget=None):
|
||||||
|
for i in range(9):
|
||||||
|
for j in range(9):
|
||||||
|
self._draw_number_cell(i, j, painter)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return QRectF(-5, -5, self.parent.width+10, self.parent.height+10)
|
||||||
|
|
||||||
|
def _draw_number_cell(self, w, h, painter):
|
||||||
|
val = self.sudoku_grid.get_cell_number(h, w)
|
||||||
|
if val == 0:
|
||||||
|
val = ''
|
||||||
|
else:
|
||||||
|
if self.sudoku_grid.get_cell_status(h, w) == sdk.VALID:
|
||||||
|
painter.setPen(self.default_pen)
|
||||||
|
else:
|
||||||
|
painter.setPen(self.invalid_pen)
|
||||||
|
|
||||||
|
painter.drawText((w+0.5)*self.parent.cell_width-5,
|
||||||
|
(h+0.5)*self.parent.cell_height+5,
|
||||||
|
str(val))
|
||||||
|
|
||||||
|
|
||||||
|
class SudokuGrid(QGraphicsObject):
|
||||||
|
# Prepare the signal
|
||||||
|
buttonClicked = pyqtSignal(float, float)
|
||||||
|
|
||||||
|
def __init__(self, width, height, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.default_pen = QPen()
|
||||||
|
self.default_pen.setColor(Qt.white)
|
||||||
|
self.default_pen.setWidth(1)
|
||||||
|
|
||||||
|
self.thick_pen = QPen()
|
||||||
|
self.thick_pen.setColor(Qt.white)
|
||||||
|
self.thick_unit = 5
|
||||||
|
self.thick_pen.setWidth(self.thick_unit)
|
||||||
|
|
||||||
|
self.horiz_gridlines = []
|
||||||
|
self.vert_gridlines = []
|
||||||
|
|
||||||
|
self.thinlines = []
|
||||||
|
self.thicklines = []
|
||||||
|
|
||||||
|
self.cell_width = self.width / 9
|
||||||
|
self.cell_height = self.height / 9
|
||||||
|
|
||||||
|
for i in range(1, 9):
|
||||||
|
delta_h = self.cell_height * i
|
||||||
|
delta_w = self.cell_width * i
|
||||||
|
if i%3 == 0:
|
||||||
|
self.thicklines.append(QLineF(0, delta_h, self.width, delta_h))
|
||||||
|
self.thicklines.append(QLineF(delta_w, 0, delta_w, self.height))
|
||||||
|
else:
|
||||||
|
self.thinlines.append(QLineF(0, delta_h, self.width, delta_h))
|
||||||
|
|
||||||
|
self.thinlines.append(QLineF(delta_w, 0, delta_w, self.height))
|
||||||
|
|
||||||
|
self.sudoku_grid = sdk.SudokuSystem()
|
||||||
|
self.grid_painter = NumberPainter(self, self.sudoku_grid)
|
||||||
|
|
||||||
|
self.mouse_w = 0
|
||||||
|
self.mouse_h = 0
|
||||||
|
self.selection_unit = 8
|
||||||
|
self.selection_pen = QPen()
|
||||||
|
self.selection_pen.setColor(Qt.white)
|
||||||
|
self.selection_pen.setWidth(self.selection_unit)
|
||||||
|
self.selection_box = QRectF(0, 0, self.cell_width, self.cell_height)
|
||||||
|
|
||||||
|
self.setAcceptHoverEvents(True)
|
||||||
|
self.setAcceptedMouseButtons(Qt.LeftButton)
|
||||||
|
|
||||||
|
self.selected = False
|
||||||
|
|
||||||
|
def replace_cell_number(self, val):
|
||||||
|
self.sudoku_grid.replace_cell_number(self.mouse_h, self.mouse_w, val)
|
||||||
|
self.grid_painter.update()
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return QRectF(-5, -5, self.width+10, self.height+10)
|
||||||
|
|
||||||
|
# Reimplemented paint
|
||||||
|
def paint(self, painter, style, widget=None):
|
||||||
|
painter.setPen(self.default_pen)
|
||||||
|
for line in self.thinlines:
|
||||||
|
painter.drawLine(line)
|
||||||
|
|
||||||
|
painter.setPen(self.thick_pen)
|
||||||
|
for line in self.thicklines:
|
||||||
|
painter.drawLine(line)
|
||||||
|
|
||||||
|
painter.setPen(self.selection_pen)
|
||||||
|
painter.drawRect(self.selection_box)
|
||||||
|
|
||||||
|
def hoverMoveEvent(self, event):
|
||||||
|
box_w = bound_value(0, int(event.pos().x()/self.cell_width), 8)
|
||||||
|
box_h = bound_value(0, int(event.pos().y() / self.cell_height), 8)
|
||||||
|
if not self.selected:
|
||||||
|
if box_w != self.mouse_w or box_h != self.mouse_h:
|
||||||
|
self.mouse_w = box_w
|
||||||
|
self.mouse_h = box_h
|
||||||
|
self.selection_box.moveTopLeft(QPointF(box_w*self.cell_width, box_h*self.cell_height))
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
w = (self.mouse_w + 0.5) * self.cell_width - 5
|
||||||
|
h = (self.mouse_h + 0.5) * self.cell_height + 5
|
||||||
|
|
||||||
|
if not self.sudoku_grid.get_cell_status(self.mouse_h, self.mouse_w) == sdk.FIXED:
|
||||||
|
self.buttonClicked.emit(w, h)
|
||||||
|
|
||||||
|
|
||||||
|
class NumberRing(QGraphicsItem):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
self.setVisible(False)
|
||||||
|
self.radius = 48
|
||||||
|
self.cell_width = 24
|
||||||
|
self.cell_height = 24
|
||||||
|
|
||||||
|
self.cell_buttons = []
|
||||||
|
for i in range(10):
|
||||||
|
cell_x = self.radius * np.sin(np.deg2rad(360/10*i)) - self.cell_width/2
|
||||||
|
cell_y = - self.radius * np.cos(np.deg2rad(360 / 10 * i)) - self.cell_height/2
|
||||||
|
if i == 0:
|
||||||
|
cell_string = 'X'
|
||||||
|
else:
|
||||||
|
cell_string = str(i)
|
||||||
|
btn = buttons.animBox(cell_x, cell_y, self.cell_width,
|
||||||
|
self.cell_height, cell_string, self)
|
||||||
|
|
||||||
|
self.cell_buttons.append(btn)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return QRectF(-5, -5, self.cell_width+self.radius*2+10,
|
||||||
|
self.cell_height + self.radius * 2 + 10)
|
||||||
|
|
||||||
|
# Reimplemented paint
|
||||||
|
def paint(self, painter, style, widget=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def connect_button_signals(self, func):
|
||||||
|
for btn in self.cell_buttons:
|
||||||
|
btn.buttonClicked.connect(func)
|
||||||
|
|
||||||
|
#def mousePressEvent(self, event):
|
||||||
|
# print('Yes')
|
30
main.py
30
main.py
|
@ -18,54 +18,26 @@ class SudokuWindow(QGraphicsView):
|
||||||
# Set up the Scene to manage the GraphicItems
|
# Set up the Scene to manage the GraphicItems
|
||||||
self.scene = QGraphicsScene(0, 0, 400, 500, self)
|
self.scene = QGraphicsScene(0, 0, 400, 500, self)
|
||||||
|
|
||||||
|
|
||||||
self.setScene(self.scene)
|
self.setScene(self.scene)
|
||||||
self.setSceneRect(self.scene.sceneRect())
|
self.setSceneRect(self.scene.sceneRect())
|
||||||
self.gameboard = board.GameBoard(400, 400)
|
self.gameboard = board.GameBoard(400, 400)
|
||||||
self.menuboard = board.BoxBoard(400, 50)
|
self.menuboard = board.BoxBoard(400, 50)
|
||||||
self.gamegrid = board.SudokuGrid(450, 450)
|
|
||||||
self.numring = board.NumberRing()
|
|
||||||
|
|
||||||
self.layout = QGraphicsLinearLayout(Qt.Vertical)
|
self.layout = QGraphicsLinearLayout(Qt.Vertical)
|
||||||
self.layout.addItem(self.gameboard)
|
self.layout.addItem(self.gameboard)
|
||||||
self.layout.addItem(self.menuboard)
|
self.layout.addItem(self.menuboard)
|
||||||
self.form = QGraphicsWidget()
|
self.form = QGraphicsWidget()
|
||||||
self.form.setLayout(self.layout)
|
self.form.setLayout(self.layout)
|
||||||
#self.layout.addItem(self.gamegrid)
|
|
||||||
#self.button1 = buttons.animBox(0, 0, 20, 20, 'a')
|
|
||||||
#self.scene.addItem(self.button1)
|
|
||||||
|
|
||||||
|
|
||||||
#self.scene.addItem(self.gameboard)
|
|
||||||
self.scene.addItem(self.form)
|
self.scene.addItem(self.form)
|
||||||
#self.scene.addItem(self.gamegrid)
|
|
||||||
#self.scene.addItem(self.numring)
|
|
||||||
self.setBackgroundBrush(QBrush(Qt.black))
|
self.setBackgroundBrush(QBrush(Qt.black))
|
||||||
self.setRenderHint(QPainter.Antialiasing)
|
self.setRenderHint(QPainter.Antialiasing)
|
||||||
self.setGeometry(0, 0, 600, 600)
|
self.setGeometry(0, 0, 600, 600)
|
||||||
|
|
||||||
self.gamegrid.buttonClicked.connect(self.show_number_ring)
|
self.ensureVisible(self.scene.sceneRect(), 10, 10)
|
||||||
self.numring.connect_button_signals(self.select_ring_number)
|
|
||||||
|
|
||||||
self.ensureVisible(self.scene.sceneRect(), 50, 50)
|
|
||||||
self.fitInView(self.gameboard.boundingRect(), Qt.KeepAspectRatio)
|
self.fitInView(self.gameboard.boundingRect(), Qt.KeepAspectRatio)
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
def show_number_ring(self, x=0, y=0):
|
|
||||||
if not self.gamegrid.selected:
|
|
||||||
self.numring.setPos(x, y)
|
|
||||||
self.numring.setVisible(True)
|
|
||||||
self.gamegrid.selected = True
|
|
||||||
else:
|
|
||||||
self.numring.setVisible(False)
|
|
||||||
self.gamegrid.selected = False
|
|
||||||
|
|
||||||
def select_ring_number(self, val):
|
|
||||||
if val == 'X':
|
|
||||||
val = 0
|
|
||||||
self.gamegrid.replace_cell_number(int(val))
|
|
||||||
self.show_number_ring()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = 0
|
app = 0
|
||||||
|
|
Loading…
Reference in New Issue