i am developing a algorithmic model the interface of which is developed in Tkinter (python 3.6.6).
at some point the interface needs to visualize the 3d-model of a vehicle therefore it opens a panda3d application.
everything is fine until the moment that one needs to click on something on the Tkinter interface. i get:
Fatal Python error: PyEval_RestoreThread: NULL tstate Current thread 0x000048cc (most recent call first): File "W:\Geeglee\ives\venv\lib\site-packages\direct\showbase\ShowBase.py", line 2002 in __igLoop File "W:\Geeglee\ives\venv\lib\site-packages\direct\task\Task.py", line 485 in step File "W:\Geeglee\ives\venv\lib\site-packages\direct\showbase\ShowBase.py", line 3065 in __tkTimerCallback File "p:\python\Lib\tkinter\__init__.py", line 749 in callit File "W:\Geeglee\ives\venv\lib\site-packages\Pmw\Pmw_2_0_1\lib\PmwBase.py", line 1776 in __call__ File "p:\python\Lib\tkinter\__init__.py", line 1283 in mainloop File "W:\Geeglee\ives\venv\lib\site-packages\direct\showbase\ShowBase.py", line 3079 in tkRun File "W:/Geeglee/ives/main_gui.py", line 138 in ives3d File "W:/Geeglee/ives/main_gui.py", line 47 in __init__ File "W:/Geeglee/ives/main_gui.py", line 507 in <module>
this happens only of both panda3d and Tkinter are open. if one closes the panda3d window everything works fine.
Now, i believe that i need to split Tkinter app and Panda3d app in two different threads. In my mind it is the cleaner way to built this kind of integration but i was not succesfull in doing so.
Right now what i am doing is to add the panda3d app as part of the Tkinter mainloop. I am not sure it is this the cause of my problem or it is related to the general structure of my program. here it is:
from tkinter import * from tkinter import ttk, Checkbutton, Canvas from panda3d.core import * from direct.showbase.ShowBase import ShowBase class TkinterGuiClass(ttk.Frame): def __init__(self, parent, args_): ttk.Frame.__init__(self, parent) self.app = parent self.app3d = None # create frame self.ives = ttk.Frame(parent) # add a frame to the canvas self.ives.grid(column=0, row=0, sticky=(N, W, E, S)) self.launch_panda3d_app() # launch panda3d app def launch_panda3d_app(self): # this is in case someone tries to launch a second panda3d app try: base.destroy() except NameError: pass self.app3d = Panda3dClass(self.ives) try: self.app3d.run() except SystemExit: base.destroy() # so if i close the panda3d window it will not shut down tkinter as well class Panda3dClass(ShowBase): def __init__(self, ives_data): self.ives_data = ives_data try: ShowBase.__init__(self, windowType='none') except Exception as e: # this is an error when it tries to start a new instance of ShowBase if str(e) == 'Attempt to spawn multiple ShowBase instances!': return else: raise Exception # so far it has created a ShowBase with no window, now create a ShowBase instance with a window base.destroy() ShowBase.__init__(self, windowType='onscreen') base.startTk() # start Tk integration base.spawnTkLoop() # make panda3d part of the Tk mainloop # main jobs of the 3d-viewer follow here if __name__ == '__main__': args = () app = Tk() TkinterGuiClass(app, args) app.mainloop()
My software is in quite an advanced state everything else works like a charm and this problem renders my software useless. I appreciate any help!