创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃

     2023-02-23     153

关键词:

【中文标题】创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃【英文标题】:Threaded Tkinter script crashes when creating the second Toplevel widget 【发布时间】:2011-04-03 19:02:02 【问题描述】:

我有一个 Python 脚本,它使用 Tkinter 作为 GUI。我的小脚本应该每 X 秒创建一个 Toplevel 小部件。当我运行我的代码时,第一个 Toplevel 小部件已成功创建,但当它尝试创建第二个时,程序崩溃了。

我正在做的是使用 after 方法在 root 的主循环旁边每 5 秒调用一次函数 startCounting。每次调用此函数时,我都会将 Toplevel 小部件对象附加到列表中并启动一个新线程,该线程有望运行新的主循环。

如果有人能解决这个问题,我将不胜感激。顺便说一句,这只是我目前用来解决我的问题的一个小脚本,它阻碍了我继续我真正的学校项目。

代码:

import threading,thread
from Tkinter import *


def startCounting():
    global root
    global topLevelList
    global classInstance

    topLevelList.append (Toplevel())
    topLevelList[len(topLevelList)-1].title("Child")
    classInstance.append(mainLoopThread(topLevelList[len(topLevelList)-1]))

    root.after(5000,startCounting)


class mainLoopThread(threading.Thread):
    def __init__(self,toplevelW):
        self.toplevelW = toplevelW
        threading.Thread.__init__(self)
        self.start()
    def run(self):
        self.toplevelW.mainloop()



global classInstance
classInstance = []
global topLevelList
topLevelList = []
global root

root = Tk() 
root.title("Main")
startCounting()
root.mainloop()

【问题讨论】:

【参考方案1】:

Tkinter 仅设计为从主线程运行。见the docs:

只需在 main 中运行所有 UI 代码 线程,并让作者写到 队列对象;例如

...下面是一个重要的示例,显示辅助线程将请求写入队列,主循环专门负责与 Tk 的所有直接交互。

许多对象和子系统不喜欢接收来自多个不同线程的请求,并且在 GUI 工具包的情况下,特别需要仅使用 ma​​in 线程的情况并不少见。

解决这个问题的正确 Python 架构始终是使用一个线程(主线程,如果必须的话)来服务于挑剔的对象或子系统;需要与所述子系统或对象交互的所有其他线程必须通过将请求排队到专用线程来获得它(如果某些请求需要结果,则可能在“返回队列”上等待结果)。这也是一个非常完善的用于通用线程的 Python 架构(我在“Python in a Nutshell”中详细阐述了它,但这是另一个主题;-)。

【讨论】:

我遇到了这个限制,这正是我使用的策略。我有一种检查所有队列的方法。然后我通过调用 root.after(ms, my_method) 在 Tkinter 的主循环中注册该方法。 my_method 中的最后一个调用是对 root.after 的另一个调用,以便 my_method 不断地在主循环中重新注册自己。重要的是 my_method 中的异常不会导致您错过向主循环注册。您可能希望在 try/finally 的最后部分调用 root.after。【参考方案2】:

Tkinter 在处理来自多个线程的输入时存在问题,我使用 mtTkinter 代替,您无需更改任何代码,一切都会正常工作。只需导入 mtTkinter 而不是 Tkinter。

你可以在这里得到它:

http://tkinter.unpythonic.net/wiki/mtTkinter

【讨论】:

【参考方案3】:

您是否有理由希望(或认为您需要)每个顶层窗口一个事件循环?单个事件循环能够处理数十个(如果不是数百或数千个)顶层窗口。而且,正如另一个答案中所指出的,您不能在单独的线程中运行此事件循环。

因此,要修复您的代码,您只需要使用一个事件循环,并让它在主线程中运行。

【讨论】:

非常感谢您的回答,多亏了你们,我才得以解决问题,我从来没有在这样的地方发过帖子,得到这么多帮助让我感到惊喜。

按下保存按钮pyqt5后关闭第二个小部件

】按下保存按钮pyqt5后关闭第二个小部件【英文标题】:Closesecondwidgetafterpressingsavebuttonpyqt5【发布时间】:2018-03-2512:29:19【问题描述】:我正在编写一个应用程序,其中主窗口小部件窗口打开第二个窗口小部件窗口,在第二个窗... 查看详情

特金特;新课程中的***

】特金特;新课程中的***【英文标题】:Tkinter;Toplevelinanewclass【发布时间】:2014-11-1510:42:53【问题描述】:我正在使用Python和Tkinter开发一个项目。我想把它模块化。主要问题之一是我的Toplevel小部件的实现太大了。我听说可以将... 查看详情

尝试添加第二个主屏幕小部件后,PendingIntents 不会触发

】尝试添加第二个主屏幕小部件后,PendingIntents不会触发【英文标题】:PendingIntentswon\'tfireafterattemptingtoadd2ndHomescreenwidget【发布时间】:2012-07-1118:23:11【问题描述】:我有一个widget,它设置了多个pendingIntents。只要我在主屏幕上... 查看详情

多种小部件尺寸

...,只是更大。我使用服务来更新我的小部件,所以我需要创建2个服务(通过远程视图等更新小部件中的数据)或者我可以让它更容易吗?当我添加中型小部件时,它会显示一个小部件,但它占用更多空间(144dpx72dp)并且没有更... 查看详情

如何在状态更改后强制小部件重新创建自己?

】如何在状态更改后强制小部件重新创建自己?【英文标题】:Howtoforceawidgettorecreateitselfafterastatechanged?【发布时间】:2021-03-0506:52:56【问题描述】:我正在学习如何在Flutter中与图像进行交互,在尝试photo_view时,我遇到了一个奇... 查看详情

如何将上下文传递给提供者的第二个小部件树

】如何将上下文传递给提供者的第二个小部件树【英文标题】:Howtopasscontexttosecondwidgettreeforprovider【发布时间】:2019-12-2601:56:36【问题描述】:我正在尝试将上下文传递给第二个小部件树(在函数中),但出现错误:尝试使用带... 查看详情

我在列中有几个扩展的小部件。首先我展开一个小部件。当我展开第二个时,第一个应该自动折叠

...有几个扩展的小部件。首先我展开一个小部件。当我展开第二个时,第一个应该自动折叠【英文标题】:Ihaveseveralexpandedwidgetsincolumn.FirstIexpandonewidget.whenIexpandingthesecondonefirstoneshouldautocollapse【发布时间】:2021-12-2405:15:22【问题描... 查看详情

如何在位于 tk.Canvas 内的 tk.Frame 中添加两个小部件?

】如何在位于tk.Canvas内的tk.Frame中添加两个小部件?【英文标题】:Howtoaddtwowidgetsinatk.Framelocatedinsideatk.Canvas?【发布时间】:2018-12-2004:00:24【问题描述】:我正在尝试用两个按钮做一个可滚动的应用程序。按下其中一个按钮应该... 查看详情

动态图像上传到备用gridster小部件上(代码片段)

...当我添加第一个小部件和上传图像时,上传的图像出现在第二个小部件上(当我添加第二个小部件时)。第一个小部件为空,然后图像出现在备用小部件上。以下是JSCode<scripttype="text/javascript">vargridster;var$color_picker=$('#color_pic... 查看详情

透明小部件不随其父级移动

...htheirparent【发布时间】:2012-05-0308:57:11【问题描述】:我创建了一个Qt应用程序,它显示了一个透明的小部件。我有另一个Qt应用程序已经在运行,它会显示一个表单。这个Qt应用程序将作为我的透明小部件的父级。更改透明小部... 查看详情

切换 kivy 小部件

...小部件。当那个小部件按钮被按下时,我希望它消失并被第二个小部件替换。这是两个小部件的.kv#uitest.kv<TestForm>:canvas:Rectangle:pos:self.center_x,0size 查看详情

在 Flutter 中按下切换开关时交换小部件

...它会显示它需要显示的小部件,而当另一个切换开关单击第二个小部 查看详情

c ++ boost线程问题[关闭]

...述】:我对C++多线程很陌生。我有以下代码流:主线程:创建队列创建第二个线程将项目添加到队列中结束第二个线程:如果队列有项目,则弹出它。(当标志设置为退出时,第二个线程退出)。问题是,一旦主函数完成将项目... 查看详情

将主要参数传递给第二个线程以启动 freeglut

...描述】:我是OpenGL和Freeglut的新手,我想为外围图形输出创建一个不是操作系统线程的线程。当我创建第二个线程时,我想传递主命令行参数,以便初始化freeglut。我正在使用:名称:Code::Blocks, 查看详情

如何使用 tkinter 创建多行条目?

】如何使用tkinter创建多行条目?【英文标题】:Howtocreateamultilineentrywithtkinter?【发布时间】:2012-03-2813:04:23【问题描述】:Entry小部件似乎只处理单行文本。我需要一个多行输入字段来输入电子邮件。有人知道怎么做吗?【问题... 查看详情

QtDesigner 中的自定义 qt 小部件

...发布时间】:2011-05-3003:50:44【问题描述】:我学习了如何创建自定义Qt小部件。我有两本手册。一个来自officialdocumentation,第二个来自C++GUIProgrammingwithQt4。我尝试了这些示例来创建自定义QtWidget并编译它们。之后,我将输出文件... 查看详情

为啥 gtkmm 有时会自动创建第二个线程?

】为啥gtkmm有时会自动创建第二个线程?【英文标题】:Whydoesgtkmmautomaticallycreateasecondthreadsometimes?为什么gtkmm有时会自动创建第二个线程?【发布时间】:2014-01-2723:56:07【问题描述】:如果我按原样编译和运行代码,该进程将使... 查看详情

Tkinter 将焦点设置在 Entry 小部件上

】Tkinter将焦点设置在Entry小部件上【英文标题】:TkintersetfocusonEntrywidget【发布时间】:2014-04-0509:19:17【问题描述】:这是我的代码:importtkinterastkuserData=tk.Tk()nbdays=tk.IntVar()mainframe=tk.Frame(userData,relief=\'raised\',borderwidth=1)tk.Label(mai 查看详情