Python 忘记和销毁帧无效
我有一个程序,用来检查用户是否有网络连接。如果没有,程序会显示一个框,上面写着要打开网络连接。然后程序会检查状态是否改变,如果改变了,就会显示登录界面。但是我就是无法去掉 noNetworkConnectionScreen
这个界面。
loadFrame
是显示“启动画面”的框。
class AppUI(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.parent.title("Redux")
self.loadFrame = Frame(self)
self.initLogin()
def initLogin(self):
internet_is_on = False
#check 3 times to be sure
for i in range(3):
#check the internet connection by pinging to google (returns True or False)
if db.internetOn():
internet_is_on = True
if internet_is_on:
self.initLoginScreen()
else:
self.initLoadScreen()
thread1 = threading.Thread(target=self.checkNetwork)
thread1.start()
我也试过 grid_forget
,结果程序崩溃了:
def checkNetwork(self):
internet_is_off = True
while internet_is_off:
if db.internetOn():
internet_is_off = False
self.loadFrame.pack_forget()
self.loadFrame.destroy()
self.initLoginScreen()
else:
time.sleep(2)
这里是我初始化加载界面的代码:
def initLoadScreen(self):
self.loadFrame.grid(row=0, column=0, pady=(150,0))
self.lblUser = Label(self.loadFrame, text="HI", font=('Arial', 60), foreground="#666666")
self.lblUser.grid(row=0, column=0)
self.canvas = Canvas(self.loadFrame, width = 121, height = 81)
self.canvas.grid(row=1, column=0)
self.loader = PhotoImage(file = 'loader.gif')
self.canvas.create_image(121, 81, image = self.loader, anchor = NW)
self.lblNetwork = Label(self.loadFrame, text="please make sure you have an active network connection", font=('Arial', 16), foreground="#666666")
self.lblNetwork.grid(row=2, column=0)
我发现 lblNetwork
上的字在两边被切掉了,但这个框就是不消失。有没有什么好主意?
2 个回答
-1
是不是需要强制刷新一下屏幕呢?
有时候,pyGTK 需要这样做(不过你是在用 pyGTK 吗?):
while gtk.events_pending(): # this forces the refresh of the screen
gtk.main_iteration()
1
销毁一个小部件或者“忘记”它是从屏幕上移除小部件的正确方法。问题几乎肯定和你使用线程有关。Tkinter 这个库不是线程安全的,应该只在一个线程中使用。如果你在一个线程中创建了小部件,就不应该在其他线程中使用它。在这种情况下,你试图从一个不同于创建它的线程中销毁一个框架。
你需要做的是在这些线程之间建立某种通信方式——可以是一个队列或者一个共享的(非 Tkinter 的)变量。因为你只是检查一个布尔标志,所以一个简单的共享变量就可以了。在你的主程序中,你可以通过在主线程中使用一个简单的 after
循环来检查这个变量:
def check_network(self):
if the_network_is_down:
<display a message>
else:
<remove the message>
# check once a second
self.after(1000, self.check_network)
另外,如果你对一个小部件调用了 destroy
,就不需要再调用 grid_forget
或者 pack_forget
——一旦小部件被销毁,就不需要做其他任何事情了。