The Toplevel widget methods are listed and explained in the following sections. It is important to note that all of these methods apply to a MainWindow as well; a MainWindow is just a specialized Toplevel widget. Also keep in mind that a lot of these methods were designed originally for use with a Unix windowing environment, and quite a few of them will state "No effect in Win32 system." Many of these functions serve no useful purpose to the typical ordinary Perl/Tk application, but we document them here for thoroughness.
Several of the methods here alter window manager properties, which often look like WM_PROPERTY_THING. These properties are also traditionally associated with the X Window system on Unix, but some still apply in Win32 systems. If a specific method doesn't say anything about which system it applies to, it will apply to both. If it applies only to one or the other (or only half-works in one system), this will be mentioned as well.
You can use the geometry method to define or retrieve a geometry string. A geometry string determines the size and placement of a window on the screen. The geometry string is a concept that originated on Unix systems and is a bit cryptic at first glance. Here is a regular expression that describes a complete geometry string:
^=?(\d+x\d+)?([+-]\d+[+-]\d+)?$
The equals sign can be omitted completely (and usually is). The first portion (\d+x\d+) is the width and height (in that order), separated by an x. Both width and height are specified in pixels by default and in grid units if the window is gridded with the grid method (described later). The last portion of the geometry string represents the x and y coordinates of the location in which the Toplevel should be placed on the screen. Both x and y are always in pixels. Here are a few examples of what some geometry strings look like:
300x300 # width and height both = 300 300x450 # width = 300, height = 450 300x450+0+0 # width = 300, height = 450 placed in upper left corner 300x450-0-0 # width = 300, height = 450 placed in lower right corner 300x450+10+10 # width = 300, height = 450 # placed 10 pixels out from upper left corner +0+0 # window is 'natural' size, placed in upper left corner
When geometry is called with no arguments, the current geometry string is returned. You can also specify a new geometry by using geometry with the new geometry string as the argument. To set the size and position of the window immediately, you would do this:
$mw = MainWindow->new( ); $mw->geometry("300x450+0+0");
If you specify only the width and height, the placement of the window is determined by the window manager. If you specify only the positioning, then the size of the window will be determined by the widgets placed within the Toplevel, but the window will be placed at those x and y coordinates.
You can force the window back to its natural size by calling geometry with an empty geometry string:
$toplevel->geometry("");
You can use maxsize to restrict the largest size of the window. It takes two integers as arguments, as follows:
$toplevel->maxsize(300,300);
If you call maxsize without any arguments, you get an empty string or a list with two items in it representing the current values. Calling maxsize with two empty strings cancels the limitation.
You can also restrict the smallest size of the window by using minsize. The window will always be at least the size specified:
$toplevel->minsize(100,100);
Calling minsize without arguments returns an empty string or a list containing the width and height, respectively. Calling minsize with two empty strings eliminates the minimum size restriction.
You can control whether a window can be resized in width and/or height by using resizable:
$toplevel->resizable(1, 0); ($canwidth, $canheight) = $toplevel->resizable( );
Specifying 1 means it is resizable, and 0 means it is nonresizable in the specified direction. If you don't specify any arguments, resizable returns a list with two items. The first item is a 1 or 0 and indicates whether the width is resizable. The second item is a 1 or 0 and indicates whether the height is resizable. By default, a window is resizable in both directions.
You can use the aspect method to force the window to stay a certain width and height:
$toplevel->aspect( [ minN, minD, maxN, maxD ]);
In this example, the N in minN and maxN stands for "numerator" and the D in minD and maxD stands for "denominator."
The aspect method does some very subtle things, and you'll probably never use it. If you do, play around with different values (starting with the example that follows) to get the effect you want.
When you use the aspect method with no arguments, it returns either an empty string (if there are no constraints to the aspect of the window) or an array containing four elements:
($minN, $minD, $maxN, $maxD) = $toplevel->aspect;
Using these values, you can see how aspect controls the window:
($minN/$minD) < width/height < ($maxN/$maxD)
You can also send four empty strings to unset the aspect restrictions on the window. Try using $toplevel->aspect(1,2,3,1); the effect is subtle.
To change the text across the top of the window, use the title method:
$toplevel->title("This will be the title");
Pass a string in with title and the new title will appear immediately in the window, assuming the window is currently visible. If you don't pass an argument with title, the current title string is returned. For the X Window System, the default title of a window is the name used to run the program, and the first character of the name is uppercase. For Microsoft Windows, the title always starts out as Toplevel.
The deiconify method causes the Toplevel to be displayed noniconified or deiconifies it immediately if the window has already been displayed once. If the window has been withdrawn, a $toplevel->raise( ) must also be done to display the window correctly.
If you call it with no arguments, the raise method brings the Toplevel to the front of all the other Toplevel windows in the application:
$toplevel->raise( );
You can also put the Toplevel in front of another Toplevel:
$toplevel->raise($other_toplevel);
It is sometimes necessary to use both deiconify and raise to get the window to show up on the screen.
When you create a window, it is a good idea to make it invisible while you fill it with widgets. You can do so by using the withdraw method:
$toplevel->withdraw( );
If the window is already visible, withdraw will make the window manager forget about the window until it has been deiconified.
The iconify method forces the Toplevel into iconified form:
$toplevel->iconify( );
Iconifying is not the same as withdrawing the window. Withdrawing the window will not show an icon on the desktop. Also, note that window managers are free to decide what to do in the iconified state. Some window managers (such as Microsoft Windows or KDE) don't show icons but just mark the windows in the task bar differently.
When you iconify your application under the X Window System, it is represented on the screen with a bitmap. You use the iconbitmap method to specify this bitmap:
$toplevel->iconbitmap( ); $toplevel->iconbitmap("bitmap");
It takes a bitmap in the same form as the -bitmap option supported by the Button widget (see Chapter 4, " Button, Checkbutton, and Radiobutton Widgets"). Calling iconbitmap with no arguments returns the current bitmap or an empty string. Calling iconbitmap with an empty string removes the current bitmap.
On Win32 systems, the application is kept in the Start taskbar with an unchangeable Tk icon and the name of the application. Using the iconbitmap method on a Win32 system does nothing.
In recent versions of Perl/Tk, the Icon method should be used instead. The Icon method works with both Unix and Win32 and allows you to specify an image instead of a bitmap, if you prefer.
A mask for the icon bitmap can be specified by using the iconmask method (remember, this will only work with X Window Systems). It also takes a bitmap specified from a file or a default bitmap name (see the -bitmap documentation in Figure 4-1). Where the bitmap mask has zeros, no part of the normal icon bitmap will be displayed. Where the mask has ones, normal icon bitmaps will be displayed.
Calling iconmask with no arguments returns the current bitmap mask or an empty string if no bitmap is being used. Calling iconmask with an empty string unsets the mask:
$currentmask = $toplevel->iconmask(); # get the mask $toplevel->iconmask("bitmapname"); # set the mask $toplevel->iconmask(""); # unset the mask
The iconname method sets or returns the current text associated with the icon that is displayed when the application is iconified. You can pass in a new string or an empty string:
$toplevel->iconname("newname"); $current_name = $toplevel->iconname();
If you don't specify an argument at all, iconname returns the current icon name or an empty string. You can query and set the icon name on a Win32 system, but it doesn't do anything. This method is used on the X Window System only.
The iconposition method suggests to the X Window System manager where the icon should be placed on the desktop when the application is iconified:
($x, $y) = $toplevel->iconposition(); $toplevel->iconposition($x, $y);
If x and y aren't specified, a list is returned containing only two items: the current x and y coordinates. If you call iconposition with two empty strings (one for each x and y), the suggestion to the window manager is canceled.
Some systems (not including Win32) support the idea of using a widget (or window) instead of a bitmap for an icon. Specify the widget by using the iconwindow method. To find out what the current widget is, call iconwindow with no arguments (an empty string is returned if there is no associated $widget). You can specify an empty string instead of $widget to cancel by using a widget for the icon:
$currentwindow = $toplevel->iconwindow(); # get $toplevel->iconwindow($window); # set $toplevel->iconwindow(""); # unset
The state method returns one of three strings: "normal", "iconic", or "withdrawn".
$state = $toplevel->state();
The string indicates the state of the window when state is called.
Every graphical program has a WM_CLIENT_MACHINE window property, which should be the hostname of the machine the program is executing on. This property can be changed using the client method, as follows:
$mw->client (new_client_name);
If new_client_name is omitted, the current name is returned. Passing undef to the client method resets the WM_CLIENT_MACHINE property to its original value.
The protocol method controls the following window properties: WM_DELETE_WINDOW, WM_SAVE_YOURSELF, and WM_TAKE_FOCUS. The callback (if any) associated with each property will be invoked when the window manager recognizes the event associated with the property:
$toplevel->protocol ( [ property_name] [, callback ] );
The WM_DELETE_WINDOW property callback is invoked when the window has been deleted by the window manager. By default, there is a callback assigned by Perl/Tk that destroys the window. If you assign a new callback, your callback will be invoked instead of the default callback. If you need to save data associated with that window, do so in the callback, then invoke $toplevel->destroy() to mimic the correct behavior afterward.
The other two properties, WM_SAVE_YOURSELF and WM_TAKE_FOCUS, are used much less commonly. For instance, WM_TAKE_FOCUS is used in Unix systems but not in Win32. The presence of these properties is dependent on the window system you are running. If your application will be running on multiple systems, don't expect these properties to always be available. To find out if they are available, assign each one a callback that does a print, then run the application to see if the print is ever invoked.
If you leave out the callback when you use protocol, the current callback assigned to that property will be returned (or an empty string, if there isn't a current callback assigned). You can remove the callback by sending an empty string instead of the callback. If neither argument is specified, the method returns a list of all properties that have callbacks assigned to them.
The colormapwindows method affects the WM_COLORMAP_WINDOWS property. This property is used to talk to the window manager about windows that have private colormaps. Using colormapwindows with no arguments returns a list of windows. The list contains windows (in order of priority) that have different colormaps than their parents:
@list = $toplevel->colormapwindows( );
You can pass a list of windows to colormapwindows as well:
$toplevel->colormapwindows(@list);
If you don't use this function at all, Perl/Tk will take care of everything for you, although the order of the windows might be different.
The command method (not to be confused with the -command option used with most of the widgets) controls the WM_COMMAND property. When used with no arguments, command returns a list reference:
$listref = $toplevel->command();
The list holds the words of the command used to start the application. Use this bit of code to determine what your application command was (which is sometimes nothing):
$listptr = $mw->command(); foreach (@$listptr) { print "$_\n"; }
You can unset the WM_COMMAND property by sending an empty string:
$toplevel->command("");
The focusmodel method controls whether or not the Toplevel widget will give up the keyboard focus when another application or window should have it:
$toplevel->focusmodel( [ "active" | "passive" ] );
The default is "passive", meaning it will give up the keyboard focus. The changes present in your application depend completely on the type of window manager you use. Our testing revealed no changes under Win32 or the X Window System.
If a widget has been reparented by the windowing system, the frame method returns the window ID of the window manager's decorative Frame. Otherwise, the returned window ID is that of the widget itself. See also the id method.
The grid method restricts the size of a window. However, to avoid conflicts with the grid geometry manager (as described in Chapter 2, "Geometry Management"), you must use the wm method to invoke grid indirectly, as follows:
$mw->wm('grid', ... );
When you tell the window to grid, you are restricting its size. The size must always snap to the grid as defined in grid. If you remember the Listbox widget and the -setgrid option to the Listbox widget back in Chapter 7, "The Listbox Widget", once you use -setgrid => 1 on a Listbox, you can use @list = $toplevel->wm('grid'); to determine the values used in the grid. Supposing the values you get are 10, 10, 7, and 17, this means the base width and height were each 10 pixels and each grid unit incremented by 7 pixels in width and 17 pixels in height. You can change the grid size and increments by calling wm('grid', ...) with new values if you desire; but if you don't, Tk manages everything quite nicely for any of the gridded widgets.
You should also know that you can unset the grid values by using empty strings for each instead of new values.
This is another method you'll never use, but it's good to know about. The group method makes a widget the group leader of related windows. For each Toplevel that you want to be in $widget's group, call $toplevel->group($widget). If $widget isn't specified, it will return the current group leader of $toplevel; it will return an empty string if $toplevel isn't part of a group.
You can send an empty string to cancel Toplevel's association with that group. That is, to remove a Toplevel from the group, call $toplevel->group("").
To make a window with none of the normal window decorations (titlebars, borders, and so on), you can use the overrideredirect method with a true value:
$toplevel->overrideredirect(1); # Remove all decorations
Be careful though; you won't be able to move the window on the screen once it is drawn. If you forgot to put an Exit Button on it, you won't be able to quit the application gracefully (although a Control-C in the window that started the script will kill it).
This is a way to make a splash screen (a screen that shows up as your application is loading). Remember that you must call MainLoop or update for it to show up at all. Chapter 15, "Anatomy of the MainLoop" discusses Tk::Splashscreen.
Calling overrideredirect with no argument returns the current value (1 or 0):
$current_value = $toplevel->overrideredirect();
Calling overrideredirect again with a 0 value will not turn decorations back on once the window has been displayed.
When the Toplevel widget is placed on the window, either the window manager tells the program where to be or the program tells the window manager where it wants to be. In some cases, the user positions the window manually when it comes up.
$who = $toplevel->positionfrom(); $toplevel->positionfrom("program"); # Try and force it
When called without argument, the positionfrom method returns information on which one happened. If it returns the string "program", an empty string, or a $widget, it means either the window manager or the program requested the position. Ifpositionfrom returns the string "user", the user placed the window manually when it was created.
You can try to force which will happen by calling positionfrom with the "program" or "user" string, but it will only work if your window manager agrees with you.
The sizefrom method does the same thing positionfrom does except, it returns information regarding the size of the window.
$who = $toplevel->sizefrom(); # "program" or "user"? $toplevel->sizefrom("user"); # Try and force it
A transient window is one that isn't quite a real window (such as a pulldown menu). You can indicate to the window manager that the Toplevel (for example, the pulldown menu) is related to its master (the window in which it is displayed) by using the transient method:
$mymaster = $toplevel->transient( ); $toplevel->transient($master);
If you don't use any arguments with transient, it returns either the current master or an empty string.
The appearance of transient windows is different among different window managers. On some window managers, there is no difference, whereas some allow for customization with their .rc files. Some only use a minimal title bar, and some show no title bar at all. Iconifying the master window may or may not iconify the transient window as well. Also, sometimes transient windows are always on top of the master window. All of this should be taken into consideration when writing portable code.
Copyright © 2002 O'Reilly & Associates. All rights reserved.