创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃 [英] Threaded Tkinter script crashes when creating the second Toplevel widget

查看:23
本文介绍了创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Python script which uses Tkinter for the GUI. My little script should create a Toplevel widget every X seconds. When I run my code, the first Toplevel widget is created successfully, but when it tries to create a second one the program crashes.

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

What I am doing is using the after method to call the function startCounting every 5 seconds alongside root's mainloop. Every time this function is called, I append a Toplevel widget object into a list and start a new thread which hopefully will be running the new mainloop.

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

I would be very grateful if someone could figure this problem out. By the way, this is just a little script that I am currently using to solve my problem, which is preventing me from going on with my real school project.

代码:

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

推荐答案

Tkinter 旨在仅从主线程运行.请参阅文档:

Tkinter is designed to run from the main thread, only. See the docs:

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

Just run all UI code in the main thread, and let the writers write to a Queue object; e.g.

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

...and a substantial example follows, showing secondary threads writing requests to a queue, and the main loop being exclusively responsible for all direct interactions with Tk.

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

Many objects and subsystems don't like receiving requests from multiple various threads, and in the case of GUI toolkit it's not rare to need specfically to use the main thread only.

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

The right Python architecture for this issue is always to devote a thread (the main one, if one must) to serving the finicky object or subsystem; every other thread requiring interaction with said subsystem or object must them obtain it by queueing requests to the dedicated thread (and possibly waiting on a "return queue" for results, if results are required as a consequence of some request). This is also a very sound Python architecture for general-purpose threading (and I expound on it at length in "Python in a Nutshell", but that's another subject;-).

这篇关于创建第二个 Toplevel 小部件时,线程 Tkinter 脚本崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆