我正在使用Python 3.4创建一个tkinter应用程序,它从API收集帖子,过滤它们并允许用户查看它们并为每个应用程序做出决定(忽略,删除,共享等)
用户需要选择日期和一些页面,然后单击“收集”按钮。程序然后从页面中获取帖子并将它们存储在“wholeList”中。
当用户点击第二个按钮“审核”时,必须过滤这些帖子并将其传递给Reviewer
。
我的问题是评论员根本没有收到任何帖子,Filterer
也没有。我在某些地方添加了一些调试print()
语句,特别是handlerCollect()
,结果令我困惑,因此这篇文章。
当我点击'Collect'时,程序将其置于“DEBUG-> 1”和“DEBUG-> 2”之间的某个位置,而不是完成handlerCollect()
回调方法。主窗口不会冻结或任何东西,因为我可以单击“查看”并打印“DEBUG-> 4”并打开Reviewer
。当我关闭主窗口时,“DEBUG-> 0”“DEBUG-> 2”和“DEBUG-> 3”最后打印,同时执行handlerCollect()
方法的其余部分。
handlerChoosePage()
发生同样的行为,“DEBUG-> 0”被延迟,直到tkinter根(TK()
)被销毁。我对结构编程的了解告诉我它应该是第一个印刷的。相反,这是最后一次。我最好的结论是,我不能正确地结束我的Toplevel
mainloop()
。我不得不承认我以前从未遇到过这样的事情。我认为在mainloop()
上结束Toplevels
的正确方法是destroy()
,我很困惑为什么调用mainloop()
的方法会被搁置到Tk
1}} root被摧毁;不太实际。
from GUICollector import GUICollector as Collector
class Launcher(tk.Frame):
def __init__(self, *args, **kwargs):
...
self.allPagesCB = Checkbutton(self.dateFrame, text="Collect for all pages",
variable = self.allPagesVar, command=self.handlerChoosePage)
self.collectBtn = Button(self, text="Collect", command=self.handlerCollect)
self.reviewBtn = Button(self, text="Review", command=self.handlerReview)
def handlerChoosePage(self):
if self.allPagesVar.get() == 0:
child = tk.Toplevel(self)
selector = PageSelector(self.toCollect, child)
selector.pack(side="top", fill="both", expand=True)
selector.mainloop()
print("DEBUG->0")
def handlerCollect(self):
print("DEBUG->1")
self.collect()
print("DEBUG->4")
for post in self.collector.getPosts():
if post not in self.wholeList:
print("...")
self.wholeList.append(post.copy())
self.collector = None
print(len(self.wholeList), "posts in wholeList")
def collect(self):
window = tk.Toplevel(self)
self.collector = Collector(self.toCollect, self.sinceEpoch, window)
self.collector.grid(row=0,column=0)
self.collector.after(500, self.collector.start)
print("DEBUG->2")
self.collector.mainloop() # This is what seems to hang indefinetly
print("DEBUG->3")
def handlerReview(self):
print("DEBUG->5")
print(len(self.wholeList), "posts in wholeList")
filterer = Filterer(self.wholeList)
self.wholeList = filterer.done[:]
window = tk.Toplevel()
reviewer = Reviewer(self.wholeList[:], window)
reviewer.grid(row=0,column=0)
reviewer.mainloop()
GUICollector模块根本不需要用户进行任何交互。 这个模块似乎工作得很好:完成它的工作,显示它已完成,然后在指定的延迟后关闭。 由于GuiCollector mainloop()似乎是悬挂的罪魁祸首,这就是我如何结束它:
class GUICollector(tk.Frame):
def __init__(self, pagesList, since, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
def start(self, event=None):
if some_logic:
self.after(250,self.start)
else:
self.done() # Does get called.
def done(self):
# Some StringVar update to display we are done on screen
self.after(1250, self.validate)
def validate(self):
self.master.destroy()
只需按一下按钮,即可通过相同的调用销毁PageSelector模块:self.master.destroy()
以下是该程序的重要输出:
DEBUG->1
DEBUG->2
=> collected data of page [PageName]
=> Found 3 posts in page
DEBUG->5
0 posts in wholeList
[The main window (Launcher) is manually closed at this point]
DEBUG->3
DEBUG->4
...
...
...
3 posts in wholeList
DEBUG->0
答案 0 :(得分:1)
mainloop 的概念假定您首先创建和初始化对象(好吧,至少是应用程序启动时需要的,即动态不使用的),设置事件处理程序(实现接口逻辑)和然后进入无限事件处理(用户界面本质上是什么),即主循环。所以,这就是为什么你会把它看成是#34;挂起"。这称为event-driven programming
重要的是,这个事件处理是在一个地方完成的,就像那样:
class GUIApp(tk.Tk):
...
app = GUIApp()
app.mainloop()
因此,当窗口死亡时,mainloop会返回。
答案 1 :(得分:0)
在我有时间重构代码之前,我通过在destroy()
次调用中添加以下行来解决问题:
self.quit() # Ends mainloop
self.master.destroy() # Destroys master (window)
我理解这并不能解决我的代码的错误结构,但它回答了我的具体问题。 destroy()
并未结束mainloop
的{{1}},TopLevel
也是如此。添加此行会使我的代码以可预测的方式执行。
一旦我重构了我的代码并验证他声称quit()
主循环将涵盖所有孩子Tk()
,我将接受@pmod的答案。