How to run open folder in tkinter under panda3d?

I’m trying to read the file path from tkinter in the panda3d window. But it doesn’t work, is it possible to open tkinter window in panda3d?

The code:

import os

from direct.gui.DirectGui import *
from direct.showbase.ShowBase import ShowBase
from panda3d.core import *

from tkinter import *
from tkinter import filedialog



class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        self.cam.setPos(0, -20, 0)

        self.jack = self.loader.loadModel("models/jack")
        self.jack.setHpr(0, 180, 180)
        self.jack.reparentTo(self.render)

        bk_text = "This is my Demo"
        textObject = OnscreenText(text=bk_text, pos=(0.95, -0.95), scale=0.07,
                                  fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter,
                                  mayChange=1)

        def setText():
            bk_text = "Button Clicked"
            textObject.setText(bk_text)

        def btn():
            path = os.getcwd()
            folder_selected = filedialog.askdirectory()
            print(folder_selected)

        b = DirectButton(text=("OK", "click!", "rolling over", "disabled"),
                         scale=.05, command=tkinter)


def tkinter():
    window = Tk()
    window.title('P3DFormatConversion')
    window.geometry('500x300')
    folder_selected = filedialog.askdirectory()
    print(folder_selected)
    window.mainloop()


app = MyApp()
app.run()

Thank you for your reading.

Your code works fine for me; clicking the DirectButton makes the directory selector pop up, and choosing a directory makes it printed to the console.

What exactly do you mean by “doesn’t work”? Also, on which OS are you?

I’m using macOS Monterey 12.1, python 3.8, and Panda 1.10.9.
Are you using window10?

The error:

Known pipe types:
  CocoaGraphicsPipe
(all display modules loaded.)
2022-01-22 18:32:31.948 python3.8[4709:133319] -[CocoaPandaApp macMinorVersion]: unrecognized selector sent to instance 0x7fb33c306830
2022-01-22 18:32:31.953 python3.8[4709:133319] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CocoaPandaApp macMinorVersion]: unrecognized selector sent to instance 0x7fb33c306830'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007ff8123f3f0b __exceptionPreprocess + 242
	1   libobjc.A.dylib                     0x00007ff812154b9d objc_exception_throw + 48
	2   CoreFoundation                      0x00007ff812478adb -[NSObject(NSObject) __retain_OA] + 0
	3   CoreFoundation                      0x00007ff81235adb9 ___forwarding___ + 1406
	4   CoreFoundation                      0x00007ff81235a7a8 _CF_forwarding_prep_0 + 120
	5   libtk8.6.dylib                      0x000000010c756db9 SetCGColorComponents + 265
	6   libtk8.6.dylib                      0x000000010c75767a TkpGetColor + 250
	7   libtk8.6.dylib                      0x000000010c691aa9 Tk_GetColor + 153
	8   libtk8.6.dylib                      0x000000010c6818e6 Tk_Get3DBorder + 134
	9   libtk8.6.dylib                      0x000000010c68174f Tk_Alloc3DBorderFromObj + 127
	10  libtk8.6.dylib                      0x000000010c692fad DoObjConfig + 941
	11  libtk8.6.dylib                      0x000000010c692ae5 Tk_InitOptions + 357
	12  libtk8.6.dylib                      0x000000010c6929c5 Tk_InitOptions + 69
	13  libtk8.6.dylib                      0x000000010c6c3b5c CreateFrame + 1548
	14  libtk8.6.dylib                      0x000000010c6c3e37 TkListCreateFrame + 151
	15  libtk8.6.dylib                      0x000000010c6bb7f8 Initialize + 2168
	16  _tkinter.cpython-38-darwin.so       0x000000010c369399 Tkapp_New + 921
	17  _tkinter.cpython-38-darwin.so       0x000000010c368cc9 _tkinter_create + 649
	18  python3.8                           0x000000010be3ef44 cfunction_vectorcall_FASTCALL + 84
	19  python3.8                           0x000000010bf2bdf2 call_function + 162
	20  python3.8                           0x000000010bf2839f _PyEval_EvalFrameDefault + 43519
	21  python3.8                           0x000000010bf1bd84 _PyEval_EvalCodeWithName + 564
	22  python3.8                           0x000000010bde16da _PyFunction_Vectorcall + 426
	23  python3.8                           0x000000010bddfd6d _PyObject_FastCallDict + 93
	24  python3.8                           0x000000010be67dc2 slot_tp_init + 178
	25  python3.8                           0x000000010be76e4b type_call + 235
	26  python3.8                           0x000000010bde002d _PyObject_MakeTpCall + 173
	27  python3.8                           0x000000010bf2be8b call_function + 315
	28  python3.8                           0x000000010bf297a4 _PyEval_EvalFrameDefault + 48644
	29  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	30  python3.8                           0x000000010bde0879 PyVectorcall_Call + 121
	31  python3.8                           0x000000010bf29951 _PyEval_EvalFrameDefault + 49073
	32  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	33  python3.8                           0x000000010bde521d method_vectorcall + 349
	34  python3.8                           0x000000010bde0879 PyVectorcall_Call + 121
	35  python3.8                           0x000000010bf29951 _PyEval_EvalFrameDefault + 49073
	36  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	37  python3.8                           0x000000010bf2bdf2 call_function + 162
	38  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	39  python3.8                           0x000000010bf1bd84 _PyEval_EvalCodeWithName + 564
	40  python3.8                           0x000000010bde16da _PyFunction_Vectorcall + 426
	41  python3.8                           0x000000010bf2bdf2 call_function + 162
	42  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	43  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	44  python3.8                           0x000000010bde514d method_vectorcall + 141
	45  python3.8                           0x000000010bf2bdf2 call_function + 162
	46  python3.8                           0x000000010bf297a4 _PyEval_EvalFrameDefault + 48644
	47  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	48  python3.8                           0x000000010bf2bdf2 call_function + 162
	49  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	50  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	51  python3.8                           0x000000010bde521d method_vectorcall + 349
	52  python3.8                           0x000000010bde0879 PyVectorcall_Call + 121
	53  core.cpython-38-darwin.so           0x000000010db6e230 _ZN12PythonThread16call_python_funcEP7_objectS1_ + 192
	54  core.cpython-38-darwin.so           0x000000010db73303 _ZN10PythonTask14do_python_taskEv + 467
	55  core.cpython-38-darwin.so           0x000000010db7311a _ZN10PythonTask7do_taskEv + 26
	56  libpanda.1.10.dylib                 0x000000010f47246d _ZN9AsyncTask18unlock_and_do_taskEv + 333
	57  libpanda.1.10.dylib                 0x000000010f476ef7 _ZN14AsyncTaskChain16service_one_taskEPNS_20AsyncTaskChainThreadE + 519
	58  libpanda.1.10.dylib                 0x000000010f475dde _ZN14AsyncTaskChain7do_pollEv + 430
	59  libpanda.1.10.dylib                 0x000000010f47e09c _ZN16AsyncTaskManager4pollEv + 76
	60  core.cpython-38-darwin.so           0x000000010d8042e2 _ZL31Dtool_AsyncTaskManager_poll_138P7_objectS0_ + 66
	61  python3.8                           0x000000010bdefa48 method_vectorcall_NOARGS + 136
	62  python3.8                           0x000000010bf2bdf2 call_function + 162
	63  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	64  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	65  python3.8                           0x000000010bf2bdf2 call_function + 162
	66  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	67  python3.8                           0x000000010bf1bd84 _PyEval_EvalCodeWithName + 564
	68  python3.8                           0x000000010bde16da _PyFunction_Vectorcall + 426
	69  python3.8                           0x000000010bf2bdf2 call_function + 162
	70  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	71  python3.8                           0x000000010bde1628 _PyFunction_Vectorcall + 248
	72  python3.8                           0x000000010bf2bdf2 call_function + 162
	73  python3.8                           0x000000010bf28310 _PyEval_EvalFrameDefault + 43376
	74  python3.8                           0x000000010bf1bd84 _PyEval_EvalCodeWithName + 564
	75  python3.8                           0x000000010bfa328f pyrun_file + 271
	76  python3.8                           0x000000010bfa2a8f pyrun_simple_file + 463
	77  python3.8                           0x000000010bfa286e PyRun_SimpleFileExFlags + 110
	78  python3.8                           0x000000010bfcc33f pymain_run_file + 463
	79  python3.8                           0x000000010bfcb856 pymain_run_python + 534
	80  python3.8                           0x000000010bfcb5e5 Py_RunMain + 37
	81  python3.8                           0x000000010bfcce01 pymain_main + 49
	82  python3.8                           0x000000010bdb3418 main + 56
	83  dyld                                0x000000011bfed4fe start + 462
)
libc++abi: terminating with uncaught exception of type NSException

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

I use windows 10 and it works for me too.

1 Like

On macOS you need to put want-tk true in Config.prc to make Tkinter play nice with Panda3D, I believe.

1 Like

Thanks for your reply.

Is it something like this?
I add this code in to the program, still don’t work
loadPrcFile("/config/conf.prc")

Well… I use some other method to call out the tkinter window. However, it is not the perfect solution.

  1. Move the tkinter function into tkinter.py
  2. change the tkinter function contexts to this:
def tkinter():
     os.system("python3 tkinter.py")

loadPrcFileData("", "want-tk true") should also work, but it’s important to do it before ShowBase is initialized. You should probably also use base.tkRoot then rather than creating your own Tk root.

Of course, a subprocess works as well.

1 Like

Thanks for the reply.

I don’t understand how to use base.tkRoot.
Is something like this:

import os
from tkinter import *
from tkinter import filedialog

from direct.gui.DirectGui import *
from direct.showbase.ShowBase import ShowBase
from panda3d.core import *
from panda3d.core import PandaSystem

loadPrcFileData("", "want-tk true")

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        print("Panda version:", PandaSystem.getVersionString())

        self.cam.setPos(0, -20, 0)

        self.jack = self.loader.loadModel("models/jack")
        self.jack.setHpr(0, 180, 180)
        self.jack.reparentTo(self.render)

        bk_text = "This is my Demo"
        textObject = OnscreenText(text=bk_text, pos=(0.95, -0.95), scale=0.07,
                                  fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter,
                                  mayChange=1)

        def setText():
            bk_text = "Button Clicked"
            textObject.setText(bk_text)

        def btn():
            # exec(open("/Users/tangkamsan/gitdir/fyp/panda3d/other/FormatConversion.py").read())
            os.system("python3 /Users/tangkamsan/gitdir/fyp/panda3d/other/FormatConversion.py")

        b = DirectButton(text=("OK", "click!", "rolling over", "disabled"),
                         scale=.05, command=tkinter)


def tkinter():
    window = base.tkRoot.Tk()
    window.title('P3DFormatConversion')
    window.geometry('500x300')
    folder_selected = filedialog.askdirectory()
    print(folder_selected)
    window.mainloop()


app = MyApp()
app.run()

Here is the error:

Traceback (most recent call last):
  File "/Users//gitdir/fyp/panda3d/other/test_tkinter.py", line 51, in <module>
    app = MyApp()
  File "/Users//gitdir/fyp/panda3d/other/test_tkinter.py", line 15, in __init__
    ShowBase.__init__(self)
  File "/Users//opt/anaconda3/envs/py38/lib/python3.8/site-packages/direct/showbase/ShowBase.py", line 331, in __init__
    Pmw = importlib.import_module('Pmw')
  File "/Users//opt/anaconda3/envs/py38/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'Pmw'

Just this:

window = base.tkRoot

I also think you don’t need to call window.mainloop(), Panda will handle this.

As for the Pmw error, you need to install the Pmw package, you can do this by typing python3.8 -m pip install Pmw (or however you invoke your Python interpreter).

1 Like

Thanks for your reply rdb.

It seems to work. But there will pop up a tk window in the beginning. How to remove the left-up tk window?

I change my code:

def tkinter():
    window = base.tkRoot
    window.withdraw()
    folder_selected = filedialog.askopenfilename()
    print(folder_selected)

In fact, there is no need for a Panda window here, you need to create an application without a window and embed the panda context in Tk. There are many examples of this on the forum, use the search to find it.

1 Like

Thank you serega-kkz. I will try it.

I really don’t think that’s a good idea, I would advise against parenting the Panda window to the Tk window unless you actually need to do this.

I think calling withdraw() is the way to hide the root window. Is that not working for you?