Hi,
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!