So currently I am creating Sudoku in PyQt5. So, far I have Board.py which just generates new boards. Currently I am working on Play.py, which should be able to click on empty squares and be able to change it with the press of a keyboard button(keypress). In Play.py I have finished everything - All the numbers are put into a board and I am able to click on buttons and it initiates a keypress. But, the way I coded it, all the buttons are stored into a list (I did this because I wanted the code to look clean) and it only updates the last button. Instead of it updating the last button, I would like it to update the button that was most recently clicked.
I have tried many things but what I have narrowed it down to currently is to find the position of the button in the list of all buttons(all_buttons) and do something from there but I'm not sure. So, how would I be able to take the key press and put it into the button that was recently pressed?
Here is Board.py. It just generates new boards it is unnecessary to look at.
import random
import numpy as np
# populates a row in random spaces
def populate():
row = [0] * 9
num_in_box = random.randint(3, 6)
while True:
spot = random.randint(0, 8)
r = random.randint(1, 9)
if r not in row:
row[spot] = r
if row.count(0) == (9 - num_in_box):
break
return row
# populates a grid in random spaces - has duplicates in column, row and box
mapped = list()
for x in range(9): mapped.append(populate())
# checks every number in column and row and returns numbers in list
def col_row_nums(array, row, col):
check_col = [j for j in array[:, col] if j != 0]
check_row = [i for i in array[row] if i != 0]
if array[row][col] in check_col:
check_col.remove(array[row][col])
return check_col + check_row
# checks every number box and returns numbers in list
def box_nums(array, box_row):
reshaped_box = np.reshape(array, (27, 3))
list_boxes_in_rows = list()
for a in range(3):
for b in range(3):
for c in range(3):
p2 = list(np.reshape((reshaped_box[c::3]), (3, 9)))
for d in range(3): list_boxes_in_rows.append(p2[a])
array_boxes_in_rows = np.array(list_boxes_in_rows)
return [k for k in array_boxes_in_rows[box_row] if k != 0]
# removes any duplicates so each column, row and box all have only one set of numbers 1 - 9
def finalize_board():
box_rows_num = -1
for x in range(9):
for y in range(9):
box_rows_num += 1
arr = np.array(mapped)
possible_nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
col_row_duplicates = list()
box_duplicates = list()
used_nums = set(col_row_nums(arr, x, y)) | set(box_nums(arr, box_rows_num))
for w in used_nums:
col_row_count = col_row_nums(arr, x, y).count(w)
box_count = box_nums(arr, box_rows_num).count(w)
if col_row_count > 1: col_row_duplicates.append(w)
if box_count > 1: box_duplicates.append(w)
if mapped[x][y] in col_row_duplicates or mapped[x][y] in box_duplicates:
remaining_nums = list(set(possible_nums) - set(used_nums))
if len(remaining_nums) > 0: mapped[x][y] = random.choice(remaining_nums)
return mapped
Next is Play.Py.
import sys
from pynput import keyboard
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
import Board
class MainWindow(qtw.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# -------------------------------------------------------------------------------------------
all_buttons = list()
layout = qtw.QGridLayout()
layout.setSpacing(0)
board = Board.finalize_board()
y_num = -1
for x, rows in enumerate(board):
for y, cell in enumerate(rows):
y += 1
if cell == 0: cell = ' '
button = qtw.QPushButton(str(cell), self)
button.setFixedHeight(100)
button.setFixedWidth(100)
layout.addWidget(button, x, y)
if cell == ' ':
button.clicked.connect(lambda: pressed())
button.setStyleSheet('QPushButton {background-color: #e3efff; color: black;}')
else:
button.setEnabled(False)
button.setStyleSheet('QPushButton {background-color: #ebebeb; color: black;}')
all_buttons.append(button)
def pressed():
with keyboard.Events() as events:
# maybe - ?? HOW TO RETURN POSITION OF BUTTON IN ALL_BUTTONS
event = events.get(1e6)
x = event.key
print(str(x))
button.setText(str(x))
self.setLayout(layout)
# -------------------------------------------------------------------------------------------
self.show()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())