我是Python和Tkinter的新手,因此,我无法弄清楚如何实现这个......
实际上,我有这个GUI:
,使用以下代码创建:
from tkinter import *
class RCP:
global handle_comm
global handle_rect
global handle_res
global spellerFrame
global color_rect_bg, color_rect_hl, color_text_bg, color_text_hl, color_text_wa
def __init__(self, targets, w_width, w_height):
self.n_row = len(targets)
self.n_col = len(targets[0])
self.w_width = w_width
self.w_height = w_height
self.targets = targets
self.canvasRoot = Tk()
self.canvasRoot.configure(background='grey')
self.setDefaults()
self.canvasRoot.bind("<<foo>>", self.flashRow)
# Initializate the main loop
self.createGrid()
self.canvasRoot.mainloop()
def setDefaults(self):
global color_rect_bg, color_rect_hl, color_text_bg, color_text_hl, color_text_wa
color_rect_bg = '#000000'
color_rect_hl = '#ffffff'
color_text_bg = '#757575'
color_text_hl = '#ffffff'
color_text_wa = '#ffff00'
global font_ratio_bg, font_ratio_hl
font_ratio_bg = 0.5
font_ratio_hl = 0.7
def createGrid(self):
# Calculate the maximum cell and font size that do not deform the commands' display
cell_size = min(self.w_height / self.n_row, self.w_width / self.n_col)
font_size = int(round(font_ratio_bg * cell_size))
result_size = int(round(cell_size/5))
# Create the canvas for the result text
global handle_res
resultLabel = Canvas(self.canvasRoot, width=self.w_width, height=result_size, bd=0,
highlightthickness=0, relief='ridge', background='grey')
resultLabel.grid(row=0, column=0, columnspan=self.n_col)
handle_res = resultLabel.create_text(2, round(result_size/2), text=' PRUEBA', fill=color_text_wa,
anchor='w', font=("Purisa", round(result_size/2), "bold"))
# Create the frame for the speller
global spellerFrame
spellerFrame = Canvas(self.canvasRoot, width=self.w_width, height=self.w_height, bd=0,
highlightthickness=0, relief='ridge')
spellerFrame.grid(row=1, column=0)
# Create the grid of commands
global handle_comm, handle_rect
handle_comm = [[None for i in range(self.n_col)] for j in range(self.n_row)]
handle_rect = handle_comm
for row_index in range(self.n_row):
for col_index in range(self.n_col):
x1 = col_index * cell_size
y1 = row_index * cell_size
x2 = (col_index + 1) * cell_size
y2 = (row_index + 1) * cell_size
handle_rect[row_index][col_index] = spellerFrame.create_rectangle(x1, y1, x2, y2, fill=color_rect_bg)
handle_comm[row_index][col_index] = \
spellerFrame.create_text(((x1+x2)/2,(y1+y2)/2), text=self.targets[row_index][col_index],
fill=color_text_bg, font=("Purisa", font_size, "bold"))
def flashRow(self):
'''Flashes the row specified as attribute'''
global spellerFrame
for col_index in range(self.n_col):
spellerFrame.itemconfig(handle_comm[1][col_index], fill=color_text_hl)
targets = [['A','B','C','D'],['E','F','G','H'],['I','J','K','L']]
myRCP = RCP(targets, 800, 600)
问题是我需要在GUI显示后修改字母的颜色。此视频显示了我想要实现的效果:https://www.youtube.com/watch?v=xvfxsNpaRGI
因此,我创建了flashRow
方法,该方法在调用时闪烁第1行。问题是我无法中断Tkinter的主循环以更新元素......
我已经阅读了after
命令,但我认为这不是一个合适的选项,因为我不知道我需要在什么时候调用flashRow
方法先验。
我可以使用generate_event
方法创建一个假事件处理程序来修改字母的颜色而不会干扰循环吗?如果是,怎么样?
提前致谢
答案 0 :(得分:2)
这将帮助您入门。将self.canvasRoot.bind("<<foo>>", self.flashRow)
更改为self.canvasRoot.after(10, self.flashRow)
。这将导致flashRow运行一次。在flashRow方法的底部,如果你想重复运行flashRow,计划它将使用after再次运行。
def flashRow(self):
'''Flashes the row specified as attribute'''
global spellerFrame
for col_index in range(self.n_col):
spellerFrame.itemconfig(handle_comm[1][col_index],
fill=color_text_hl)
# Put conditions or change the delay to something else,
# but this will reschedule flashRow in 100ms repeatedly.
self.canvasRoot.after(100, self.flashRow)
答案 1 :(得分:2)
widget.after(ms, callback, *args)
在第一次被程序读取后调用callback(*args)
ms
毫秒。因此,您可以定义一个回调方法,例如self.flashRow
,然后在__init__
中使用您的时间框架调用它,如:
self.canvasRoot.after(250, self.flashRow)
或:
self.flashRow
只要他们在<{em> mainloop
电话之前,两者都应该没问题。然后在你的回调函数self.flashRow
中,你需要确保它在250毫秒的时间范围内递归调用自身:
self.canvasRoot.after(250, self.flashRow)
我将self.flashRow
配置为有一些随机闪烁:
def flashRow(self):
'''Flashes the row specified as attribute'''
import random
global spellerFrame
_row = random.randint(0, 2)
_color = random.choice((color_text_hl, 'grey'))
print(_color)
for col_index in range(self.n_col):
spellerFrame.itemconfig(handle_comm[_row][col_index], fill=_color)
self.canvasRoot.after(250, self.flashRow)
另请参阅,您提供的非mcve代码的完整配置:
from tkinter import *
class RCP:
global handle_comm
global handle_rect
global handle_res
global spellerFrame
global color_rect_bg, color_rect_hl, color_text_bg, color_text_hl, color_text_wa
def __init__(self, targets, w_width, w_height):
self.n_row = len(targets)
self.n_col = len(targets[0])
self.w_width = w_width
self.w_height = w_height
self.targets = targets
self.canvasRoot = Tk()
self.canvasRoot.configure(background='grey')
self.setDefaults()
# Initializate the main loop
self.createGrid()
self.canvasRoot.after(250, self.flashRow)
self.canvasRoot.mainloop()
def setDefaults(self):
global color_rect_bg, color_rect_hl, color_text_bg
global color_text_hl, color_text_wa
color_rect_bg = '#000000'
color_rect_hl = '#ffffff'
color_text_bg = '#757575'
color_text_hl = '#ffffff'
color_text_wa = '#ffff00'
global font_ratio_bg, font_ratio_hl
font_ratio_bg = 0.5
font_ratio_hl = 0.7
def createGrid(self):
# Calculate the maximum cell and font size that do not
# deform the commands' display
cell_size = min(self.w_height / self.n_row, self.w_width / self.n_col)
font_size = int(round(font_ratio_bg * cell_size))
result_size = int(round(cell_size/5))
# Create the canvas for the result text
global handle_res
resultLabel = Canvas(self.canvasRoot, width=self.w_width,
height=result_size, bd=0,
highlightthickness=0, relief='ridge', background='grey')
resultLabel.grid(row=0, column=0, columnspan=self.n_col)
handle_res = resultLabel.create_text(2, round(result_size/2),
text=' PRUEBA', fill=color_text_wa, anchor='w',
font=("Purisa", round(result_size/2), "bold"))
# Create the frame for the speller
global spellerFrame
spellerFrame = Canvas(self.canvasRoot, width=self.w_width,
height=self.w_height, bd=0,
highlightthickness=0, relief='ridge')
spellerFrame.grid(row=1, column=0)
# Create the grid of commands
global handle_comm, handle_rect
handle_comm = [[None for i in range(self.n_col)] for j in range(self.n_row)]
handle_rect = handle_comm
for row_index in range(self.n_row):
for col_index in range(self.n_col):
x1 = col_index * cell_size
y1 = row_index * cell_size
x2 = (col_index + 1) * cell_size
y2 = (row_index + 1) * cell_size
handle_rect[row_index][col_index] = spellerFrame.create_rectangle(x1,
y1, x2, y2, fill=color_rect_bg)
handle_comm[row_index][col_index] = \
spellerFrame.create_text(((x1+x2)/2,(y1+y2)/2),
text=self.targets[row_index][col_index],
fill=color_text_bg,
font=("Purisa", font_size, "bold"))
def flashRow(self):
'''Flashes the row specified as attribute'''
import random
global spellerFrame
_row = random.randint(0, 2)
_color = random.choice((color_text_hl, 'grey'))
print(_color)
for col_index in range(self.n_col):
spellerFrame.itemconfig(handle_comm[_row][col_index], fill=_color)
self.canvasRoot.after(250, self.flashRow)
targets = [['A','B','C','D'],['E','F','G','H'],['I','J','K','L']]
myRCP = RCP(targets, 800, 600)