Building a DirectGUI File Dialogue

Hi all - I’m a first time caller - discovered Panda a week ago - like it a lot :astonished:)

I want to build a File Open Dialogue in my P3D app.
Can’t find such a thing explicitly in the samples or manuals.

I am guessing that the most likely way to build a scrollable click/selectable list
will be with a DirectScrolledList, but so far what I’ve managed is somewhat clunky…

Would appreciate it if anyone has done or seen such a thing before, and is willing to share :slight_smile:

cheers
nb

With something as big and OS-specific as a file dialog, you’re probably better off using a third-party windowing system like tk or wxPython to present it, rather than trying to construct it in the 3-D window using DirectGui.

Both tk and wxPython have decent Python interfaces. There are examples of using the tkFileDialog in Panda; for instance, look at direct/src/tkpanels/ParticlePanel.py.

David

Thanks, I’ll have a dig thru that…
(unfortunately the particles test app fails to run - reference to a module named LinearVectorForce, which I can’t find anywhere in the Panda installation :frowning:

Have you got the latest Panda3D version 1.2.1? This version, at least, does correctly define LinearVectorForce (this is a C++ module which gets imported via pandac.PandaModules).

David

That all works very well now - thanks for the tip…

One minor puzzle - the File Menu has a built-in Quit action, but it only exits the ‘front’ screen, there is a small TK screen that stays, and even a ‘sys.exit’ doesn’t close that one?

The code below just displays enough to select a file, then simply prints the filename. It demonstrates the Quit action that doesn’t.

#---------------------------------------------
# --- Simple File Dialogue : Load/Save skeleton ---
import direct.directbase.DirectStart        #Initialize Panda
import sys, os

from direct.tkwidgets.AppShell import *
#----------------------
class UserIF(AppShell):
#----------------------
    # Override class variables
    appname = 'User Interface'
    frameWidth  = 200
    frameHeight = 50
    
    def __init__(self):
        # Initialize application specific info
        AppShell.__init__(self)

    # override class method 
    def createInterface(self):

        # --- FILE MENU ---
        # Get a handle on the file menu so commands can be inserted before Quit item
        fileMenu = self.menuBar.component('File-menu')
        fileMenu.insert_command( fileMenu.index('Quit'), label = 'Load', command = self.getLoadFilename)
        fileMenu.insert_command( fileMenu.index('Quit'), label = 'Save', command = self.getSaveFilename)

    # override class method 
    def quit(self):
        print "Quit"
        #sys.exit()
        AppShell.quit(self)

    def getLoadFilename(self):
        path = '.'   # can put logic here to load say the last used path...
        if not os.path.isdir(path):
            print 'Warning: Invalid default directory!'
            print 'Using current directory'
            path = '.'

        Filename = askopenfilename(
            defaultextension = '.egg',
            filetypes = (('Model Files', '*.egg;*.bam'), ('All files', '*')),
            initialdir = path,
                title = 'Load ',
                parent = self.parent)

        if Filename:
          print Filename
        else:
          print "No filename"
        return Filename  # returns full path
           
    def getSaveFilename(self):
        path = '.'   # can put logic here to load say the last used path...
        if not os.path.isdir(path):
            print 'Warning: Invalid default directory!'
            print 'Using current directory'
            path = '.'

        Filename = asksaveasfilename(
            defaultextension = '.egg',
            filetypes = (('Model Files', '*.egg;*.bam'), ('All files', '*')),
            initialdir = path,
                title = 'Load ',
                parent = self.parent)

        if Filename:
          print Filename
        else:
          print "No filename"
        return Filename  # returns full path
    
#--------------------------------------------

ui = UserIF()
run()

That’s the default Tk window, it sure is annoying, isn’t it? No one requested that one to open, Tk just insists on opening a default window all by itself. (It expects you to do something with it, but none of the Direct tools do–the modular Python interface doesn’t lend itself to using the one, global, default window.)

I’m surprised it doesn’t go away when you exit the Python process, though. It certainly does for me.

David

It does go away if I take focus back to the Panda window, and close from that.
But there is a Quit option in the TK menu, and if I put a sys.exit in the Quit handler, that does not close all the windows.