无法在Tkinter中创建新的标签。

huangapple go评论76阅读模式
英文:

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()

huangapple
  • 本文由 发表于 2023年7月11日 09:06:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658157.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定