Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python方法奇怪地暂停,直到tkinter根被关闭_Python_Debugging_Tkinter_Destroy - Fatal编程技术网

Python方法奇怪地暂停,直到tkinter根被关闭

Python方法奇怪地暂停,直到tkinter根被关闭,python,debugging,tkinter,destroy,Python,Debugging,Tkinter,Destroy,我正在使用Python3.4创建一个tkinter应用程序,它从API收集帖子,过滤帖子,允许用户查看帖子,并对每个帖子做出决定(忽略、删除、共享等) 用户需要选择一个日期和一些页面,然后单击“收集”按钮。然后程序从页面中获取帖子,并将其储存在“wholeList”中。 当用户单击第二个按钮“Review”时,必须过滤帖子并将其传递给审阅者 我的问题是,审阅者根本没有收到任何帖子,过滤器也没有。我在一些地方添加了一些调试print()语句,尤其是handlerCollect(),结果让我感到困惑

我正在使用Python3.4创建一个tkinter应用程序,它从API收集帖子,过滤帖子,允许用户查看帖子,并对每个帖子做出决定(忽略、删除、共享等)

用户需要选择一个日期和一些页面,然后单击“收集”按钮。然后程序从页面中获取帖子,并将其储存在“wholeList”中。 当用户单击第二个按钮“Review”时,必须过滤帖子并将其传递给
审阅者

我的问题是,审阅者根本没有收到任何帖子,
过滤器也没有。我在一些地方添加了一些调试
print()
语句,尤其是
handlerCollect()
,结果让我感到困惑,因此发表了这篇文章

当我单击“Collect”时,程序没有完成
handlerCollect()
回调方法,而是将其置于“DEBUG->1”和“DEBUG->2”之间的某个位置。主窗口没有冻结或任何东西,因为我可以单击“Review”,让它打印“DEBUG->4”,并打开
Reviewer
。当我关闭主窗口时,“DEBUG->0”、“DEBUG->2”和“DEBUG->3”最终打印出来,同时执行
handlerCollect()
方法的其余部分

同样的行为发生在
handlerChoosePage()
上,其中“DEBUG->0”被延迟,直到tkinter根(
TK()
)被销毁。我对结构化编程的知识告诉我,它应该是第一本印刷品。相反,这是最后一次。我最好的结论是,我不能正确地结束我的
Toplevel
mainloop()。我必须承认我以前从未遇到过这样的事情。我认为在
Toplevels
上结束
mainloop()
s的正确方法是使用
destroy()
,我很困惑为什么调用
mainloop()
s的方法会被搁置,直到
Tk
根被销毁;不太实际

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()
只需按下按钮,页面选择器模块就会被销毁:
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
mainloop的概念假设您首先创建和初始化对象(至少是应用程序启动时需要的对象,即不动态使用的对象),设置事件处理程序(实现接口逻辑),然后进入无限事件处理(用户界面本质上是什么),即主循环。所以,这就是为什么你认为它“挂起”。这叫做

重要的是,事件处理在一个地方完成,如下所示:

class GUIApp(tk.Tk):
   ...


app = GUIApp()
app.mainloop()

因此,当窗口关闭时,主循环将返回。

在我有时间重构代码之前,我通过在
destroy()
调用中添加以下行来解决问题:

self.quit() # Ends mainloop
self.master.destroy() # Destroys master (window)
我知道这并不能解决我代码的糟糕结构,但它回答了我的具体问题
destroy()
不会结束
TopLevel
s的
main循环,但
quit()
会结束。添加这一行可以使代码以可预测的方式执行


一旦我重构了我的代码并验证了@pmod关于
Tk()
mainloop将覆盖所有子
TopLevel
s的说法,我就会接受@pmod的答案。

你应该只有一个
mainloop
,而不是很多。如果您启动多个事件循环,您可能会得到嵌套的事件循环,这肯定会看到奇怪的效果。@schlenk:不可能:您肯定会得到嵌套的事件循环。我看到很多评论说应该只有一个
mainloop
(因为如果我回忆正确,每个进程只有一个事件循环)我很想遵循建议,但我不明白如何在每个辅助窗口上不调用
mainloop
s就可以创建一个包含多个窗口的应用程序……很简单。不要这样做。删除当前的mainloop()调用。只调用
root=tk.tk()
一次。所有其他窗口都应该是顶级窗口,通常以
root
作为第一个参数(但对于与另一个小部件连接的弹出窗口,请使用该小部件)。调用root.mainloop是最后一件事,就像pmod的回答一样。如果我遗漏了什么,我很抱歉,但这不是我构建代码的方式吗?我的问题是,事实上,
mainloop
在一个
TopLevel
上调用,当它的相关窗口关闭时不会返回,只有当
Tk
窗口关闭时才会返回。你说得对,但我不会为每个窗口打电话给Tk,是吗?@Antoinenderezchiel不,你没有。无法在事件处理程序中调用mainloop,这完全违反了该概念。mainloop是调用事件处理程序的地方。请注意,
启动器的主循环是从主程序调用的。基本上,我们回到了我问@schlenk和@BryanOakley的同一个问题:如果没有多个
mainloop
s,我怎么能有多个窗口?@AntoineEnderEzechiel你的特殊问题在哪里?试着提出更具体的问题。@AntoineEnderEzechiel简言之,将布局处理程序和动作处理程序的创建分开,然后您将看到
self.quit() # Ends mainloop
self.master.destroy() # Destroys master (window)