英文:
Can not create a new Label in Tkinter
问题
在这个程序中,我模拟了连接失败的情况。首先,会显示一个 "Connecting..." 标签。在连接失败后,标签会变成 "Connection Failed." 并显示一个 "Try Again" 按钮。当按下 "Try Again" 按钮时,我想要销毁 "Connection Failed." 标签并创建一个新的 "Connecting..." 标签。销毁操作成功进行,但新的 "Connecting..." 标签无法创建,我看不到它。我还尝试使用 config
方法将 "Connection Failed." 文本修改为 "Connecting...",但也没有起作用。这很奇怪...
import time
import tkinter as tk
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# 创建主窗口
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry(f"{screen_width}x{screen_height}")
is_connection_done = tk.StringVar(value="")
try_again_button = None
connecting_message = None
def connect():
global try_again_button, connecting_message, root
print('尝试连接')
if try_again_button:
try_again_button.destroy()
try_again_button = None
connecting_message.destroy()
connecting_message = tk.Label(root, text="Connecting...")
connecting_message.pack()
time.sleep(2)
is_connection_done.set("failed")
connecting_message = tk.Label(root, text="Connecting...")
connecting_message.pack()
connection_event_id = root.after(1000, connect)
while True:
is_connection_done.set("")
root.wait_variable(is_connection_done)
if is_connection_done.get() == 'done':
connecting_message.config(text='连接成功!')
break
elif is_connection_done.get() == 'failed':
print('连接失败')
connecting_message.config(text='连接失败。')
try_again_button = tk.Button(root, text='重试', command=connect)
try_again_button.pack()
# 启动事件循环
root.mainloop()
英文:
In this program, I have simulated a failure in a connection. At first, a "Connecting..." label is displayed. After the failure, the label will change to "Connection Failed." and a try again button is displayed. When the try again button is pressed, I want to destroy the "Connection Failed." label and create a new "Connecting..." label. The destruction happens successfully but a new "Connecting..." label can not be created and I can not see that. I also tried to modify the "Connection Failed." text to "Connecting..." using the config method but it does not work either. It is weird...
import time
import tkinter as tk
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# Create main window
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry(f"{screen_width}x{screen_height}")
is_connection_done = tk.StringVar(value="")
try_again_button = None
connecting_message = None
def connect():
global try_again_button, connecting_message, root
print('Trying to connect')
if try_again_button:
try_again_button.destroy()
try_again_button = None
connecting_message.destroy()
connecting_message = tk.Label(root, text="Connecting...")
connecting_message.pack()
time.sleep(2)
is_connection_done.set("failed")
connecting_message = tk.Label(root, text="Connecting...")
connecting_message.pack()
connection_event_id = root.after(1000, connect)
while True:
is_connection_done.set("")
root.wait_variable(is_connection_done)
if is_connection_done.get() == 'done':
connecting_message.config(text='Connected Successfully!')
break
elif is_connection_done.get() == 'failed':
print('Failed')
connecting_message.config(text='Connection Failed.')
try_again_button = tk.Button(root, text='Try Again', command=connect)
try_again_button.pack()
# Start event loop
root.mainloop()
答案1
得分: 0
由于while
循环阻止了root.mainloop()
的执行,所以tkinter
主循环无法控制并更新小部件。
你可以在connect()
函数的connecting_message.pack()
之后调用connecting_message.update()
来强制更新。
然而,在tkinter
应用程序中不推荐使用while
循环。建议使用after()
代替。
import time
import tkinter as tk
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# 创建主窗口
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry(f"{screen_width}x{screen_height}")
is_connection_done = tk.StringVar(value="")
def connect():
# 隐藏"Try Again"按钮
try_again_button.pack_forget()
# 更新标签文本
connecting_message.config(text="连接中...")
# 使用after()代替time.sleep(2)
root.after(2000, is_connection_done.set, "failed")
connecting_message = tk.Label(root, text="连接中...")
connecting_message.pack()
connection_event_id = root.after(1000, connect)
# 创建按钮但最初隐藏
try_again_button = tk.Button(root, text='再试一次', command=connect)
def checking():
is_connection_done.set("")
root.wait_variable(is_connection_done)
if is_connection_done.get() == 'done':
connecting_message.config(text='连接成功!')
return # 停止检查循环
elif is_connection_done.get() == 'failed':
connecting_message.config(text='连接失败。')
# 显示"再试一次"按钮
try_again_button.pack()
root.after(100, checking) # 安排下一次检查
# 启动检查循环
checking()
# 启动事件循环
root.mainloop()
英文:
Since the while loop blocks root.mainloop()
from executing, so tkinter
mainloop cannot take control and update widgets.
You can call connecting_message.update()
after connecting_message.pack()
inside connect()
to force the update.
However, it is not recommended to use while loop in a tkinter
application. Use after()
instead.
import time
import tkinter as tk
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
# Create main window
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry(f"{screen_width}x{screen_height}")
is_connection_done = tk.StringVar(value="")
def connect():
# hide the "Try Again" button
try_again_button.pack_forget()
# update label text
connecting_message.config(text="Connecting...")
# use after() instead of time.sleep(2)
root.after(2000, is_connection_done.set, "failed")
connecting_message = tk.Label(root, text="Connecting...")
connecting_message.pack()
connection_event_id = root.after(1000, connect)
# create the button but initially hidden
try_again_button = tk.Button(root, text='Try Again', command=connect)
def checking():
is_connection_done.set("")
root.wait_variable(is_connection_done)
if is_connection_done.get() == 'done':
connecting_message.config(text='Connected Successfully!')
return # stop the checking loop
elif is_connection_done.get() == 'failed':
connecting_message.config(text='Connection Failed.')
# show the "Try Again" button
try_again_button.pack()
root.after(100, checking) # schedule next checking
# start checking loop
checking()
# Start event loop
root.mainloop()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论