Still documenting sudoku_graphics
parent
319c6b6970
commit
54b27ffbac
|
@ -143,6 +143,16 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
puzzleFinished = Signal()
|
puzzleFinished = Signal()
|
||||||
|
|
||||||
def __init__(self, width, height, parent=None):
|
def __init__(self, width, height, parent=None):
|
||||||
|
"""Initialise the lines and animation to draw the grid, as well as initialising the
|
||||||
|
graphics components. The parent argument is passed into BaseSudokuItem init method.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
width: float
|
||||||
|
Width of the grid
|
||||||
|
height: float
|
||||||
|
Height of the grid
|
||||||
|
"""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
|
@ -185,9 +195,8 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
|
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
|
||||||
self.set_disabled(False)
|
self.set_disabled(False)
|
||||||
|
|
||||||
# Length of the box to be drawn
|
# Set up the animation
|
||||||
self.length = 0
|
self.length = 0
|
||||||
# Set up the length to be animated
|
|
||||||
self.anim = QPropertyAnimation(self, b'length')
|
self.anim = QPropertyAnimation(self, b'length')
|
||||||
self.anim.setDuration(500) # Animation speed
|
self.anim.setDuration(500) # Animation speed
|
||||||
self.anim.setStartValue(0)
|
self.anim.setStartValue(0)
|
||||||
|
@ -201,6 +210,13 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.anim.finished.connect(self.finish_drawing)
|
self.anim.finished.connect(self.finish_drawing)
|
||||||
|
|
||||||
def set_disabled(self, state):
|
def set_disabled(self, state):
|
||||||
|
"""Disable or Enable the grid to accept inputs
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
state: bool
|
||||||
|
If true, enable the grid. Disable otherwise.
|
||||||
|
"""
|
||||||
if state:
|
if state:
|
||||||
self.setAcceptedMouseButtons(Qt.NoButton)
|
self.setAcceptedMouseButtons(Qt.NoButton)
|
||||||
else:
|
else:
|
||||||
|
@ -208,12 +224,15 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.setAcceptHoverEvents(not state)
|
self.setAcceptHoverEvents(not state)
|
||||||
|
|
||||||
def finish_drawing(self):
|
def finish_drawing(self):
|
||||||
|
"""Function to be called once the animaion finishes. Emits the finishDrawing signal
|
||||||
|
"""
|
||||||
if self.length == self.width:
|
if self.length == self.width:
|
||||||
self.drawn = True
|
self.drawn = True
|
||||||
self.finishDrawing.emit()
|
self.finishDrawing.emit()
|
||||||
|
|
||||||
# Toggle the animation to be play forward or backward
|
|
||||||
def toggle_anim(self, toggling):
|
def toggle_anim(self, toggling):
|
||||||
|
"""Toggle the animation to be play forward or backward
|
||||||
|
"""
|
||||||
if toggling:
|
if toggling:
|
||||||
self.anim.setDirection(QAbstractAnimation.Forward)
|
self.anim.setDirection(QAbstractAnimation.Forward)
|
||||||
else:
|
else:
|
||||||
|
@ -222,11 +241,25 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.anim.start()
|
self.anim.start()
|
||||||
|
|
||||||
def generate_new_grid(self, difficulty):
|
def generate_new_grid(self, difficulty):
|
||||||
|
"""Generate a new puzzle and update the grid
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
difficulty: int
|
||||||
|
The difficulty level
|
||||||
|
"""
|
||||||
self.sudoku_grid.generate_random_board(difficulty)
|
self.sudoku_grid.generate_random_board(difficulty)
|
||||||
#self.sudoku_grid.generate_test_board(difficulty) # Uncomment for testing
|
#self.sudoku_grid.generate_test_board(difficulty) # Uncomment for testing
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def change_cell_scribbles(self, val):
|
def change_cell_scribbles(self, val):
|
||||||
|
"""Change the scribble of a digit of a given cell at the mouse position
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
val: int
|
||||||
|
The scribbled digit to toggle. 0 to clear all
|
||||||
|
"""
|
||||||
if val == 0:
|
if val == 0:
|
||||||
self.sudoku_grid.clear_scribble(self.mouse_h, self.mouse_w)
|
self.sudoku_grid.clear_scribble(self.mouse_h, self.mouse_w)
|
||||||
else:
|
else:
|
||||||
|
@ -234,15 +267,26 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.grid_painter.update()
|
self.grid_painter.update()
|
||||||
|
|
||||||
def replace_cell_number(self, val):
|
def replace_cell_number(self, val):
|
||||||
|
"""Replaces the digit in a given cell at the mouse position
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
val: int
|
||||||
|
The digit for replacing
|
||||||
|
"""
|
||||||
self.sudoku_grid.replace_cell_number(self.mouse_h, self.mouse_w, val)
|
self.sudoku_grid.replace_cell_number(self.mouse_h, self.mouse_w, val)
|
||||||
self.grid_painter.update()
|
self.grid_painter.update()
|
||||||
if self.sudoku_grid.completion_check():
|
if self.sudoku_grid.completion_check():
|
||||||
self.puzzleFinished.emit()
|
self.puzzleFinished.emit()
|
||||||
|
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
|
"""Reimplemented from QGraphicsObject
|
||||||
|
"""
|
||||||
return QRectF(-5, -5, self.width+10, self.height+10)
|
return QRectF(-5, -5, self.width+10, self.height+10)
|
||||||
|
|
||||||
def paint(self, painter, style, widget=None):
|
def paint(self, painter, style, widget=None):
|
||||||
|
"""Reimplemented from QGraphicsObject. Draws the grid lines and the selection box, which follows the mouse.
|
||||||
|
"""
|
||||||
painter.setPen(self.default_pen)
|
painter.setPen(self.default_pen)
|
||||||
for line in self.thinlines:
|
for line in self.thinlines:
|
||||||
painter.drawLine(line)
|
painter.drawLine(line)
|
||||||
|
@ -256,7 +300,10 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
painter.drawRect(self.selection_box)
|
painter.drawRect(self.selection_box)
|
||||||
|
|
||||||
def hoverMoveEvent(self, event):
|
def hoverMoveEvent(self, event):
|
||||||
if not (self.freeze and self.drawn):
|
"""Reimplemented from QGraphicsObject. Updates the mouse grid coordinates as long as the grid is drawn
|
||||||
|
is not frozen.
|
||||||
|
"""
|
||||||
|
if (not self.freeze) and self.drawn:
|
||||||
box_w = bound_value(0, int(event.pos().x()/self.cell_width), 8)
|
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)
|
box_h = bound_value(0, int(event.pos().y() / self.cell_height), 8)
|
||||||
if box_w != self.mouse_w or box_h != self.mouse_h:
|
if box_w != self.mouse_w or box_h != self.mouse_h:
|
||||||
|
@ -266,9 +313,13 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. May be useless
|
||||||
|
"""
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
def mouseReleaseEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Emits buttonCLicked signal once the player releases the mouse button.
|
||||||
|
"""
|
||||||
if self.drawn:
|
if self.drawn:
|
||||||
w = (self.mouse_w + 0.5) * self.cell_width
|
w = (self.mouse_w + 0.5) * self.cell_width
|
||||||
h = (self.mouse_h + 0.5) * self.cell_height
|
h = (self.mouse_h + 0.5) * self.cell_height
|
||||||
|
@ -279,17 +330,25 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
self.buttonClicked.emit(0, 0, self.scribbling)
|
self.buttonClicked.emit(0, 0, self.scribbling)
|
||||||
|
|
||||||
def focusInEvent(self, event):
|
def focusInEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Unfreeze the grid on focus
|
||||||
|
"""
|
||||||
self.set_disabled(False)
|
self.set_disabled(False)
|
||||||
|
|
||||||
def focusOutEvent(self, event):
|
def focusOutEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Freeze the grid when out of focus
|
||||||
|
"""
|
||||||
self.set_disabled(True)
|
self.set_disabled(True)
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Check if scribble key is held, toggling on scribbling mode.
|
||||||
|
"""
|
||||||
if not event.isAutoRepeat():
|
if not event.isAutoRepeat():
|
||||||
if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
|
if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
|
||||||
self.scribbling = True
|
self.scribbling = True
|
||||||
|
|
||||||
def keyReleaseEvent(self, event):
|
def keyReleaseEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Check if scribble key is released, toggling off scribbling mode.
|
||||||
|
"""
|
||||||
if not event.isAutoRepeat():
|
if not event.isAutoRepeat():
|
||||||
if event.key() == SCRIBBLE_KEY and self.scribbling:
|
if event.key() == SCRIBBLE_KEY and self.scribbling:
|
||||||
self.scribbling = False
|
self.scribbling = False
|
||||||
|
@ -297,6 +356,9 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
# Defining the length to be drawn as a Property
|
# Defining the length to be drawn as a Property
|
||||||
@Property(float)
|
@Property(float)
|
||||||
def length(self):
|
def length(self):
|
||||||
|
"""float: The length of the grid lines to be drawn.
|
||||||
|
When set, the grid lines points are set.
|
||||||
|
"""
|
||||||
return self._length
|
return self._length
|
||||||
|
|
||||||
@length.setter
|
@length.setter
|
||||||
|
@ -319,10 +381,21 @@ class SudokuGrid(BaseSudokuItem):
|
||||||
|
|
||||||
|
|
||||||
class NumberRing(BaseSudokuItem):
|
class NumberRing(BaseSudokuItem):
|
||||||
|
"""The number ring which consists of the ringButtons for player input.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
loseFocus : Signal
|
||||||
|
An explicit signal for when the ring loses focus.
|
||||||
|
keyPressed : Signal(str, bool)
|
||||||
|
Emit when a digit is pressed, and whether scribbling mode is on
|
||||||
|
"""
|
||||||
loseFocus = Signal()
|
loseFocus = Signal()
|
||||||
keyPressed = Signal(str, bool)
|
keyPressed = Signal(str, bool)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
"""Create the ring buttons and layout. The parent argument is passed into BaseSudokuItem init method.
|
||||||
|
"""
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
@ -357,6 +430,8 @@ class NumberRing(BaseSudokuItem):
|
||||||
self.scribbling = False
|
self.scribbling = False
|
||||||
|
|
||||||
def finish_animation(self):
|
def finish_animation(self):
|
||||||
|
"""When the animation is finished, hide away and freeze the buttons and loses the focus if it closes, or
|
||||||
|
unfreeze it and set the transparency depending on mouse position if it opens"""
|
||||||
if self.radius == 0:
|
if self.radius == 0:
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
self.freeze_buttons(True)
|
self.freeze_buttons(True)
|
||||||
|
@ -368,8 +443,9 @@ class NumberRing(BaseSudokuItem):
|
||||||
else:
|
else:
|
||||||
self.set_buttons_transparent(True)
|
self.set_buttons_transparent(True)
|
||||||
|
|
||||||
# Toggle the animation to be play forward or backward
|
|
||||||
def toggle_anim(self, toggling):
|
def toggle_anim(self, toggling):
|
||||||
|
"""Toggle the animation to be play forward or backward
|
||||||
|
"""
|
||||||
self.freeze_buttons(True)
|
self.freeze_buttons(True)
|
||||||
if toggling:
|
if toggling:
|
||||||
self.anim.setDirection(QAbstractAnimation.Forward)
|
self.anim.setDirection(QAbstractAnimation.Forward)
|
||||||
|
@ -379,38 +455,64 @@ class NumberRing(BaseSudokuItem):
|
||||||
self.anim.start()
|
self.anim.start()
|
||||||
|
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
|
"""Reimplemented from QGraphicsObject
|
||||||
|
"""
|
||||||
return QRectF(-5-self.radius-self.cell_width/2, -5-self.radius-self.cell_height/2,
|
return QRectF(-5-self.radius-self.cell_width/2, -5-self.radius-self.cell_height/2,
|
||||||
self.cell_width+self.radius*2+10, self.cell_height + self.radius * 2 + 10)
|
self.cell_width+self.radius*2+10, self.cell_height + self.radius * 2 + 10)
|
||||||
|
|
||||||
# Reimplemented paint
|
|
||||||
def paint(self, painter, style, widget=None):
|
def paint(self, painter, style, widget=None):
|
||||||
|
"""Reimplemented from QGraphicsObject. Does nothing but is needed. May be used for fancy effects?
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def send_button_press(self, val):
|
def send_button_press(self, val):
|
||||||
|
"""Emits the keyPressed signal if any of the buttons is pressed, and attempts to close the ring
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
val : str
|
||||||
|
The digit to be emitted
|
||||||
|
"""
|
||||||
self.keyPressed.emit(val, self.scribbling)
|
self.keyPressed.emit(val, self.scribbling)
|
||||||
self.close_menu()
|
self.close_menu()
|
||||||
|
|
||||||
def freeze_buttons(self, freeze):
|
def freeze_buttons(self, freeze):
|
||||||
|
"""Freezes the button
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
freeze: bool
|
||||||
|
If true, freezes the button. Unfreezes otherwise.
|
||||||
|
"""
|
||||||
for btn in self.cell_buttons:
|
for btn in self.cell_buttons:
|
||||||
btn.set_freeze(freeze)
|
btn.set_freeze(freeze)
|
||||||
|
|
||||||
def focusOutEvent(self, event):
|
def focusOutEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Checks whether the mouse if over any of the buttons and refocus of so.
|
||||||
|
This is here because clicking the button can cause the ring to focus out for some reason.
|
||||||
|
"""
|
||||||
if not any(btn.isUnderMouse() for btn in self.cell_buttons):
|
if not any(btn.isUnderMouse() for btn in self.cell_buttons):
|
||||||
self.toggle_anim(False)
|
self.toggle_anim(False)
|
||||||
else:
|
else:
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
|
"""Reimplemented from QGraphicsObject. Similar reason to reimplementing focusOutEvent.
|
||||||
|
"""
|
||||||
if not any(btn.isUnderMouse() for btn in self.cell_buttons):
|
if not any(btn.isUnderMouse() for btn in self.cell_buttons):
|
||||||
self.toggle_anim(False)
|
self.toggle_anim(False)
|
||||||
else:
|
else:
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
|
|
||||||
def close_menu(self):
|
def close_menu(self):
|
||||||
|
"""Closes the ring if scribbling mode is off.
|
||||||
|
"""
|
||||||
if not self.scribbling:
|
if not self.scribbling:
|
||||||
self.toggle_anim(False)
|
self.toggle_anim(False)
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
|
"""Get the digit pressed and emits the keyPressed signal. Check also if scribbling mode is on
|
||||||
|
"""
|
||||||
if not event.isAutoRepeat():
|
if not event.isAutoRepeat():
|
||||||
if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
|
if (event.key() == SCRIBBLE_KEY) and not self.scribbling:
|
||||||
self.scribbling = True
|
self.scribbling = True
|
||||||
|
|
Loading…
Reference in New Issue