用许多小部件更新gui时,Tkinter闪烁



是否可以在不闪烁的情况下更新框架(删除现有的小部件并创建新的(?这个例子被简化了。事实上,表单可以按不同的顺序包含不同的小部件,因此更新现有的小部件不是解决方案。但如果你按A、B、A、A。。。我仍然看到一些令人不安的闪烁。我希望看到两个图像之间的即时切换。我问这个问题的原因是,我有一个更复杂的应用程序,它显示类似动态表单的东西(几十行中有选项,每个选项都可以导致该选项下的表单更改、隐藏或添加选项等(。我注意到了奇怪的行为:当我更改任何不影响其他选项的选项,并且刷新表单时(删除小部件并创建相同的内容(,我看到闪烁。但是,当我更改影响表单的选项(添加另一个选项(时,虽然过程仍然相同(销毁所有小部件并创建新的小部件(,但没有闪烁。

编辑:添加到youtube视频的链接

import tkinter as tk

class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry('400x900')
self.resizable(width=0, height=0)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1, uniform='a')
self.grid_columnconfigure(1, weight=1, uniform='a')
self.grid_columnconfigure(2, weight=1, uniform='a')
tk.Button(text='A', command=lambda: self.add(20)).grid(row=0, column=0, sticky='nsew')
tk.Button(text='B', command=lambda: self.add(30)).grid(row=0, column=1, sticky='nsew')
tk.Button(text='clear', command=lambda: self.add(0)).grid(row=0, column=2, sticky='nsew')
self.form = tk.Frame()
self.form.grid_columnconfigure(0, weight=1)
self.form.grid_columnconfigure(1, weight=1)
self.form.grid(row=1, column=0, columnspan=3, sticky='nsew')
self.mainloop()
def add(self, n):
# self.form.grid_remove()
# self.update()
for child in self.form.winfo_children():
child.destroy()
for i in range(0, 2 * n, 2):
name = f'Row {i // 2 + 1}'
tk.Label(master=self.form, text=name, bg='sky blue').grid(row=i, column=0, sticky='nsew')
tk.Button(master=self.form, text=name, relief='flat', bg='white').grid(row=i, column=1, sticky='nsew')
tk.Frame(master=self.form, height=1, bg='black').grid(row=i + 1, column=0, columnspan=2, sticky='nsew')
# self.form.grid()

if __name__ == '__main__':
app = App()

我找到了一个很好的解决方案,但我认为应该有更好的方法来实现这一点(使用一个Frame(。在这个例子中,我交替使用两帧。一个是";在背景中";而第二个";在前景中";。当添加小部件时,我总是在后台使用它,然后我调用tkrise方法将它移动到前台。update_idlettasks((也很重要。正如您在视频中看到的,这看起来比上一个示例好100%。当您想显示一个对象的属性,然后切换到另一个对象并显示其属性时,这一点很重要。当两个对象只有一个不同的值时,您可以很容易地用眼睛识别哪个对象在切换过程中发生了变化。但当整个画面在切换过程中闪烁时,几乎不可能发现变化。

链接到youtube视频


import tkinter as tk

class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry('400x900')
self.resizable(width=0, height=0)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(0, weight=1, uniform='a')
self.grid_columnconfigure(1, weight=1, uniform='a')
self.grid_columnconfigure(2, weight=1, uniform='a')
tk.Button(text='A', command=lambda: self.add(20)).grid(row=0, column=0, sticky='nsew')
tk.Button(text='B', command=lambda: self.add(30)).grid(row=0, column=1, sticky='nsew')
tk.Button(text='clear', command=lambda: self.add(0)).grid(row=0, column=2, sticky='nsew')
self.forms = (tk.Frame(self), tk.Frame(self))
for form in self.forms:
form.grid_columnconfigure(0, weight=1)
form.grid_columnconfigure(1, weight=1)
form.grid(row=1, column=0, columnspan=3, sticky='nsew')
self.form = self.forms[1]
self.mainloop()
def switch_form(self):
for form in self.forms:
if form is not self.form:
self.form = form
break
def add(self, n):
for child in self.form.winfo_children():
child.destroy()
self.switch_form()
for i in range(0, 2 * n, 2):
name = f'Row {i // 2 + 1}'
tk.Label(master=self.form, text=name, bg='sky blue').grid(row=i, column=0, sticky='nsew')
tk.Button(master=self.form, text=name, relief='flat', bg='white').grid(row=i, column=1, sticky='nsew')
tk.Frame(master=self.form, height=1, bg='black').grid(row=i + 1, column=0, columnspan=2, sticky='nsew')
self.update_idletasks()
self.form.tkraise()

if __name__ == '__main__':
app = App()

最新更新