Native FileChooser Dialogs

This tutorial is based on the Windows native filechooser and the PyGTK FileChooserDialog. To use this tutorial on Windows the pywin32 package will need to be installed. Pywin32 can be downloaded at its web site http://sourceforge.net/projects/pywin32/.

It is just a basic class wrapped around both. If you are using Windows, a Windows filechooser will be displayed. Otherwise a PyGTK FileChooserDialog will be displayed. The purpose of this is to make sure when people are opening files on Windows that they do not have problems because the file chooser is different from every other program that they use.

First things first, if you want to use the Windows filechooser you will need to import:

import win32gui, win32con

Now we start the class. It will be called NativeFileChooser. When we initialize the class we will set the filters. For Windows this will be a string:

self.file_filter="""Text files\0*.txt\0All Files\0*.*\0"""

For the PyGTK FileChooserDialog the filter will be initialized like this:

self.file_filter=gtk.FileFilter()
self.file_filter.set_name("Text files")
self.file_filter.add_mime_type("text/*")
self.file_filter_all=gtk.FileFilter()
self.file_filter_all.set_name("All files")
self.file_filter_all.add_pattern("*")

Both filters above will display a drop down box that has "Text files" and "All Files". When text files is selected only text files will be displayed. When all files are selected all files will be displayed in the filechooser.

So now when the class NativeFileChoosers is initialized the file filter types will be set. The actual dialogs will be shown with a show method.

Now with the filters set we can display the filechooser dialogs. On Windows this is done using the win32gui.GetOpenFileNameW function. The important thing to note here is fname. fname is the name of the file chosen and the path.

Another thing important aspect to using GetOpenFileNameW is that if Cancel is pressed instead of Open, it will cause a win32gui.error that must be caught. So make sure when you use GetOpenFileNameW it is used with Exception handling.

        #exception handling to catch if user presses Cancel
        try:
            fname, customfilter, flags=win32gui.GetOpenFileNameW(
                InitialDir=os.path.join(os.environ['USERPROFILE'],"My Documents"),
                Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER,
                File='', DefExt='txt',
                Title='Select a File',
                Filter=self.file_filter,
                FilterIndex=0)
        except win32gui.error:
            print "Cancel clicked"
            return None
        
        self.fname=fname
        print 'open file names:', repr(fname)
    

The PyGTK FileChooserDialog is rather simple to use. You call FileChooserDialog with some options, add the filters that were created when the NativeFileChooser class was initialized, run the dialog and call destroy().

        dialog=gtk.FileChooserDialog(title="Select a File", action=gtk.FILE_CHOOSER_ACTION_OPEN,
            buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.add_filter(self.file_filter)

        dialog.add_filter(self.file_filter_all)

        response = dialog.run()
        if response == gtk.RESPONSE_OK:
            self.fname = dialog.get_filename()
        elif response == gtk.RESPONSE_CANCEL:
            print 'Cancel Clicked'
        dialog.destroy()
    

All that is needed now is a button to call the filechooser. button = gtk.Button(label="Display a Native File Chooser Dialog") file_chooser = NativeFileChooser() button.connect("clicked", file_chooser.show)

The finished code below is more or less the same as has been shown in the first two pages. It has an added function get_filename added to the NativeFileChooser class that returns the name of the selected file.

It also has code to setup a window and add a button in the section __name__ == "__main__". This code should be familiar and easy to follow.

native-filechooser.py

        import pygtk
        pygtk.require('2.0')
        import gtk
        import sys
        import os

        if sys.platform=="win32":
            import win32gui, win32con
            
        class NativeFileChooser:
            def __init__(self):
                self.fname=None
                if sys.platform=="win32":
                    self.file_filter="""Text files\0*.txt\0All Files\0*.*\0"""
                else:
                    self.file_filter=gtk.FileFilter()
                    self.file_filter.set_name("Text files")
                    self.file_filter.add_mime_type("text/*")
                    self.file_filter_all=gtk.FileFilter()
                    self.file_filter_all.set_name("All files")
                    self.file_filter_all.add_pattern("*")


            def show(self, widget):
                if sys.platform=="win32":
                    try:
                        fname, customfilter, flags=win32gui.GetOpenFileNameW(
                            InitialDir=os.path.join(os.environ['USERPROFILE'],"My Documents"),
                            Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER,
                            File='', DefExt='txt',
                            Title='Select a File',
                            Filter=self.file_filter,
                            FilterIndex=0)
                    except win32gui.error:
                        print "Cancel clicked"
                        return None
                    
                    self.fname=fname
                    print 'open file names:', repr(fname)

                else:
                    dialog=gtk.FileChooserDialog(title="Select a File", action=gtk.FILE_CHOOSER_ACTION_OPEN,
                        buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
                    dialog.add_filter(self.file_filter)

                    dialog.add_filter(self.file_filter_all)

                    response = dialog.run()
                    if response == gtk.RESPONSE_OK:
                        self.fname = dialog.get_filename()
                    elif response == gtk.RESPONSE_CANCEL:
                        print 'Cancel Clicked'
                    dialog.destroy()
            
            def get_filename(self):
                return self.fname
                
        if __name__ == "__main__":
            window = gtk.Window(gtk.WINDOW_TOPLEVEL)
            window.set_title("Native Filechooser")

            # It's a good idea to do this for all windows.
            window.connect("destroy", lambda wid: gtk.main_quit())
            window.connect("delete_event", lambda a1,a2:gtk.main_quit())

            # Setup button
            image = gtk.Image()
            image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
            button = gtk.Button(label="Display a Native File Chooser Dialog")
            button.set_image(image)
            
            # Setup NativeFileChooser
            file_chooser = NativeFileChooser()
            #Connect the "clicked" signal of the button to our callback
            button.connect("clicked", file_chooser.show)
            button.show()

            window.add(button)
            window.show()
            gtk.main()
                

Leave a Comment:


2 + 2 =