使用按键单击时如何更改pyqt5中的按钮文本
问题描述
所以目前我正在 PyQt5 中创建数独.所以,到目前为止,我有 Board.py,它只是生成新的板.目前我正在研究 Play.py,它应该能够点击空白方块并能够通过按下键盘按钮(按键)来更改它.在 Play.py 中,我已经完成了所有操作 - 所有数字都放入了一块板上,我可以单击按钮并启动按键.但是,按照我的编码方式,所有按钮都存储在一个列表中(我这样做是因为我希望代码看起来干净)并且它只更新最后一个按钮.我希望它更新最近单击的按钮,而不是更新最后一个按钮.
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.
我已经尝试了很多东西,但我目前将其缩小到的是在所有按钮(all_buttons)列表中找到按钮的位置并从那里做一些事情,但我不确定.那么,如何才能将按键按下并将其放入最近按下的按钮中?
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?
这里是 Board.py.它只是生成了不需要查看的新板.
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
接下来是 Play.Py.
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_())
解决方案
你快到了.使用 keyPressEvent
点击这里.
import sys
from PyQt5.QtWidgets import (QApplication, QWidget)
from PyQt5.Qt import Qt
class MainWindow(QWidget):
def __init__(self):
super().__init__()
def keyPressEvent(self, event):
print(chr(event.key()))
def test_method(self):
print('Space key pressed')
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = MainWindow()
demo.show()
sys.exit(app.exec_())
event.key()
将始终返回一个整数.您可以使用内置的 chr(int)
函数来获取密钥,问题是我们无法识别字母和数字以外的密钥.如果您还想要其他键,请使用条件.
event.key()
will always return an integer. You can use the built-in chr(int)
function to get the key, the problem is we can't identify keys other than alphabets and numbers. If you want other keys as well, use conditions.
def keyPressEvent(self, event):
if event.key() == Qt.Key_Space:
print("Space pressed")
# Qt.Key_Shift for shift key, Qt.Key_Control for Ctrl key.
这是最终代码:阅读edit2
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5.QtCore import pyqtSlot
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(self)
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.setCursor(qtc.Qt.PointingHandCursor)
button.mousePressEvent = lambda event: self.mousePressEvent(event)
button.setStyleSheet('QPushButton {background-color: #e3efff; color: black;}')
else:
button.setEnabled(False)
button.setStyleSheet('QPushButton {background-color: #ebebeb; color: black;}')
all_buttons.append(button)
self.last_clicked = ''
self.setLayout(layout)
# -------------------------------------------------------------------------------------------
self.show()
def keyPressEvent(self, event):
k = (chr(event.key()))
self.last_clicked.setText(k)
self.last_clicked.setStyleSheet("background-color: #e3efff; color: black;")
def mousePressEvent(self, event):
widget = self.childAt(event.pos())
widget.setStyleSheet("background-color: #e3efff; color: black; border: 1px solid red")
print(widget.pos())
self.last_clicked = widget
return qtw.QWidget.mousePressEvent(self, event)
# -------------------------------------------------------------------------------------------
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = MainWindow()
sys.exit(app.exec_())
现在,当您按下某个键时,它会更新最近单击按钮的文本.您可能想添加一些尝试,除了 keyPressEvent
和 setText 函数
Now when you press a key, it updates the text of the recently clicked button. You might want to add some try except to the keyPressEvent
and setText function
编辑 2:我不完全知道为什么第一个按钮被选中,我猜 mousePressEvent
有问题.它首先返回第一个小部件,然后返回实际单击的按钮.我调整了一些东西,现在可以正常工作了.
EDIT 2:
I don't exactly know why the first button gets selected, I'm guessing something's wrong with the mousePressEvent
. It first returns the first widget and then the actual button that was clicked. I tweaked a few things and it now works fine.
我改变的东西:
我创建了一个新列表
self.available_buttons
.它包含所有空的/可点击的按钮.
I created a new list
self.available_buttons
. It contains all the empty/clickable buttons.
只要按下一个空按钮,代码就会遍历列表并搜索 last_clicked
小部件.如果找到 last_clicked
小部件,它会突出显示该按钮并将所有其他按钮更改为正常(无边框颜色).
Whenever an empty button is pressed, the code goes through the list and searches for last_clicked
widget. If the last_clicked
widget is found, it highlights the button and changes all other buttons to normal(no border color).
class MainWindow(qtw.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# -------------------------------------------------------------------------------------------
all_buttons = list() # contains all buttons
self.available_buttons = list() # contains clickable buttons
layout = qtw.QGridLayout(self)
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.setCursor(qtc.Qt.PointingHandCursor)
button.mousePressEvent = lambda event: self.mousePressEvent(event)
button.setStyleSheet('QPushButton {background-color: #e3efff; color: black;}')
self.available_buttons.append(button) # appends empty buttons to the list
else:
button.setEnabled(False)
button.setStyleSheet('QPushButton {background-color: #ebebeb; color: black;}')
all_buttons.append(button)
self.last_clicked = ''
self.setLayout(layout)
self.show()
# -------------------------------------------------------------------------------------------
def keyPressEvent(self, event):
k = (chr(event.key()))
self.last_clicked.setText(k)
self.last_clicked.setStyleSheet("background-color: #e3efff; color: black;")
def mousePressEvent(self, event):
widget = self.childAt(event.pos())
self.last_clicked = widget
for button in self.available_buttons: #searches for clicked button
if widget == button:
button.setStyleSheet("background-color: #e3efff; color: black; border: 1px solid red") # adds border to clicked button
else:
button.setStyleSheet("background-color: #e3efff; color: black;") # all the other buttons go back to their normal state
return qtw.QWidget.mousePressEvent(self, event)
# -------------------------------------------------------------------------------------------
相关文章