multithreading - "RuntimeError: Calling Tcl from different appartment"tkinter 和线程

标签 multithreading python-3.x tkinter tcl

我想使用线程和 tkinter ( python 3.6 ) 实现 GUI。
当我运行 GUIExecution.py 时,出现以下错误。
" RuntimeError: Calling Tcl from different appartment "on self.root.mainloop() in base_gui_class.py
我是在一个类的基础上实现的,三个代码文件如下。
可执行文件是 GUIExecution.py。
我花了很多时间试图修复错误,但我还没有能够修复它。
请多多指教。
此外,如果我在 python2 环境中运行以下代码,它可以正常工作而不会出错。

GUI执行.py

from base_gui_class import *

from base_class import *

speed = 1000
height = 500
width = 700

base_model = base_class()
gui = base_gui_class(base_model, speed, height, width)
base_model.visualize()

基类.py
class base_class():
    genes = []
    dicLocations = {}
    gui = ''
    best = ''
    time = 0

    def __init__(self):
        pass

    def visualize(self):
        if self.gui != '':
            self.gui.start()

    def registerGUI(self, gui):
        self.gui = gui

base_gui_class.py
import threading
import tkinter as tk
import math
import threading
import time
class base_gui_class(threading.Thread):
    root = ''
    canvas = ''
    speed = 0
    base_model = ''
def __init__(self, base_model, speed, h, w):
    threading.Thread.__init__(self)
    self.base_model = base_model
    base_model.registerGUI(self)

    self.root = tk.Tk()

    self.canvas = tk.Canvas(self.root, height=h, width=w)
    self.canvas.pack()

    self.root.title("Test")
    self.speed = 1 / speed
def run(self):
    self.root.mainloop()
def update(self):
    time.sleep(self.speed)
    width = int(self.canvas.cget("width"))
    height = int(self.canvas.cget("height"))
    self.canvas.create_rectangle(0, 0, width, height, fill='white')
def stop(self):
    self.root.quit()

最佳答案

对于一个非常好的第一和第二近似值,Tk 的核心是单线程的。它可以从多个线程中使用,但只能在每个线程中单独初始化它。在内部,它广泛使用特定于线程的变量来避免对主要锁定的需要(也就是说,它没有像大的全局解释器锁那样),但这意味着你不能作弊。无论哪个线程初始化 Tk 上下文,都必须是唯一与该 Tk 上下文交互的线程。 这包括加载 Tkinter 模块 所以你实际上只能从你的主线程中使用 Tkinter;解决这个问题是严肃的专家专用的东西。

我建议您通过使用队列向其发布事件来使您的工作线程更改您的 GUI(或者以其他方式与关键部分和条件变量互锁,尽管我发现队列在实践中更容易)。

关于multithreading - "RuntimeError: Calling Tcl from different appartment"tkinter 和线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45799121/

相关文章:

java - 两个线程共享静态 boolean 字段,但第一个线程仍然不退出

python-3.x - 为什么先导入 * 然后 ttk?

multithreading - Postgresql事务 "COMMIT"线程安全吗?

python - 我可以暂停和恢复的线程?

python-3.x - 类型 'ObjectID'的对象不可JSON序列化

python - 避免使用 global 不会让 Python 编程新手感到困惑?

python - 即使用户关闭了 Web 浏览器/选项卡,如何运行 Python 3 函数?

python-3.x - (Python) 使用滚动条将框架插入 Canvas

python - 如何在 mac 上自定义 tkinter 菜单栏?

c# - 并行编程 TPL