“RuntimeError: Calling Tcl from different appartment” tkinter and threading

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I want to implement GUI using threading and tkinter (python 3.6).
When I run GUIExecution.py, the following error occurs.
"RuntimeError: Calling Tcl from different appartment" on self.root.mainloop() in base_gui_class.py
I am implementing it on a class basis, and the three code files are as follows.
The executable file is GUIExecution.py. I spent a lot of time trying to fix the error, but I have not been able to fix it yet.
Please give a lot of advice.
Additionally, if I run the following code in a python2 environment, it works fine without error.

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

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

回答1:

To a very good first and second approximation, the core of Tk is single threaded. It can be used from multiple threads, but only by initialising it separately in each of those threads. Internally, it uses thread-specific variables extensively to avoid the need for major locking (that is, it has nothing like a big Global Interpreter Lock) but that means you must not cheat. Whatever thread initialises a Tk context must be the only thread that interacts with that Tk context. This includes loading the Tkinter module so you are effectively restricted to using Tkinter from your main thread only; working around this is serious expert's-only stuff.

I recommend that you make your worker threads make changes to your GUI by posting events to it using a queue (or otherwise interlock with critical sections and condition variables, though I find queues easier in practice).



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!