Updated 2016-01-30 01:24:19 by pooryorick

tk_getOpenFile, a Tk command, presents a dialog to the user in order to open or save files.

Synopsis  edit

tk_getOpenFile ?option value ...?

Options  edit

-defaultextension extension
select what type of file to pick by default
-filetypes patternList
set up the type selector
-initialdir directory
where to start looking
-initialfile filename
what file to have initially (otherwise none)
-message string
extra info for the user about the selection
-multiple boolean
whether the user can pick several files from the same directory
-parent window
what window is the owner of the dialog (otherwise .)
-title string
title string for the dialog
-typevariable varName
variable to capture what file type was selected (not always obvious from extension name)

Description  edit

tk_getOpenFile is usually associated with Open in the File menu. Its purpose is for the user to select an existing file. If the user enters an non-existent file, the dialog box gives the user an error prompt and requires the user to give an alternative selection. If an application allows the user to create new files, it should do so by providing a separate New menu command.

On Windows, a native file selector is used. You can get the Tcl-coded "original" as used on Unix/Linux by explicitly calling:
set filename [::tk::dialog::file:: open arg arg..]

Note that the command name is the empty string in its namespace. Any other value than open for the first argument calls the equivalent of tk_getSaveFile. (RS)

Some folks on Windows use a script version of tk_getOpenFile/tk_getSaveFile because there is an odd Windows bug that can cause your application to misbehave. If you double-click to select a file name, the dialog consumes only 1.5 clicks (<down><up><down>), then the dialog closes, and the remaining 0.5 click (<up> event) gets delivered to whatever widget was underneath. This can cause buttons to activate or focus to change. You might want to Drain The Event Queue. Note that this is bug 611615, fixed in Tk 8.4.8.

Discussion  edit

tkfbox is a nifty little portable bundle for extending get{Open,Save}File capabilities.

This grabbed my attention because of my recent TIP regarding sub-classing the file dialogs on UNIX (well, non-Windows platforms). But there isn't enough documentation to tell what the benefits of this file are. -- CLN 2001-10-19

tkfbox was originally from sun, but partially reworked by me (Mick O'Donnell). I was recently asked why I used it rather than the now standard tk_getOpenFile/tk_getSaveFile. Well, I have so far found 4 advantages of pure the tcl/tk code versions:

  • Can set background colors to the window: the built-in versions are limited to a gray background. the tkfbox version uses the default background color.
  • Doesn't fall prey to the bug in the built in version which means that double clicks on a file name are not totally consumed, and can cause a click event on a widget below the open file dialog. This can be patched, but it is a problem. -- MG recalls reading somewhere that this is now fixed, but can't remember where...
  • When you call the tkfbox tk_getSaveFile with multiple filetypes specified, and change the filetype using the filetype listitem, then the displayed filename will change its extension. E.g., changing from jpg to gif will also change the filename's extension. This doesnt happen with the built in tk_getSaveFile.
  • The real advantage is that since the tkfbox version is tcl/tk code, I can adapt it at will. If there is some feature I don't like in the built-in version, I can change/add/delete the feature.
  • SEH Allows selection of files and directories in virtual filesystems.

Mick mailto:[email protected]

DKF: As the maintainer of (the script versions of) the standard dialogs, I'd love to have suggestions of how to improve them, so long as these improvements are things that are not too hostile to operating in a cross-platform manner (note that the official script-level API is pretty-much fixed; the Windows native dialogs are not very capable!)

MGS: With tk_getSaveFile and tk_chooseDirectory, you should be able to create directories.

DLR: Suggestions for improvement: Change the default icons for folders and files, they look rather ugly. I use the ones that come with BWidgets. Ability to select multiple files.

JBR 2003-09-08: I have extended the tkfbox code to include some new options. You can find it here: [1]

-blueplate separates the dirs into one IconList and the files into another.

-colormap allows the file dialog to use the colormap of a parent window.

-dirslist take a list of "standard" directories and puts them at the top of the dir popup.

-filetype enables a secret global parameter controlled by an additional file type popup menu.

-infoproc an experimental feature to allow a proc to be called when the button one is pressed and help over an item.

I have just recently merged these extensions with the 8.4 tkfbox that allows multiple files to be selected. We use all these extended options in the ds9 image display program. The idea with the info proc feature is to allow the user to get some more info about the file before commiting to opening it. In the case of our image files a single image may contain many images of various types, the info proc can display additional data about where and when the images in the file were obtained and popup a menu allowing the user to select and image within the file.

2005-04-27 - I would like to use something like a 'tooltip' to display the modification date when the cursor is placed over file names in the tk_getOpenFile dialog box. Any suggestions on how to approach this would be appreciated.

MG 2005-04-28: See the page balloon help for some basic code for doing them. To explain it basically, though, you just need to bind to the label widgets (or whatever's used) listing the file names, for <Enter> and <Leave>. On the <Enter> binding, you create a toplevel widget with the decorations off (using wm overrideredirect), and pack a label widget inside the toplevel with the info you want (which can be obtained with clock format [file mtime $file]). Then bind to the <Leave> event, and have that binding destroy your new toplevel widget. If you need any more help with it, post back, and I'll take a look at the code for it and throw an example together.

Might this be something worth adding as standard? On Windows XP, for instance, moving over a file (in tk_getOpenFile or Explorer, etc) shows a tooltip with "Type" (probably not much use on other platforms?), the Modified date, and the file size. (Oh, for shortcuts, it just shows the directory of the file linked to, either relatively if it's below the directory the shortcut itself is in, or absolutely, otherwise.)

MG adds, a couple of hours later: I played around with this a little, and added tooltips to it. They look pretty crude, but it's easy enough to edit. The code is probably quite crude too, though (I guessed largely at how some of the internals, particularly for option parsing, worked), but it does at least seem to work. It's a complete replacement for the tkfbox.tcl file included in $tclHome/lib/tk8.4/ (mine is from ActiveTcl 8.4.9) - if you just save it, and source it before using tk_getOpenFile, it'll have the changes. Some primitive docs are at the bottom of the page. (On Windows XP, where I tested it, it doesn't pick up shortcuts properly, because file type doesn't recognise them.) You can find the file on my website, here: [2] Oh, incidently, it should work as tk_getSaveFile, too, though I didn't test it as such.

I tried the code from MG's reference above - looks like the file was truncated, but after comparing it with the standard tkfbox.tcl (thanks for the reference!) and pasting in the remainder of the file, the example ran and I'm able to tweak the changes a bit for personal preferences. Thanks for the help!

MG: Woops :) It's no longer truncated. If you've made any changes to the tooltip that improve the appearance (I basically got it working and didn't go any further), feel free to add the changes here or email me them ([email protected]) and I'll add them into the code on my site, if you'd like to.

LES 2005-09-09: When I select files with tk_getOpenFile, I can select .DOC files in the drop-down box and have all and only *.DOC files visible, ready for selection.

Or I can select .RTF files in the drop-down box and have all and only *.RTF files visible, ready for selection.

Or I can select * files in the drop-down box and have ALL FILES WHATSOEVER visible, ready for selection.

How do I get both and only .DOC and .RTF files available for selection?

RS:
 tk_getOpenFile -filetypes {{Text {.doc .rtf}}}

[DRS] 2006-11-16: Is there a way to get the dialog to sort the filenames by date? I did find [3] tip #271 with an improved dialog but I need a cross-platform solution that doesn't require a custom version of tcl/tk.

TML 2008-07-07: I tried to access ::vfs::urltype mounted ftp files served by ::ftpd via tk_getOpenFile, which works fine on Linux, but fails on Windows. Am I right to suppose the native Windows getOpenFile dialog just doesn't go with VFS at all? As a workaround, I'm using the undocumented "::tk::dialog::file:: open ..." which creates the Unix tk_getOpenFile dialog on all platforms. (There's an intentional blank before the "open" - the proc name really is the empty string!)

MG: That's correct. On Windows (and MacOS, I think?) a native dialog is called by tk_getOpenFile, which can't see inside a VFS. The ::tk::dialog::file one which is used on Linux is pure-Tcl, so can see all the files Tcl can. If you need to access things in the VFS, either what you're doing now, or the File selection dialog for Tile are probably your best bet.

LV: recently on comp.lang.tcl someone asked a question about tk_getOpenFile that triggered a question in my mind.

What would be an example of the safe way to use the results of tk_getOpenFile -multiple 1 on Windows, knowing that in all likelihood the files will have spaces in them?
package require Tk

set types {
    {{Text Files}       {.txt}        }
    {{TCL Scripts}      {.tcl}        }
    {{C Source Files}   {.c}      TEXT}
    {{GIF Files}        {.gif}        }
    {{Text Files}       {}        TEXT}
    {{All Files}        *             }
}
set filenameList [tk_getOpenFile -filetypes $types -multiple true ]

foreach filename $filenameList {
     if { [file readable $filename] } {
        puts "I found $filename"
     }
}

I thought the above code should work. However, I am missing something, because when I select 2 files, I get an error saying that the file (followed by the 2 file names) does not exist.

LV 2009-05-07:

For someone using tk_getOpenFile with the -multiple true option, here's a note about the actual keyboard behavior of the dialog, at least in Tk 8.5.4.

  1. To select multiple files that are in a row, you can either select the first file, then holding down the shift key, drag the mouse to the last file name, or you can select the first file, then holding down the shift key, select the last file of the set you wish.
  2. To select multiple files that are not beside one another, things are tricky. You need to first hold down the control key, then select the file names you wish. You may not let go of the control key until you have all the files selected or the previously selected files are unselected.

witek 2011-06-12

Is there a way to disable displaying of hidden directories in Linux (starting with a dot ".") when file sector dialog opens?

idg 2011-06-12:

Not conveniently, but the necessary hooks are already in place in the file tkfbox.tcl. This file lives in your tcl installation which, depending on the distribution, is:
    Ubuntu: /usr/share/tcltk/tk8.5/
    Fedora: /usr/share/tk8.5/
    Slackware: /usr/lib/tk8.5/

Find the line
namespace eval ::tk::dialog::file {

about 1/3 of the way through this file. Then, a couple of lines down,
set ::tk::dialog::file::showHiddenVar 0

will turn off the hidden file display. If you want to make this user-selectable at run time,
set ::tk::dialog::file::showHiddenBtn 1

in the same area. This is easy on your own system, a headache if you want to distribute code to others. I wish this would be made an official part of Tk...

witek 2011-06-12:

Great! It works. It should be set like this for Linux/Unix by default. It would give much better experience to the user.

Googie 2011-June-13:

It's enough to just set those variables manually after loading Tk package. You don't need to edit tkfbox.tcl (which is usually read-only to Unix users).

Just use lines:
set ::tk::dialog::file::showHiddenVar 0
set ::tk::dialog::file::showHiddenBtn 1

after
package require Tk

or just at the very begining of your script if you're running script with wish (or wish-like) interpreter. Important is that Tk is loaded before you change these variables.

KD 2011/06/13: That won't work, you first have to force the auto-loader to load tk_getOpenFile, for example with a dummy call:
catch {tk_getOpenFile foo bar}

witek 2011-06-13:

Thanks Googie. Why didn't I think about it myself?! Anyway, it's a bit ugly; having an option like "-disable_hidden" for tk_getOpenFile would be more cleaner way to do it.

RJM 2012-09-04: About encoding of returned filenames: Here some ambiguities were apparent. This was revealed after trying to establish a full utf-8 command line argument for the exec command (which will be discussed on a separate page - Tcl fails here). I experimented with the return value of tk_getOpenFile and wrote it under different conditions in a file, to allow exact examination of the encoding result. Here is a table:
encoding system ... utf-8 utf-8 cp1252 cp1252
file attr. w wb w wb field comment
w/o conversion OK less ?less less ? means: true '?'-substitution
convertto utf-8 more OKfalse OK false: same length, but

(less = less characters than utf-string; more = more...)

The code framework:
encoding system [utf-8|cp1252]
set filename [tk_getopenFIle]
set fid [open fn.txt w]
puts -nonewline $filename
close $fid

Comment: The test path from tk_getopenFile contained several international characters. The variable filename outputs to file as correct utf-8 while using non-binary file I/O only when encoding system is utf-8. When the system encoding is not utf-8, multibyte characters are represented as plain '?'-characters. Hence in a non-utf-8 system, a encoding convertto utf-8 makes sense. Here, a binary file I/O always ensures a correct result. Non-binary file-I/O fails in this case! I'm tempted to treat it as a bug. It is this latter result that also applies, when an utf-8 string is used as argument in exec <program> (even when system encoding is set to utf-8).

See Also  edit

select
An abstraction over tk_getOpenFile and tk_chooseDirectory
tk_getSaveFile
Tkgetfile - An enhanced FileOpen browser replacement for tk_getOpenFile
File selection dialog for Tile