Pmw.1.3.2/ 0000755 0001750 0001750 00000000000 10675673460 011437 5 ustar serge2 serge2 Pmw.1.3.2/src/ 0000755 0001750 0001750 00000000000 10655462400 012212 5 ustar serge2 serge2 Pmw.1.3.2/src/setup.py 0000755 0001750 0001750 00000002730 10675672672 013751 0 ustar serge2 serge2 #!/usr/bin/env python # setup.py from distutils.core import setup setup(name="Pmw", version='1.3.2', description = 'Python Mega Widgets', author="Telstra Corporation Limited, Australia", author_email="", url='http://pmw.sourceforge.net/', package_dir = { "Pmw":"Pmw"}, packages=['Pmw', 'Pmw.Pmw_1_3', 'Pmw.Pmw_1_3.lib',], package_data={'Pmw': ['Pmw_1_3/lib/Pmw.def', 'Pmw_1_3/doc/*', 'Pmw_1_3/contrib/*', 'Pmw_1_3/demos/*', 'Pmw_1_3/tests/*', 'Pmw_1_3/bin/*', ] }, license='BSD', long_description='''Pmw is a toolkit for building high-level compound widgets, or megawidgets, constructed using other widgets as component parts. It promotes consistent look and feel within and between graphical applications, is highly configurable to your needs and is easy to use.''', classifiers = [ 'Development Status :: Alpha', 'Environment :: Console', 'Intended Audience :: End Users/Desktop', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: BSD', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Programming Language :: Python', 'Topic :: GUI', ], ) Pmw.1.3.2/src/Pmw/ 0000755 0001750 0001750 00000000000 10655462400 012755 5 ustar serge2 serge2 Pmw.1.3.2/src/Pmw/__init__.py 0000644 0001750 0001750 00000002627 10656147112 015076 0 ustar serge2 serge2 # This file is executed when the Pmw package is imported. It creates # a lazy importer/dynamic loader for Pmw and replaces the Pmw module # with it. Even though the loader from the most recent installed # version of Pmw is used, the user is able to specify which version of # Pmw megawidgets to load by using the setversion() function of the # loader. # This is the only file in Pmw which is not part of a particular Pmw # release. import sys import os import re def _hasLoader(dir): # Only accept Pmw_V_R_P with single digits, since ordering will # not work correctly with multiple digits (for example, Pmw_10_0 # will be before Pmw_9_9). if re.search('^Pmw_[0-9]_[0-9](_[0-9])?$', dir) is not None: for suffix in ('.py', '.pyc', '.pyo'): path = os.path.join(_dir, dir, 'lib', 'PmwLoader' + suffix) if os.path.isfile(path): return 1 return 0 # First get a list of all subdirectories containing versions of Pmw. _dir = __path__[0] _listdir = os.listdir(_dir) _instdirs = filter(_hasLoader, _listdir) _instdirs.sort() _instdirs.reverse() # Using the latest version import the dynamic loader. _loader = 'Pmw.' + _instdirs[0] + '.lib.PmwLoader' __import__(_loader) _mod = sys.modules[_loader] # Create the dynamic loader and install it into sys.modules. sys.modules['_Pmw'] = sys.modules['Pmw'] sys.modules['Pmw'] = _mod.PmwLoader(_dir, _instdirs, _listdir) Pmw.1.3.2/src/Pmw/README 0000644 0001750 0001750 00000000606 10656147112 013640 0 ustar serge2 serge2 Python megawidgets Pmw is a toolkit for building high-level compound widgets in Python using the Tkinter module. All documentation about Pmw is in the form of html files stored in the 'doc' directory of each release of Pmw. Please use your Web browser to view the file 'doc/index.html' in the directory containing the most recent release. Pmw.1.3.2/src/Pmw/Pmw_1_3/ 0000755 0001750 0001750 00000000000 10655462400 014162 5 ustar serge2 serge2 Pmw.1.3.2/src/Pmw/Pmw_1_3/doc/ 0000755 0001750 0001750 00000000000 10655462400 014727 5 ustar serge2 serge2 Pmw.1.3.2/src/Pmw/Pmw_1_3/doc/refindex.html 0000644 0001750 0001750 00000010627 10656147112 017430 0 ustar serge2 serge2
Pmw 1.3 - 7 Aug 2007 - Home
Pmw.AboutDialog() - window to display version and contact information
An about dialog is a dialog window which displays information about the application, such as name, version, copyright and contact details.
The text of the message is constructed from the application name
(given by the applicationname option) followed by the values
supplied in the most recent calls to Pmw.aboutversion()
,
Pmw.aboutcopyright()
and Pmw.aboutcontact()
functions.
The icon of the message defaults to 'info', but may be changed using the icon_bitmap component option.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
class Demo: def __init__(self, parent): # Create dialog. Pmw.aboutversion('9.9') Pmw.aboutcopyright('Copyright My Company 1999\nAll rights reserved') Pmw.aboutcontact( 'For information about this application contact:\n' + ' My Help Desk\n' + ' Phone: +61 2 9876 5432\n' + ' email: help@my.company.com.au' ) self.about = Pmw.AboutDialog(parent, applicationname = 'My Application') self.about.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show about dialog', command = self.execute) w.pack(padx = 8, pady = 8) def execute(self): self.about.show()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.Balloon() - display "tool tips" for a number of widgets
A balloon megawidget can be used to give short help messages to the user when they place the mouse over a button or other widget for a short time. It can also be used to display help messages for canvas or text items.
One balloon megawidget can be used to display help for many
widgets or items. For each widget or item that requires balloon
help, the bind()
or bindtag()
method is used to specify the
help text that should be displayed.
The help message is displayed in a popup balloon window when the mouse remains over the widget or item for a short time. The popup balloon is withdrawn when the mouse leaves the widget or item, or any mouse buttons are pressed.
The position of the popup balloon is configurable and may appear either relative to the widget or item or relative to the position of the mouse.
The popup balloon is displayed without any window manager decorations.
The megawidget can cooperate with a Pmw.MessageBar to display a single-line help message as well as the balloon help.
activate()
. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
helpmessage
method of the messagebar. The default is None.
Note that tagunbind()
must be called when deleting a canvas
item, so that the popup balloon window can be withdrawn if it was
triggered by the item. (Unfortunately this can not be automated
as is done for widgets since Tk does not support <Destroy>
bindings on canvas items, so there is no way that Pmw.Balloon can
be notified of the deletion of an item.)
class Demo: def __init__(self, parent): # Create the Balloon. self.balloon = Pmw.Balloon(parent) # Create some widgets and megawidgets with balloon help. frame = Tkinter.Frame(parent) frame.pack(padx = 10, pady = 5) field = Pmw.EntryField(frame, labelpos = 'nw', label_text = 'Command:') field.setentry('mycommand -name foo') field.pack(side = 'left', padx = 10) self.balloon.bind(field, 'Command to\nstart/stop', 'Enter the shell command to control') start = Tkinter.Button(frame, text='Start') start.pack(side='left', padx = 10) self.balloon.bind(start, 'Start the command') stop = Tkinter.Button(frame, text='Stop') stop.pack(side='left', padx = 10) self.balloon.bind(stop, 'Stop the command') self.suicide = Tkinter.Button(frame, text='Kill me soon!', command = self.killButton) self.suicide.pack(side='left', padx = 10) self.balloon.bind(self.suicide, 'Watch this button disappear!') scrolledCanvas = Pmw.ScrolledCanvas(parent, canvas_width = 300, canvas_height = 115, ) scrolledCanvas.pack() canvas = scrolledCanvas.component('canvas') self.canvas = canvas # Create some canvas items and individual help. item = canvas.create_arc(5, 5, 35, 35, fill = 'red', extent = 315) self.balloon.tagbind(canvas, item, 'This is help for\nan arc item') item = canvas.create_bitmap(20, 150, bitmap = 'question') self.balloon.tagbind(canvas, item, 'This is help for\na bitmap') item = canvas.create_line(50, 60, 70, 80, 85, 20, width = 5) self.balloon.tagbind(canvas, item, 'This is help for\na line item') item = canvas.create_text(10, 90, text = 'Canvas items with balloons', anchor = 'nw', font = field.cget('entry_font')) self.balloon.tagbind(canvas, item, 'This is help for\na text item') # Create two canvas items which have the same tag and which use # the same help. canvas.create_rectangle(100, 10, 170, 50, fill = 'aliceblue', tags = 'TAG1') self.bluecircle = canvas.create_oval(110, 30, 160, 80, fill = 'blue', tags = 'TAG1') self.balloon.tagbind(canvas, 'TAG1', 'This is help for the two blue items' + '\n' * 10 + 'It is very, very big.', 'This is help for the two blue items') item = canvas.create_text(180, 10, text = 'Delete', anchor = 'nw', font = field.cget('entry_font')) self.balloon.tagbind(canvas, item, 'After 2 seconds,\ndelete the blue circle') canvas.tag_bind(item, '<ButtonPress>', self._canvasButtonpress) scrolledCanvas.resizescrollregion() scrolledText = Pmw.ScrolledText(parent, text_width = 32, text_height = 4, text_wrap = 'none', ) scrolledText.pack(pady = 5) text = scrolledText.component('text') self.text = text text.insert('end', 'This is a text widget with ', '', ' balloon', 'TAG1', '\nhelp. Find the ', '', ' text ', 'TAG1', ' tagged with', '', ' help.', 'TAG2', '\n', '', 'Remove tag 1.', 'TAG3', '\nAnother line.\nAnd another', '', ) text.tag_configure('TAG1', borderwidth = 2, relief = 'sunken') text.tag_configure('TAG3', borderwidth = 2, relief = 'raised') self.balloon.tagbind(text, 'TAG1', 'There is one secret\nballoon help.\nCan you find it?') self.balloon.tagbind(text, 'TAG2', 'Well done!\nYou found it!') self.balloon.tagbind(text, 'TAG3', 'After 2 seconds\ndelete the tag') text.tag_bind('TAG3', '<ButtonPress>', self._textButtonpress) frame = Tkinter.Frame(parent) frame.pack(padx = 10) self.toggleBalloonVar = Tkinter.IntVar() self.toggleBalloonVar.set(1) toggle = Tkinter.Checkbutton(frame, variable = self.toggleBalloonVar, text = 'Balloon help', command = self.toggle) toggle.pack(side = 'left', padx = 10) self.balloon.bind(toggle, 'Toggle balloon help\non and off') self.toggleStatusVar = Tkinter.IntVar() self.toggleStatusVar.set(1) toggle = Tkinter.Checkbutton(frame, variable = self.toggleStatusVar, text = 'Status help', command = self.toggle) toggle.pack(side = 'left', padx = 10) self.balloon.bind(toggle, 'Toggle status help on and off, on and off' + '\n' * 10 + 'It is very, very big, too.', 'Toggle status help on and off') # Create and pack the MessageBar. messageBar = Pmw.MessageBar(parent, entry_width = 40, entry_relief='groove', labelpos = 'w', label_text = 'Status:') messageBar.pack(fill = 'x', expand = 1, padx = 10, pady = 5) # Configure the balloon to display its status messages in the # message bar. self.balloon.configure(statuscommand = messageBar.helpmessage) def toggle(self): if self.toggleBalloonVar.get(): if self.toggleStatusVar.get(): self.balloon.configure(state = 'both') else: self.balloon.configure(state = 'balloon') else: if self.toggleStatusVar.get(): self.balloon.configure(state = 'status') else: self.balloon.configure(state = 'none') def killButton(self): # Test for old bug when destroying widgets 1) while the # balloon was up and 2) during the initwait period. print 'Destroying button in 2 seconds' self.suicide.after(2000, self.suicide.destroy) def _canvasButtonpress(self, event): print 'Destroying blue circle in 2 seconds' self.canvas.after(2000, self.deleteBlueCircle) def deleteBlueCircle(self): self.balloon.tagunbind(self.canvas, self.bluecircle) self.canvas.delete(self.bluecircle) def _textButtonpress(self, event): print 'Deleting the text tag in 2 seconds' self.text.after(2000, self.deleteTextTag) def deleteTextTag(self): self.balloon.tagunbind(self.text, 'TAG1') self.text.tag_delete('TAG1')
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 20 May 2002
Pmw.ButtonBox() - manager megawidget for buttons
A button box is a container megawidget which manages a number of buttons. One of these buttons may be specified as the default and it will be displayed with the platform specific appearance for a default button. The buttons may be laid out either horizontally or vertically.
If None, a label component is not created. The default is None.
add()
and
insert()
methods. If there is no label component, then no
frame component is created and the hull component acts as the
container. By default, this component is a Tkinter.Frame.
Button components are created dynamically by the add()
and
insert()
methods. By default, the buttons are of type
Tkinter.Button and are created with a component group of
Button.
index()
method.
index()
method.
If forInsert is true, Pmw.END returns the number of buttons rather than the index of the last button.
index()
method. Any keyword arguments present
will be passed to the constructor when creating the button. If
the text keyword argument is not given, the text option of the
button defaults to componentName. To add a button to the end of
the button box, use add()
. The method returns the component
widget.
index()
method.
index()
method.
class Demo: def __init__(self, parent): # Create and pack the ButtonBox. self.buttonBox = Pmw.ButtonBox(parent, labelpos = 'nw', label_text = 'ButtonBox:', frame_borderwidth = 2, frame_relief = 'groove') self.buttonBox.pack(fill = 'both', expand = 1, padx = 10, pady = 10) # Add some buttons to the ButtonBox. self.buttonBox.add('OK', command = self.ok) self.buttonBox.add('Apply', command = self.apply) self.buttonBox.add('Cancel', command = self.cancel) # Set the default button (the one executed when <Return> is hit). self.buttonBox.setdefault('OK') parent.bind('<Return>', self._processReturnKey) parent.focus_set() # Make all the buttons the same width. self.buttonBox.alignbuttons() def _processReturnKey(self, event): self.buttonBox.invoke() def ok(self): print 'You clicked on OK' def apply(self): print 'You clicked on Apply' def cancel(self): print 'You clicked on Cancel'
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 24 May 1998
Pmw.ComboBox() - dropdown or simple combination box
A combobox contains an entry field and an associated scrolled listbox. When an item in the listbox is selected, it is displayed in the entry field. Optionally, the user may also edit the entry field directly.
For a simple combobox, the scrolled listbox is displayed beneath the entry field. For a dropdown combobox (the default), the scrolled listbox is displayed in a window which pops up beneath the entry field when the user clicks on an arrow button on the right of the entry field. Either style allows an optional label.
If None, a label component is not created. The default is None.
update_idletasks()
at the
beginning of the function. Alternatively, wrap the function using
Pmw.busycallback()
. The default is None.
bbox()
method. Without this explicit forwarding,
the bbox()
method (aliased to grid_bbox()
) of the hull would
be invoked, which is probably not what the programmer intended.
get()
method of the scrolledlist
component, except that if first is None then
the value of the entry field is returned.
If setentry is true, also set the entry field to the selected item.
size()
method. Without this explicit forwarding,
the size()
method (aliased to grid_size()
) of the hull would
be invoked, which is probably not what the programmer intended.
class Demo: def __init__(self, parent): parent.configure(background = 'white') # Create and pack the widget to be configured. self.target = Tkinter.Label(parent, relief = 'sunken', padx = 20, pady = 20, ) self.target.pack(fill = 'x', padx = 8, pady = 8) # Create and pack the simple ComboBox. words = ('Monti', 'Python', 'ik', 'den', 'Holie', 'Grailen', '(Bok)') simple = Pmw.ComboBox(parent, label_text = 'Simple ComboBox:', labelpos = 'nw', selectioncommand = self.changeText, scrolledlist_items = words, dropdown = 0, ) simple.pack(side = 'left', fill = 'both', expand = 1, padx = 8, pady = 8) # Display the first text. first = words[0] simple.selectitem(first) self.changeText(first) # Create and pack the dropdown ComboBox. colours = ('cornsilk1', 'snow1', 'seashell1', 'antiquewhite1', 'bisque1', 'peachpuff1', 'navajowhite1', 'lemonchiffon1', 'ivory1', 'honeydew1', 'lavenderblush1', 'mistyrose1') dropdown = Pmw.ComboBox(parent, label_text = 'Dropdown ComboBox:', labelpos = 'nw', selectioncommand = self.changeColour, scrolledlist_items = colours, ) dropdown.pack(side = 'left', anchor = 'n', fill = 'x', expand = 1, padx = 8, pady = 8) # Display the first colour. first = colours[0] dropdown.selectitem(first) self.changeColour(first) def changeColour(self, colour): print 'Colour: ' + colour self.target.configure(background = colour) def changeText(self, text): print 'Text: ' + text self.target.configure(text = text)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 1 November 1998
Pmw.ComboBoxDialog() - selection dialog displaying a list and an entry field
A combobox dialog is a dialog window which displays a list and an entry field which can be used to prompt the user for a value.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
dropdown = 0
. By default, this component is a Pmw.ComboBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
size()
method. Without this explicit forwarding, the size()
method (aliased to grid_size()
) of the hull would be invoked,
which is probably not what the programmer intended.
class Demo: def __init__(self, parent): # Create the dialog. self.dialog = Pmw.ComboBoxDialog(parent, title = 'My ComboBoxDialog', buttons = ('OK', 'Cancel'), defaultbutton = 'OK', combobox_labelpos = 'n', label_text = 'What do you think of Pmw?', scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross')) self.dialog.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show combo box dialog', command = self.doit) w.pack(padx = 8, pady = 8) def doit(self): result = self.dialog.activate() print 'You clicked on', result, self.dialog.get()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.Counter() - entry field with up and down arrow buttons
A counter contains an entry field and two arrow buttons to increment and decrement the value in the entry field. Standard counting types include numbers, times and dates. A user defined counting function may also be supplied for specialised counting. Counting can be used in combination with the entry field's validation. The components may be laid out horizontally or vertically.
Each time an arrow button is pressed the value displayed in the entry field is incremented or decremented by the value of the increment option. If the new value is invalid (according to the entry field's validate option, perhaps due to exceeding minimum or maximum limits), the old value is restored.
When an arrow button is pressed and the value displayed is not an exact multiple of the increment, it is "truncated" up or down to the nearest increment.
The most general way to specify the datatype option is as a dictionary. The kind of counting is specified by the 'counter' dictionary field, which may be either a function or the name of one of the standard counters described below. If the dictionary does not have a 'counter' field, the field defaults to 'numeric'.
Any other fields in the dictionary are passed on to the counter function as keyword arguments.
If datatype is not a dictionary, then it is equivalent to
specifying it as a dictionary with a single 'counter' field.
For example, datatype = 'real'
is equivalent to
datatype = {'counter' : 'real'}
.
The standard counters are:
string.atol()
.
string.atof()
. This
counter accepts a 'separator' argument, which specifies
the character used to represent the decimal point. The
default 'separator' is '.'.
Pmw.timestringtoseconds()
. This counter accepts a
'separator' argument, which specifies the character used to
separate the time fields. The default separator is ':'.
This counter also accepts a 'time24' argument. If this is
true, the time value is converted to a value between
'00:00:00' and '23:59:59'. The default is false.
Pmw.datestringtojdn()
. This counter accepts a 'separator'
argument, which specifies the character used to separate the
three date fields. The default is '/'. This counter also
accepts a 'format' argument, which is passed to
Pmw.datestringtojdn()
to specify the desired ordering of the
fields. The default is 'ymd'.
This counter also accepts a 'yyyy' argument. If this is
false, the year field will be displayed as the year within the
century, otherwise it will be fully displayed. In both cases
it will be displayed with at least 2 digits, using leading
zeroes. The default is false.
If the 'counter' dictionary field is a function, then it will be called whenever the counter is to be incremented or decremented. The function is called with at least three arguments, the first three being (text, factor, increment), where text is the current contents of the entry field, factor is 1 when incrementing or -1 when decrementing, and increment is the value of the increment megawidget option.
The other arguments are keyword arguments made up of the fields of the datatype dictionary (excluding the 'counter' field).
The counter function should return a string representing the incremented or decremented value. It should raise a ValueError exception if the text is invalid. In this case the bell is rung and the entry text is not changed.
The default for datatype is numeric.
For the number datatypes, the value of increment is a number. For the 'time' datatype, the value is in seconds. For the 'date' datatype, the value is in days. The default is 1.
If None, a label component is not created. The default is None.
class Demo: def __init__(self, parent): # Need to use long ints here because on the Macintosh the maximum size # of an integer is smaller than the value returned by time.time(). now = (long(time.time()) / 300) * 300 # Create the Counters. self._date = Pmw.Counter(parent, labelpos = 'w', label_text = 'Date (4-digit year):', entryfield_value = time.strftime('%d/%m/%Y', time.localtime(now)), entryfield_command = self.execute, entryfield_validate = {'validator' : 'date', 'format' : 'dmy'}, datatype = {'counter' : 'date', 'format' : 'dmy', 'yyyy' : 1}) self._isodate = Pmw.Counter(parent, labelpos = 'w', label_text = 'ISO-Date (4-digit year):', entryfield_value = time.strftime('%Y-%m-%d', time.localtime(now)), entryfield_command = self.execute, entryfield_validate = {'validator' : 'date', 'format' : 'ymd', 'separator' : '-' }, datatype = {'counter' : 'date', 'format' : 'ymd', 'yyyy' : 1, 'separator' : '-' }) self._time = Pmw.Counter(parent, labelpos = 'w', label_text = 'Time:', entryfield_value = time.strftime('%H:%M:%S', time.localtime(now)), entryfield_validate = {'validator' : 'time', 'min' : '00:00:00', 'max' : '23:59:59', 'minstrict' : 0, 'maxstrict' : 0}, datatype = {'counter' : 'time', 'time24' : 1}, increment=5*60) self._real = Pmw.Counter(parent, labelpos = 'w', label_text = 'Real (with comma)\nand extra\nlabel lines:', label_justify = 'left', entryfield_value = '1,5', datatype = {'counter' : 'real', 'separator' : ','}, entryfield_validate = {'validator' : 'real', 'min' : '-2,0', 'max' : '5,0', 'separator' : ','}, increment = 0.1) self._custom = Pmw.Counter(parent, labelpos = 'w', label_text = 'Custom:', entryfield_value = specialword[:4], datatype = _custom_counter, entryfield_validate = _custom_validate) self._int = Pmw.Counter(parent, labelpos = 'w', label_text = 'Vertical integer:', orient = 'vertical', entry_width = 2, entryfield_value = 50, entryfield_validate = {'validator' : 'integer', 'min' : 0, 'max' : 99} ) counters = (self._date, self._isodate, self._time, self._real, self._custom) Pmw.alignlabels(counters) # Pack them all. for counter in counters: counter.pack(fill='both', expand=1, padx=10, pady=5) self._int.pack(padx=10, pady=5) def execute(self): print 'Return pressed, value is', self._date.get() specialword = 'Monti Python ik den Holie Grailen (Bok)' def _custom_validate(text): if string.find(specialword, text) == 0: return 1 else: return -1 def _custom_counter(text, factor, increment): # increment is ignored here. if string.find(specialword, text) == 0: length = len(text) if factor == 1: if length >= len(specialword): raise ValueError, 'maximum length reached' return specialword[:length + 1] else: if length == 0: raise ValueError, 'empty string' return specialword[:length - 1] else: raise ValueError, 'bad string ' + text
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 24 May 1998
Pmw.CounterDialog() - selection dialog displaying a counter
A counter dialog is a dialog window which displays a counter which can be used to prompt the user for a value.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
component('entry').delete()
.
component('entry').index()
.
component('entry').insert()
.
class Demo: def __init__(self, parent): # Create the dialog to prompt for the number of times to ring the bell. self.dialog = Pmw.CounterDialog(parent, label_text = 'Enter the number of times to\n' + \ 'sound the bell (1 to 5)\n', counter_labelpos = 'n', entryfield_value = 2, counter_datatype = 'numeric', entryfield_validate = {'validator' : 'numeric', 'min' : 1, 'max' : 5}, buttons = ('OK', 'Cancel'), defaultbutton = 'OK', title = 'Bell ringing', command = self.execute) self.dialog.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show counter dialog', command = self.dialog.activate) w.pack(padx = 8, pady = 8) def execute(self, result): if result is None or result == 'Cancel': print 'Bell ringing cancelled' self.dialog.deactivate() else: count = self.dialog.get() if not self.dialog.valid(): print 'Invalid entry: "' + count + '"' else: print 'Ringing the bell ' + count + ' times' for num in range(string.atoi(count)): if num != 0: self.dialog.after(200) self.dialog.bell() self.dialog.deactivate()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.Dialog() - toplevel window with button box
A dialog is a toplevel window composed of a button box and a child site area. The child site area can be used to specialise the megawidget by creating other widgets within it. This can be done by using this class directly or by deriving from it.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
component('dialogchildsite')
.
index()
method.
class Demo: def __init__(self, parent): # Create two buttons to launch the dialog. w = Tkinter.Button(parent, text = 'Show application modal dialog', command = self.showAppModal) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'Show global modal dialog', command = self.showGlobalModal) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'Show dialog with "no grab"', command = self.showDialogNoGrab) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'Show toplevel window which\n' + 'will not get a busy cursor', command = self.showExcludedWindow) w.pack(padx = 8, pady = 8) # Create the dialog. self.dialog = Pmw.Dialog(parent, buttons = ('OK', 'Apply', 'Cancel', 'Help'), defaultbutton = 'OK', title = 'My dialog', command = self.execute) self.dialog.withdraw() # Add some contents to the dialog. w = Tkinter.Label(self.dialog.interior(), text = 'Pmw Dialog\n(put your widgets here)', background = 'black', foreground = 'white', pady = 20) w.pack(expand = 1, fill = 'both', padx = 4, pady = 4) # Create the window excluded from showbusycursor. self.excluded = Pmw.MessageDialog(parent, title = 'I still work', message_text = 'This window will not get\n' + 'a busy cursor when modal dialogs\n' + 'are activated. In addition,\n' + 'you can still interact with\n' + 'this window when a "no grab"\n' + 'modal dialog is displayed.') self.excluded.withdraw() Pmw.setbusycursorattributes(self.excluded.component('hull'), exclude = 1) def showAppModal(self): self.dialog.activate(geometry = 'centerscreenalways') def showGlobalModal(self): self.dialog.activate(globalMode = 1) def showDialogNoGrab(self): self.dialog.activate(globalMode = 'nograb') def showExcludedWindow(self): self.excluded.show() def execute(self, result): print 'You clicked on', result if result not in ('Apply', 'Help'): self.dialog.deactivate(result)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.EntryField() - entry widget with validation
An entry field contains an entry widget with optional validation of various kinds. Built-in validation may be used, such as integer, real, time or date, or an external validation function may be supplied. If valid text is entered, it will be displayed with the normal background. If invalid text is entered, it is not displayed and the previously displayed text is restored. If partially valid text is entered, it will be displayed with a background color to indicate it is in error. An example of partially valid real text is '-.', which may be the first two charactes of the valid string '-.5'. Some validators, such as date, have a relaxed interpretation of partial validity, which allows the user flexibility in how they enter the text.
Validation is performed early, at each keystroke or other event which modifies the text. However, if partially valid text is permitted, the validity of the entered text can be checked just before it is to be used, which is a form of late validation.
Minimum and maximum values may be specified. Some validators also accept other specifications, such as date and time formats and separators.
Validation is performed by a function which takes as its first argument the entered text and returns one of three standard values, indicating whether the text is valid:
invoke()
is called. The default is None.
The validate_function is used to implement the validation and the stringtovalue_function is used to convert the entry input into a value which can be compared with the minimum and maximum limits. These functions are as described for the validate option.
If either of these is not given as a function, it is assumed to be the name of one of the other extra validators or one of the standard validators. The alias search is performed when the validate option is configured, not when the extravalidators option is configured or when the validate function is called.
If the name of one of the extra validators is the same as one of the standard validators, the extra validator takes precedence. The default is {}.
setentry()
. The default
is self.bell.
If None, a label component is not created. The default is None.
setentry()
. The default is None.
The most general way to specify the validate option is as a dictionary. The kind of validation is specified by the 'validator' dictionary field, which may be the name of one of the standard validators described below, the name of a validator supplied by the extravalidators option, a function or None. The default is None.
Any other dictionary fields specify other restrictions on the entered values. For all validators, the following fields may be specified:
If the dictionary contains a 'stringtovalue' field, it overrides the normal stringtovalue function for the validator. The stringtovalue function is described below.
Other fields in the dictionary (apart from the core fields mentioned above) are passed on to the validator and stringtovalue functions as keyword arguments.
If validate is not a dictionary, then it is equivalent to
specifying it as a dictionary with a single 'validator' field.
For example, validate = 'real'
is equivalent to /validate =
{'validator' : 'real'}/ and specifies real numbers without any
minimum or maximum limits and using '.' as the decimal point
character.
The standard validators accepted in the 'validator' field are:
string.atol()
.
string.atol(text, 16)
.
string.atof()
. This
validator accepts a 'separator' argument, which specifies
the character used to represent the decimal point. The
default 'separator' is '.'.
Pmw.timestringtoseconds()
.
This validator accepts a 'separator' argument, which
specifies the character used to separate the three fields.
The default separator is ':'. The time may be negative.
Pmw.datestringtojdn()
. This validator accepts a
'separator' argument, which specifies the character used to
separate the three fields. The default is ':'. This
validator also accepts a 'format' argument, which is passed to
Pmw.datestringtojdn()
to specify the desired ordering of the
fields. The default is 'ymd'.
If 'validator' is a function, then it will be called whenever
the contents of the entry may have changed due to user action or
by a call to setentry()
. The function is called with at least
one argument, the first one being the new text as modified by the
user or setentry()
. The other arguments are keyword arguments
made up of the non-core fields of the validate dictionary.
The validator function should return Pmw.OK, Pmw.ERROR or Pmw.PARTIAL as described above. It should not perform minimum and maximum checking. This is done after the call, if it returns Pmw.OK.
The 'stringtovalue' field in the dictionary may be specified as the name of one of the standard validators, the name of a validator supplied by the extravalidators option, a function or None.
The stringtovalue function is used to convert the entry input
into a value which can then be compared with any minimum or
maximum values specified for the validator. If the 'min' or
'max' fields are specified as strings, they are converted using
the stringtovalue function. The stringtovalue function is
called with the same arguments as the validator function. The
stringtovalue function for the standard number validators
convert the string to a number. Those for the standard alpha
validators return the length of the string. Those for the
standard 'time' and 'date' validators return the number of
seconds and the Julian Day Number, respectively. See
Pmw.stringtoreal()
, Pmw.timestringtoseconds()
and
Pmw.datestringtojdn()
.
If the validator has been specified as a function and no
'stringtovalue' field is given, then it defaults to the standard
python len()
function.
If 'validator' is None, no validation is performed. However, minimum and maximum checking may be performed, according to the stringtovalue function. For example, to limit the entry text to a maximum of five characters:
Pmw.EntryField(validate = {'max' : 5})
The validator functions for each of the standard validators can be accessed as:
Pmw.numericvalidator Pmw.integervalidator Pmw.hexadecimalvalidator Pmw.realvalidator Pmw.alphabeticvalidator Pmw.alphanumericvalidator Pmw.timevalidator Pmw.datevalidator
Whenever the validate option is configured, the text currently displayed in the entry widget is revalidated. If it is not valid, the errorbackground color is set and the invalidcommand function is called. However, the displayed text is not modified.
The default for validate is None.
set()
method of the variable is called. If this
is not done in this case, the entry widget background will not be
set correctly.
setentry('')
.
setvalue()
method.
class Demo: def __init__(self, parent): # Create and pack the EntryFields. self._any = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Any:', validate = None, command = self.execute) self._real = Pmw.EntryField(parent, labelpos = 'w', value = '55.5', label_text = 'Real (10.0 to 99.0):', validate = {'validator' : 'real', 'min' : 10, 'max' : 99, 'minstrict' : 0}, modifiedcommand = self.changed) self._odd = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Odd length:', validate = self.custom_validate, value = 'ABC') self._date = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Date (in 2000):', value = '2000/2/29', validate = {'validator' : 'date', 'min' : '2000/1/1', 'max' : '2000/12/31', 'minstrict' : 0, 'maxstrict' : 0, 'format' : 'ymd'}, ) now = time.localtime(time.time()) self._date2 = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Date (d.m.y):', value = '%d.%d.%d' % (now[2], now[1], now[0]), validate = {'validator' : 'date', 'format' : 'dmy', 'separator' : '.'}, ) self._time = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Time (24hr clock):', value = '8:00:00', validate = {'validator' : 'time', 'min' : '00:00:00', 'max' : '23:59:59', 'minstrict' : 0, 'maxstrict' : 0}, ) self._comma = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Real (with comma):', value = '123,456', validate = {'validator' : 'real', 'separator' : ','}, ) entries = (self._any, self._real, self._odd, self._date, self._date2, self._time, self._comma) for entry in entries: entry.pack(fill='x', expand=1, padx=10, pady=5) Pmw.alignlabels(entries) self._any.component('entry').focus_set() def changed(self): print 'Text changed, value is', self._real.getvalue() def execute(self): print 'Return pressed, value is', self._any.getvalue() # This implements a custom validation routine. It simply checks # if the string is of odd length. def custom_validate(self, text): print 'text:', text if len(text) % 2 == 0: return -1 else: return 1
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 May 1998
Pmw.Group() - frame with ring border and tag
This megawidget consists of an interior frame with an exterior ring border and an identifying tag displayed over the top edge of the ring. The programmer can create other widgets within the interior frame.
tag_pyclass = None
, then no tag component is created. By default, this component is a Tkinter.Label.
component('groupchildsite')
.
class Demo: def __init__(self, parent): # Create and pack the Groups. w = Pmw.Group(parent, tag_text='label') w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) cw = Tkinter.Label(w.interior(), text = 'A group with the\ndefault Label tag') cw.pack(padx = 2, pady = 2, expand='yes', fill='both') w = Pmw.Group(parent, tag_pyclass = None) w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) cw = Tkinter.Label(w.interior(), text = 'A group\nwithout a tag') cw.pack(padx = 2, pady = 2, expand='yes', fill='both') radiogroups = [] self.var = Tkinter.IntVar() self.var.set(0) radioframe = Tkinter.Frame(parent) w = Pmw.Group(radioframe, tag_pyclass = Tkinter.Radiobutton, tag_text='radiobutton 1', tag_value = 0, tag_variable = self.var) w.pack(fill = 'both', expand = 1, side='left') cw = Tkinter.Frame(w.interior(),width=200,height=20) cw.pack(padx = 2, pady = 2, expand='yes', fill='both') radiogroups.append(w) w = Pmw.Group(radioframe, tag_pyclass = Tkinter.Radiobutton, tag_text='radiobutton 2', tag_font = Pmw.logicalfont('Helvetica', 4), tag_value = 1, tag_variable = self.var) w.pack(fill = 'both', expand = 1, side='left') cw = Tkinter.Frame(w.interior(),width=200,height=20) cw.pack(padx = 2, pady = 2, expand='yes', fill='both') radiogroups.append(w) radioframe.pack(padx = 6, pady = 6, expand='yes', fill='both') Pmw.aligngrouptags(radiogroups) w = Pmw.Group(parent, tag_pyclass = Tkinter.Checkbutton, tag_text='checkbutton', tag_foreground='blue') w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) cw = Tkinter.Frame(w.interior(),width=150,height=20) cw.pack(padx = 2, pady = 2, expand='yes', fill='both') w = Pmw.Group(parent, tag_pyclass = Tkinter.Button, tag_text='Tkinter.Button') w.configure(tag_command = w.toggle) w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) cw = Tkinter.Label(w.interior(), background = 'aliceblue', text = 'A group with\na Button tag!?' ) cw.pack(padx = 2, pady = 2, expand='yes', fill='both') w = Pmw.Group(parent, tag_pyclass = Tkinter.Button, tag_text='Show/Hide') w.configure(tag_command = w.toggle) w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) cw = Tkinter.Label(w.interior(), background = 'aliceblue', text = 'Now you see me.\nNow you don\'t.' ) cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 15 November 1998
Pmw.HistoryText() - text widget with a course-grained form of history
A history text is a scrolled text widget with added functionality to maintain a history of each screen and allow editing of prior screens. Here, screen refers to the entire contents of the text widget. This widget does not support a fine-grained history of every change made to the text.
Together with a few buttons and a scrolled text to display the results, a history text can be used as the query-entry part of a simple interactive text-based database query system. When the user enters and executes a query, the query (the entire contents of the text widget) is added to the history list. The user may view previous queries and either execute them again or modify them and execute the new query. If a previously executed query is modified, the user may undo or redo all changes made to the query before the query is executed.
addhistory()
. The default is 1.
addhistory()
. The default is 1.
next()
and prev()
methods. The default is None.
If None, a label component is not created. The default is None.
Otherwise, the size of the megawidget is determined by the width and height of the text component, along with the size and/or existence of the other components, such as the label, the scrollbars and the scrollmargin option. All these affect the overall size of the megawidget. The default is 0.
If compressany is true, a new entry will be added to the history list only if the currently displayed entry has changed.
If compresstail is true, a new entry will be added to the history list only if the currently displayed entry has changed or if it is not the last entry in the history list.
addhistory()
. The second item is the edited text (if the user
has modified the entry but addhistory()
has not yet been called
on the text). The third item specifies whether the entry should
currently display the original or modified text.
undo()
.
class Demo: def __init__(self, parent): # Create and pack the PanedWidget to hold the query and result # windows. # !! panedwidget should automatically size to requested size panedWidget = Pmw.PanedWidget(parent, orient = 'vertical', hull_height = 400, hull_width = 550) panedWidget.add('query', min = 0.05, size = 0.2) panedWidget.add('buttons', min = 0.1, max = 0.1) panedWidget.add('results', min = 0.05) panedWidget.pack(fill = 'both', expand = 1) # Create and pack the HistoryText. self.historyText = Pmw.HistoryText(panedWidget.pane('query'), text_wrap = 'none', text_width = 60, text_height = 10, historycommand = self.statechange, ) self.historyText.pack(fill = 'both', expand = 1) self.historyText.component('text').focus() buttonList = ( [20, None], ['Clear', self.clear], ['Undo', self.historyText.undo], ['Redo', self.historyText.redo], [20, None], ['Prev', self.historyText.prev], ['Next', self.historyText.next], [30, None], ['Execute', Pmw.busycallback(self.executeQuery)], ) self.buttonDict = {} buttonFrame = panedWidget.pane('buttons') for text, cmd in buttonList: if type(text) == type(69): frame = Tkinter.Frame(buttonFrame, width = text) frame.pack(side = 'left') else: button = Tkinter.Button(buttonFrame, text = text, command = cmd) button.pack(side = 'left') self.buttonDict[text] = button for text in ('Prev', 'Next'): self.buttonDict[text].configure(state = 'disabled') self.results = Pmw.ScrolledText(panedWidget.pane('results'), text_wrap = 'none') self.results.pack(fill = 'both', expand = 1) def statechange(self, prevstate, nextstate): self.buttonDict['Prev'].configure(state = prevstate) self.buttonDict['Next'].configure(state = nextstate) def clear(self): self.historyText.delete('1.0', 'end') def addnewlines(self, text): if len(text) == 1: text = text + '\n' if text[-1] != '\n': text = text + '\n' if text[-2] != '\n': text = text + '\n' return text def executeQuery(self): sql = self.historyText.get() self.results.insert('end', 'Query:\n' + self.addnewlines(sql)) self.results.see('end') self.results.update_idletasks() self.historyText.addhistory() results = 'Results:\nfoo' if len(results) > 0: self.results.insert('end', self.addnewlines(results)) self.results.see('end')
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 20 May 2002
Pmw.LabeledWidget() - frame with label
This megawidget consists of an interior frame with an associated label which can be positioned on any side of the frame. The programmer can create other widgets within the interior frame.
If None, a label component is not created. The default is None.
component('labelchildsite')
.
class Demo: def __init__(self, parent): # Create a frame to put the LabeledWidgets into frame = Tkinter.Frame(parent, background = 'grey90') frame.pack(fill = 'both', expand = 1) # Create and pack the LabeledWidgets. column = 0 row = 0 for pos in ('n', 'nw', 'wn', 'w'): lw = Pmw.LabeledWidget(frame, labelpos = pos, label_text = pos + ' label') lw.component('hull').configure(relief='sunken', borderwidth=2) lw.grid(column=column, row=row, padx=10, pady=10) cw = Tkinter.Button(lw.interior(), text='child\nsite') cw.pack(padx=10, pady=10, expand='yes', fill='both') # Get ready for next grid position. column = column + 1 if column == 2: column = 0 row = row + 1
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 8 November 1998
Pmw.MainMenuBar() - manager for toplevel native menus
This class is a wrapper for the Tkinter.Menu class. It should be used as the main menu of toplevel windows. The class is similar to Pmw.MenuBar, but should be used when native menus are required. See the Tkinter.Menu documentation for full details.
This class should be created as the child of a Tkinter.Toplevel
and should then be specified as the menu associated with the
toplevel, using the toplevel's configure()
method. For example:
# Create a Pmw.MegaToplevel. megaToplevel = Pmw.MegaToplevel() # Get the Tkinter.Toplevel from Pmw.MegaToplevel. toplevel = megaToplevel.interior() # Create the menu bar for the toplevel. menuBar = Pmw.MainMenuBar(toplevel) # Configure the toplevel to use the menuBar. toplevel.configure(menu = menuBar)
There are methods to add menus, both as toplevel menus and sub-menus, and for adding menu items to the menus. Each menu item may have help text to be displayed by a Pmw.Balloon. Each menu and cascaded menu (sub-menu) is referenced by name which is supplied on creation.
This megawidget is derived from Pmw.MegaArchetype (not Pmw.MegaWidget like most other megawidgets), with the hull class being Tkinter.Menu.
(Note that due to bugs in Tk's menubar functionality, balloon help has not been implemented and status help does not work properly.)
Due to a bug in some versions of Tk (8.0 and possible others), help text will not be displayed by the balloon. However, help text will be displayed in the balloon's associated messagebar. The default is None.
To select a menu, simultaneously press the <Alt> key and the accelerator character indicated on a toplevel menu item. The arrows keys can then be used to select other menus and menu items. To invoke a menu item, press <Return> or press the accelerator character indicated on the menu item.
Each accelerator character will be assigned automatically unless
traverseSpec is supplied to the addmenu()
, addmenuitem()
or
addcascademenu()
methods. The automatically selected
accelerator character for a menu item is the first character in
the label text that has not already been used as an accelerator in
the menu containing the menu item.
If traverseSpec is given, it must be either an integer or a character. If an integer, it specifies the index of the character in the label text to use as the accelerator character. If a character, it specifies the character to use as the accelerator character. The default is 1.
Menu components are created dynamically by the addmenu()
and
addcascademenu()
methods. By default, these are of type
Tkinter.Menu and are created with a component group of Menu.
addmenu()
or addcascademenu()
methods.
A menu item in the parent menu is created (with the
add_cascade()
method of the parent menu) using all keyword
arguments except tearoff and name.
If the label keyword argument is not given, the label option of the menu item defaults to menuName. If the underline keyword argument is not given (and the hotkeys megawidget option is true) the underline option is determined as described under hotkeys and is used to specify the keyboard accelerator.
The statusHelp argument is used as the help string for the menu
item. This is displayed using the showstatus()
method of the
balloon.
The tearoff and name keyword arguments, if present, are passed to the constructor of the menu. See Tkinter.Menu for details of these options. The menu is created as a component named menuName.
addmenu()
or addcascademenu()
methods.
A menu item in the toplevel menu is created (with the
add_cascade()
method) using all keyword arguments except
tearoff and name.
If the label keyword argument is not given, the label option of the menu button defaults to menuName. If the underline keyword argument is not given (and the hotkeys megawidget option is true) the underline option is determined as described under hotkeys and is used to specify the keyboard accelerator.
The statusHelp argument is used as the help string for the menu
item. This is displayed using the showstatus()
method of the
balloon. Currently balloonHelp is not used, due to a bug in Tk
version 8.0.
The tearoff and name keyword arguments, if present, are passed to the constructor of the menu. See Tkinter.Menu for details of these options. The menu is created as a component named menuName.
addcascademenu()
method). Any
keyword arguments present will be passed to the menu when creating
the menu item. See Tkinter.Menu for the valid options for each
item type. In addition, a keyboard accelerator may be
automatically given to the item, as described under hotkeys.
When the mouse is moved over the menu item, the helpString will be displayed by the balloon's statuscommand.
class Demo: def __init__(self, parent): # Create button to launch the toplevel with main menubar. w = Tkinter.Button(parent, text = 'Show Pmw.MainMenuBar demo', command = lambda parent=parent: MainMenuBarToplevel(parent)) w.pack(padx = 8, pady = 8) class MainMenuBarToplevel: def __init__(self, parent): # Create the toplevel to contain the main menubar. megaToplevel = Pmw.MegaToplevel(parent, title = title) toplevel = megaToplevel.interior() # Create the Balloon for this toplevel. self.balloon = Pmw.Balloon(toplevel) # Create and install the MenuBar. menuBar = Pmw.MainMenuBar(toplevel, balloon = self.balloon) toplevel.configure(menu = menuBar) self.menuBar = menuBar # Add some buttons to the MainMenuBar. menuBar.addmenu('File', 'Close this window or exit') menuBar.addmenuitem('File', 'command', 'Close this window', command = PrintOne('Action: close'), label = 'Close') menuBar.addmenuitem('File', 'separator') menuBar.addmenuitem('File', 'command', 'Exit the application', command = PrintOne('Action: exit'), label = 'Exit') menuBar.addmenu('Edit', 'Cut, copy or paste') menuBar.addmenuitem('Edit', 'command', 'Delete the current selection', command = PrintOne('Action: delete'), label = 'Delete') menuBar.addmenu('Options', 'Set user preferences') menuBar.addmenuitem('Options', 'command', 'Set general preferences', command = PrintOne('Action: general options'), label = 'General...') # Create a checkbutton menu item. self.toggleVar = Tkinter.IntVar() # Initialise the checkbutton to 1: self.toggleVar.set(1) menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off', label = 'Toggle', command = self._toggleMe, variable = self.toggleVar) self._toggleMe() menuBar.addcascademenu('Options', 'Size', 'Set some other preferences', traverseSpec = 'z', tearoff = 1) for size in ('tiny', 'small', 'average', 'big', 'huge'): menuBar.addmenuitem('Size', 'command', 'Set size to ' + size, command = PrintOne('Action: size ' + size), label = size) menuBar.addmenu('Help', 'User manuals', name = 'help') menuBar.addmenuitem('Help', 'command', 'About this application', command = PrintOne('Action: about'), label = 'About...') # Create and pack the main part of the window. self.mainPart = Tkinter.Label(toplevel, text = 'This is the\nmain part of\nthe window', background = 'black', foreground = 'white', padx = 30, pady = 30) self.mainPart.pack(fill = 'both', expand = 1) # Create and pack the MessageBar. self.messageBar = Pmw.MessageBar(toplevel, entry_width = 40, entry_relief='groove', labelpos = 'w', label_text = 'Status:') self.messageBar.pack(fill = 'x', padx = 10, pady = 10) self.messageBar.message('state', 'Balloon/status help not working properly - Tk menubar bug') buttonBox = Pmw.ButtonBox(toplevel) buttonBox.pack(fill = 'x') buttonBox.add('Disable\nall', command = menuBar.disableall) buttonBox.add('Enable\nall', command = menuBar.enableall) buttonBox.add('Create\nmenu', command = self.add) buttonBox.add('Delete\nmenu', command = self.delete) buttonBox.add('Create\nitem', command = self.additem) buttonBox.add('Delete\nitem', command = self.deleteitem) # Configure the balloon to displays its status messages in the # message bar. self.balloon.configure(statuscommand = self.messageBar.helpmessage) self.testMenuList = [] def _toggleMe(self): print 'Toggle value:', self.toggleVar.get() def add(self): if len(self.testMenuList) == 0: num = 0 else: num = self.testMenuList[-1] num = num + 1 name = 'Menu%d' % num self.testMenuList.append(num) self.menuBar.addmenu(name, 'This is ' + name) def delete(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[0] name = 'Menu%d' % num del self.testMenuList[0] self.menuBar.deletemenu(name) def additem(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[-1] menuName = 'Menu%d' % num menu = self.menuBar.component(menuName) if menu.index('end') is None: label = 'item X' else: label = menu.entrycget('end', 'label') + 'X' self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label, command = PrintOne('Action: ' + menuName + ': ' + label), label = label) def deleteitem(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[-1] menuName = 'Menu%d' % num menu = self.menuBar.component(menuName) if menu.index('end') is None: self.menuBar.bell() else: self.menuBar.deletemenuitems(menuName, 0) class PrintOne: def __init__(self, text): self.text = text def __call__(self): print self.text
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 April 2000
Pmw.MegaArchetype() - abstract base class for all Pmw megawidgets
This class is the basis for all Pmw megawidgets. It provides methods to manage options and component widgets.
This class is normally used as a base class for other classes. If the hullClass argument is specified, such as in the Pmw.MegaWidget and Pmw.MegaToplevel classes, a container widget is created to act as the parent of all other component widgets. Classes derived from these sub classes create other component widgets and options to implement megawidgets that can be used in applications.
If no hullClass argument is given to the constructor, no container widget is created and only the option configuration functionality is available.
A megawidget is generally made up of other widgets packed within the megawidget's containing widget. These sub-widgets are called the components of the megawidget and are given logical names for easy reference. The component mechanism allows the user of a megawidget to gain controlled access to some of the internals of the megawidget, for example to call a method of a component or to set a component's configuration options.
Sub components: If a component is itself a megawidget containing sub-components, then these sub-components can be referred to using the notation component_subcomponent. For example, Pmw.ComboBox has a component named entryfield which is an instance of Pmw.EntryField, which itself has a Tkinter.Entry component named entry. In the context of the combobox, this entry widget can be referred to as entryfield_entry.
Component aliases: Because the sub-component notation may make component names inconveniently long, components and sub-components can be aliased to simpler names. For example, the entryfield_entry sub-component of Pmw.ComboBox is aliased to simply entry. If there is no conflict in component names, sub-component names are usually aliased to the name of the "leaf" component.
Component groups: Similar components of a megawidget can be given a group name, which allows all components of a group to be referenced using the one group name. For example, the two arrow components of Pmw.Counter have a group name of Arrow. Also, megawidgets that can create an unlimited number of similar components, such as Pmw.ButtonBox, create each of these components with the same group name. By convention, group names begin with a capital letter.
A megawidget defines options which allow the megawidget user
to modify the appearance and behaviour of the megawidget.
Using the same technique as Tkinter widgets, the values of
megawidget options may be set in calls to the constructor and
to configure()
and the values may be queried by calls to
cget()
and configure()
. Like Tkinter widgets, megawidget
options are initialised with default values. Also, if the
useTkOptionDb option to Pmw.initialise()
has been set,
then the Tk option database will be queried to get the initial
values. Strings found in the option database are converted
to python objects (integer, float, tuple, dictionary, etc)
using a restricted eval()
call. Anything that is not accepted by
eval()
is treated as a string.
Inherited options: As well as the options defined in a class, a derived class inherits all options of its base classes. The default value of an option defined by a base class may be modified by the derived class.
Initialisation options: Some megawidget options can only be
set in the call to the constructor. These are called
initialisation options. Unlike normal configuration
options, they cannot be set by calling the configure()
method.
Component options: Options of the components of a megawidget
can be referred to using the notation component_option.
Like the megawidget options, component options can be used in
calls to the constructor and to the cget()
and configure()
methods. For example, the state option of the Tkinter.Text
text component of Pmw.ScrolledText may be set by calling
widget.configure(text_state = 'disabled')
Sub-components, component aliases and component groups may also be combined with options. For example, the state option of the entryfield_entry component of Pmw.ComboBox may be set by calling
combobox.configure(entryfield_entry_state = 'normal')
Since it has an alias, it is more convenient to use the equivalent form
combobox.configure(entry_state = 'normal')
Also, the background color of both arrows of Pmw.Counter can be set using the Arrow component group.
counter.configure(Arrow_background = 'aliceblue')
The pyclass component option is a special notation that can be used to specify a non-default python class for a component. This can only be used when the component is being constructed. For a component created during the construction of its parent megawidget, this option must be given to the constructor in the form component_pyclass. For example, to change the python class of the text sub-component of Pmw.TextDialog to a class FontText.Text
dialog = Pmw.TextDialog(text_pyclass = FontText.Text)
For components created after the construction of the parent megawidget, the pyclass option must be passed into the method which constructs the component. For example, to set the python class of a button in Pmw.ButtonBox to a class MyButton:
buttonBox.add('special', pyclass = MyButton)
The new python class of the component must support all methods and options that are used by the megawidget when operating on the component. The exact interface required for each component is not documented. You will have to examine the Pmw source code. However, any class derived from the default class of a component can be used as the new class of the component, as long as all of the original methods and options are still supported. For example, any class derived from Tkinter.Text can be used as the class of the text sub-component of Pmw.TextDialog.
The pyclass component option should not be confused with the class option that some of the Tk widgets support. The class option sets the Tk option database class for the widget and is used by Tk to query the database for the default values of the widget's other options. The name pyclass was chosen so that it did not conflict with any known Tk options.
The constructors of classes derived from this class all accept the same arguments: one positional argument and any number of keyword arguments. The positional argument defaults to None (meaning the root window) and specifies the widget to use as the parent when creating the megawidget's hull component. The keyword arguments define initial values for options. The format for the constructors of derived classes is:
def __init__(self, parent = None, **kw):
defineoptions()
method.
This method is for use by derived classes. It is only used if a
megawidget should conditionally define some options, perhaps
depending on the value of other options. Usually, megawidgets
unconditionally define all their options in the call to
defineoptions()
and do not need to use addoptions()
. This
method must be called after the call to defineoptions()
and
before the call to initialiseoptions()
.
myWidget['font']
. Unlike Tkinter's cget(), which always returns
a string, this method returns the same value and type as used when
the option was set (except where option is a component option
and the component is a Tkinter widget, in which case it returns
the string returned by Tcl/Tk).
If no arguments are given, return a tuple consisting of all
megawidget options and values, each as a 5-element tuple
(name, resourceName, resourceClass, default, value).
This is in the same format as the value returned by the standard
Tkinter configure()
method, except that the resource name is
always the same as the option name and the resource class is the
option name with the first letter capitalised.
If one argument is given, return the 5 element tuple for option.
Otherwise, set the configuration options specified by the keyword arguments. Each key should be in the format described in the Options section.
If this method is called during megawidget construction, any component options supplied to the megawidget constructor which refer to this component (by componentName or componentGroup) are added to the kw dictionary before calling widgetClass. If the dictionary contains a 'pyclass' key, then this item is removed from the dictionary and the value is used instead of widgetClass. For more details see The pyclass component option section.
This method may be called by derived classes during or after megawidget construction. It returns the instance of the class created.
grid()
method, with childCols
and childRows indicating how many rows and columns the label
should span. Note that all other child widgets of the parent
must be added to the parent using the grid()
method. The
createlabel()
method may be called by derived classes during
megawidget construction.
configure()
. The keywords argument should be the keyword
arguments passed in to the constructor of the megawidget. The user
may override the default value of an option by supplying a keyword
argument to the constructor.
If any option created by a base class is also defined by optionDefs, then the derived class's default value will take precedence over the base class's. If the callback field is not None, then this will also override the callback set by the base class.
If callback is Pmw.INITOPT, then the option is an initialisation option.
The dynamicGroups argument contains a list of the groups of the
components created dynamically by this megawidget. If a group is
included in this list, then it not an error if a keyword argument
for the group is given to the constructor or to configure()
,
even when no components with this group have been created.
If defineoptions()
is called, it must be called once in the
megawidget constructor before the call to the constructor of the
base class and there must be a matching call to
initialiseoptions()
at the end of the constructor.
defineoptions()
was also called in the constructor.
The dummy argument is not required, but is retained for
backwards compatibility.
It checks that all keyword arguments given to the constructor have
been used. If not, it raises an error indicating which arguments
were unused. A keyword is defined to be used if, during the
construction of a megawidget, it is defined in a call to
defineoptions()
or addoptions()
(by the megawidget or one of
its base classes), or it references, by name, a component of the
megawidget, or it references, by group, at least one component.
It also calls the configuration callback function for all options
that have a callback.
This method is only effective when called by the constructor of
the leaf class, that is, the class in the class hierarchy which
first called defineoptions()
. For all other classes in the
class hierarchy (base classes), the method returns immediately.
interior()
as the parent of any components or sub-widgets it
creates. Megawidgets which can be further subclassed, such as
Pmw.Dialog, should redefine this method to return the widget in
which subclasses should create children. The overall containing
widget is always available as the hull component.
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 May 1998
Pmw.MegaToplevel() - base class for megawidgets within a toplevel
This class creates a megawidget contained within a toplevel window. It may be used directly to create a toplevel megawidget or it may be used as a base class for more specialised toplevel megawidgets, such as Pmw.Dialog. It creates a Tkinter.Toplevel component, named hull, to act as the container of the megawidget. The window class name for the hull widget is set to the most-specific class name for the megawidget. Derived classes specialise this class by creating other widget components as children of the hull widget.
The megawidget may be used as either a normal toplevel window or
as a modal dialog. Use show()
and withdraw()
for normal use
and activate()
and deactivate()
for modal dialog use. If the
window is deleted by the window manager while being shown
normally, the default behaviour is to destroy the window. If the
window is deleted by the window manager while the window is active
(ie: when used as a modal dialog), the window is deactivated.
Use the userdeletefunc()
and usermodaldeletefunc()
methods to
override these behaviours. Do not call protocol()
to set the
WM_DELETE_WINDOW window manager protocol directly if you want to
use this window as a modal dialog.
The currently active windows form a stack with the most recently activated window at the top of the stack. All mouse and keyboard events are sent to this top window. When it deactivates, the next window in the stack will start to receive events.
activate()
. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is None.
show()
method instead.
If the BLT extension to Tk is present, a busy cursor will be
displayed on other toplevel windows, using Pmw.showbusycursor()
.
The activate()
method does not return until the deactivate()
method is called, when the window is withdrawn, the grab released
and the result returned.
If globalMode is false, the window will grab control of the pointer and keyboard, preventing any events from being delivered to any other toplevel windows within the application. If globalMode is true, the grab will prevent events from being delivered to any other toplevel windows regardless of application. Global grabs should be used sparingly, if at all.
If globalMode is 'nograb', then no grab is performed. If BLT
is present, this will allow mouse and keyboard events to be
received by other windows whose exclude busycursor attribute has
been set to true by a call to Pmw.setbusycursorattributes()
.
Note that if 'nograb' is used and BLT is not present, then all
other windows will receive mouse and keyboard events. This is
because, in plain Tk, there is no way to specify that two windows
(only) receive events. If your application may be used without
BLT, then do not use 'nograb'.
When the window is displayed, it is positioned on the screen according to geometry which may be one of:
geometry = first+100+100
will initially display the window
at position (100,100). Other calls to activate()
will not
change the previous position of the window.
If the BLT Tcl extension library is present, a clock cursor will be displayed until the window is deactivated.
If the activatecommand option is callable, it is called just before the window begins to wait for the result.
If the master option is not None, the window will become a transient window of master, which should be a toplevel window. If master has the special value of 'parent', the master is the toplevel window of the window's parent.
activate()
is currently waiting for a result to be passed to it
by a call to deactivate()
).
activate()
is waiting. It
will withdraw the window, release the grab and cause the
activate()
call to return with the value of result.
If the deactivatecommand option is callable, it is called just
before the deactivate()
method returns.
withdraw()
then
show()
will not move the window, whereas calling withdraw()
then deiconify()
may change the window's position. (This may
depend on the behaviour of the window manager.)
self.destroy
.
self.deactivate
.
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 May 1998
Pmw.MegaWidget() - base class for megawidgets within a frame
This class creates a megawidget contained within a Tkinter.Frame window. The class acts as the base class for megawidgets that are not contained in their own toplevel window, such as Pmw.ButtonBox and Pmw.ComboBox. It creates a Tkinter.Frame component, named hull, to act as the container of the megawidget. The window class name for the hull widget is set to the most-specific class name for the megawidget. Derived classes specialise this class by creating other widget components as children of the hull widget.
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 May 1998
Pmw.MenuBar() - manager megawidget for menu buttons and menus
A menu bar is a container megawidget which manages a number of menu buttons and dropdown menus. There are methods to add menu buttons and menus to the menu bar and for adding menu items to the menus. Menu buttons may be added to the left or right of the megawidget. Each menu button and menu item may have help text to be displayed by a Pmw.Balloon. Each menu and cascaded menu (sub-menu) is referenced by name which is supplied on creation.
To select a menu, simultaneously press the <Alt> key and the accelerator character indicated on a menu button. The arrows keys can then be used to select other menus and menu items. To invoke a menu item, press <Return> or press the accelerator character indicated on the menu item.
Each accelerator character will be assigned automatically unless
traverseSpec is supplied to the addmenu()
, addmenuitem()
or
addcascademenu()
methods. The automatically selected
accelerator character for a menu button (or menu item) is the
first character in the label text that has not already been used
as an accelerator for a menu button (or in the menu containing the
menu item).
If traverseSpec is given, it must be either an integer or a character. If an integer, it specifies the index of the character in the label text to use as the accelerator character. If a character, it specifies the character to use as the accelerator character. The default is 1.
Menu button components are created dynamically by the
addmenu()
method. By default, these are of type
Tkinter.Menubutton and are created with a component group of
Button.
Menu components are created dynamically by the addmenu()
and
addcascademenu()
methods. By default, these are of type
Tkinter.Menu and are created with a component group of Menu.
addmenu()
or addcascademenu()
methods.
A menu item in the parent menu is created (with the
add_cascade()
method of the parent menu) using all keyword
arguments except tearoff.
If the label keyword argument is not given, the label option of the menu item defaults to menuName. If the underline keyword argument is not given (and the hotkeys megawidget option is true) the underline option is determined as described under hotkeys and is used to specify the keyboard accelerator.
The statusHelp argument is used as the help string for the menu
item. This is displayed using the showstatus()
method of the
balloon.
The tearoff keyword argument, if present, is passed to the constructor of the menu. The menu is created as a component named menuName-menu.
addmenu()
or addcascademenu()
methods.
Any keyword arguments present (except tearoff) will be passed to the constructor of the menu button. If the text keyword argument is not given, the text option of the menu button defaults to menuName. If the underline keyword argument is not given (and the hotkeys megawidget option is true) the underline option is determined as described under hotkeys and is used to specify the keyboard accelerator. Each menu button is packed into the menu bar using the given side, which should be either left or right. The menu button is created as a component named menuName-button.
If the balloon option has been defined, balloonHelp and
statusHelp are passed to the balloon as the help strings for the
menu button. See the bind()
method of Pmw.Balloon for how these
strings may be displayed.
The tearoff keyword argument, if present, is passed to the constructor of the menu. The menu is created as a component named menuName-menu.
addcascademenu()
method). Any
keyword arguments present will be passed to the menu when creating
the menu item. See Tkinter.Menu for the valid options for each
item type. In addition, a keyboard accelerator may be
automatically given to the item, as described under hotkeys.
When the mouse is moved over the menu item, the helpString will be displayed by the balloon's statuscommand.
class Demo: def __init__(self, parent): # Create the Balloon. self.balloon = Pmw.Balloon(parent) # Create and pack the MenuBar. menuBar = Pmw.MenuBar(parent, hull_relief = 'raised', hull_borderwidth = 1, balloon = self.balloon) menuBar.pack(fill = 'x') self.menuBar = menuBar # Add some buttons to the MenuBar. menuBar.addmenu('File', 'Close this window or exit') menuBar.addmenuitem('File', 'command', 'Close this window', command = PrintOne('Action: close'), label = 'Close') menuBar.addmenuitem('File', 'separator') menuBar.addmenuitem('File', 'command', 'Exit the application', command = PrintOne('Action: exit'), label = 'Exit') menuBar.addmenu('Edit', 'Cut, copy or paste') menuBar.addmenuitem('Edit', 'command', 'Delete the current selection', command = PrintOne('Action: delete'), label = 'Delete') menuBar.addmenu('Options', 'Set user preferences') menuBar.addmenuitem('Options', 'command', 'Set general preferences', command = PrintOne('Action: general options'), label = 'General...') # Create a checkbutton menu item. self.toggleVar = Tkinter.IntVar() # Initialise the checkbutton to 1: self.toggleVar.set(1) menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off', label = 'Toggle', command = self._toggleMe, variable = self.toggleVar) self._toggleMe() menuBar.addcascademenu('Options', 'Size', 'Set some other preferences', traverseSpec = 'z', tearoff = 1) for size in ('tiny', 'small', 'average', 'big', 'huge'): menuBar.addmenuitem('Size', 'command', 'Set size to ' + size, command = PrintOne('Action: size ' + size), label = size) menuBar.addmenu('Help', 'User manuals', side = 'right') menuBar.addmenuitem('Help', 'command', 'About this application', command = PrintOne('Action: about'), label = 'About...') # Create and pack the main part of the window. self.mainPart = Tkinter.Label(parent, text = 'This is the\nmain part of\nthe window', background = 'black', foreground = 'white', padx = 30, pady = 30) self.mainPart.pack(fill = 'both', expand = 1) # Create and pack the MessageBar. self.messageBar = Pmw.MessageBar(parent, entry_width = 40, entry_relief='groove', labelpos = 'w', label_text = 'Status:') self.messageBar.pack(fill = 'x', padx = 10, pady = 10) self.messageBar.message('state', 'OK') buttonBox = Pmw.ButtonBox(parent) buttonBox.pack(fill = 'x') buttonBox.add('Disable\nall', command = menuBar.disableall) buttonBox.add('Enable\nall', command = menuBar.enableall) buttonBox.add('Create\nmenu', command = self.add) buttonBox.add('Delete\nmenu', command = self.delete) buttonBox.add('Create\nitem', command = self.additem) buttonBox.add('Delete\nitem', command = self.deleteitem) # Configure the balloon to displays its status messages in the # message bar. self.balloon.configure(statuscommand = self.messageBar.helpmessage) self.testMenuList = [] def _toggleMe(self): print 'Toggle value:', self.toggleVar.get() def add(self): if len(self.testMenuList) == 0: num = 0 else: num = self.testMenuList[-1] num = num + 1 name = 'Menu%d' % num self.testMenuList.append(num) self.menuBar.addmenu(name, 'This is ' + name) def delete(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[0] name = 'Menu%d' % num del self.testMenuList[0] self.menuBar.deletemenu(name) def additem(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[-1] menuName = 'Menu%d' % num menu = self.menuBar.component(menuName + '-menu') if menu.index('end') is None: label = 'item X' else: label = menu.entrycget('end', 'label') + 'X' self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label, command = PrintOne('Action: ' + menuName + ': ' + label), label = label) def deleteitem(self): if len(self.testMenuList) == 0: self.menuBar.bell() else: num = self.testMenuList[-1] menuName = 'Menu%d' % num menu = self.menuBar.component(menuName + '-menu') if menu.index('end') is None: self.menuBar.bell() else: self.menuBar.deletemenuitems(menuName, 0) class PrintOne: def __init__(self, text): self.text = text def __call__(self): print self.text
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 22 April 2000
Pmw.MessageBar() - information line for displaying short messages
A message bar contains a single-line message display area. Messages of several different types may displayed. Messages are cleared after a period defined for each message type. Each message type has a priority so that if the application attempts to display more than one message at a time, the message with the highest priority will be displayed. Messages may be accompanied by a number of audible bells.
This megawidget can be used for both interactive help messages (when the mouse enters certain widgets) and also for other general messages.
To perform the help function it can cooperate with the Pmw.Balloon megawidget so that the programmer (or user) can choose either balloon help, message bar help, both or neither.
This megawidget supports a configurable number of message types. The default types include 'state', 'help', 'usererror' and 'systemerror'. The difference between these are the length of time they are displayed, the number of bells that are rung and the priority of the message. For example, the 'help' message type is lower in priority than the 'usererror', so that error messages will always be displayed in preference to help messages regardless of the order the messages are created. The 'state' message type is lowest in priority but has no timeout, so it should contain messages describing the current state of the application, such as Waiting for database connection or 'Waiting for file to be unlocked'. Generally this should be set to the empty string when the application is running normally. By default the help messages (with message type 'help') time out after 5 seconds, so that if the cursor happens to be left over a widget, the application state will be redisplayed after a short time.
If None, a label component is not created. The default is None.
{ 'systemerror' : (5, 10, 2, 1), 'usererror' : (4, 5, 1, 0), 'busy' : (3, 0, 0, 0), 'systemevent' : (2, 5, 0, 0), 'userevent' : (2, 5, 0, 0), 'help' : (1, 5, 0, 0), 'state' : (0, 0, 0, 0), }
message('help', text)
.
class Demo: def __init__(self, parent): # Create and pack the MessageBar. self._messagebar = Pmw.MessageBar(parent, entry_width = 40, entry_relief='groove', labelpos = 'w', label_text = 'Status:') self._messagebar.pack(side = 'bottom', fill = 'x', expand = 1, padx = 10, pady = 10) # Create and pack the ScrolledListBox to change the MessageBar. self.box = Pmw.ScrolledListBox(parent, listbox_selectmode='single', items=('state', 'help', 'userevent', 'systemevent', 'usererror', 'systemerror', 'busy',), label_text='Message type', labelpos='n', selectioncommand=self.selectionCommand) self.box.pack(fill = 'both', expand = 'yes', padx = 10, pady = 10) self._index = 0 self._stateCounter = 0 def selectionCommand(self): sels = self.box.getcurselection() if len(sels) > 0: self._index = self._index + 1 messagetype = sels[0] if messagetype == 'state': self._stateCounter = (self._stateCounter + 1) % 3 text = stateMessages[self._stateCounter] if text != '': text = text + ' (' + messagetype + ')' self._messagebar.message('state', text) else: text = messages[messagetype] text = text + ' (' + messagetype + ')' self._messagebar.message(messagetype, text) if messagetype == 'busy': Pmw.showbusycursor() self.box.after(2000) Pmw.hidebusycursor() self._messagebar.resetmessages('busy') text = 'All files successfully removed' text = text + ' (userevent)' self._messagebar.message('userevent', text) messages = { 'help': 'Save current file', 'userevent': 'Saving file "foo"', 'busy': 'Busy deleting all files from file system ...', 'systemevent': 'File "foo" saved', 'usererror': 'Invalid file name "foo/bar"', 'systemerror': 'Failed to save file: file system full', } stateMessages = { 0: '', 1: 'Database is down', 2: 'Waiting for reply from database', }
Pmw 1.3 - 7 Aug 2007 - Home
Pmw.MessageDialog() - a dialog displaying a text message and an icon
A message dialog is a dialog window which displays a simple message to the user along with one or more buttons to press.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
class Demo: def __init__(self, parent): self.parent = parent # Create dialog 1. self.dialog1 = Pmw.MessageDialog(parent, title = 'Simple message dialog', defaultbutton = 0, message_text = 'A simple message dialog\nwith no callback.') self.dialog1.iconname('Simple message dialog') self.dialog1.withdraw() # Create dialog 2. self.dialog2 = Pmw.MessageDialog(parent, title = 'Bell ringing dialog', message_text = 'This message dialog\nwill ring the bell ' + 'when\nyou click on the buttons.', iconpos = 'w', icon_bitmap = 'error', command = self.execute2, buttons = ('One', 'Two', 'Three', 'Close')) self.dialog2.iconname('Bell ringing dialog') self.dialog2.withdraw() # Create dialog 3. self.dialog3 = Pmw.MessageDialog(parent, title = 'Vertical button dialog', message_text = 'This message dialog\nhas the buttons on the\n' + 'right hand side.', buttonboxpos = 'e', iconpos = 'n', icon_bitmap = 'warning', buttons = ('Goodbye', 'Au revoir', 'Sayonara', 'Close'), defaultbutton = 'Close') self.dialog3.iconname('Vertical button dialog') self.dialog3.withdraw() # Create some buttons to launch the dialogs. w = Tkinter.Button(parent, text = 'Simple dialog', command = lambda self = self: self.dialog1.activate(geometry = 'first+100+100')) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'Bell ringing dialog', command = self.dialog2.activate) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'Vertical buttons', command = self.dialog3.activate) w.pack(padx = 8, pady = 8) w = Tkinter.Button(parent, text = 'On the fly dialog', command = self._createOnTheFly) w.pack(padx = 8, pady = 8) def execute2(self, result): print 'You clicked on', result if result is None: self.dialog2.deactivate(result) elif result == 'Close': self.dialog2.deactivate(result) else: for count in range({'One': 1, 'Two': 2, 'Three': 3}[result]): if count != 0: self.dialog2.after(200) self.dialog2.bell() def _createOnTheFly(self): dialog = Pmw.MessageDialog(self.parent, title = 'On the fly dialog', defaultbutton = 0, buttons = ('OK', 'Apply', 'Cancel', 'Help'), message_text = 'This dialog was created when you clicked ' + 'on the button.') dialog.iconname('Simple message dialog') result = dialog.activate() print 'You selected', result
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.NoteBook() - a set of tabbed pages
A notebook contains a set of tabbed pages. At any one time only one of these pages (the selected page) is visible, with the other pages being hidden "beneath" it. Another page in the notebook may be displayed by clicking on the tab attached to the page. The tabs are displayed along the top edge.
Optionally, the notebook may be displayed without tabs. In this case, another selection widget, such as Pmw.OptionMenu, may be used to select the pages.
This megawidget is derived from Pmw.MegaArchetype (not Pmw.MegaWidget like most other megawidgets), with the hull class being Tkinter.Canvas.
selectpage()
method. The default is 'n'.
Page and tab components are created dynamically by the add()
and insert()
methods. By default, the pages are of type
Tkinter.Frame and are created with a component group of Page
and the tabs are of type Tkinter.Button and are created with a
component group of Tab.
insert()
method
for full details.
index()
method.
If the currently selected page is deleted, then the next page, in index order, is selected. If the end page is deleted, then the previous page is selected.
If forInsert is true, Pmw.END returns the number of pages rather than the index of the last page.
index()
method. If
tabpos is not None, also create a tab as a component named
pageName-tab. Keyword arguments prefixed with page_ or
tab_ are passed to the respective constructors when creating the
page or tab. If the tab_text keyword argument is not given, the
text option of the tab defaults to pageName. If a page is
inserted into an empty notebook, the page is selected. To add a
page to the end of the notebook, use add()
. The method returns
the pageName component widget.
index()
method.
index()
method.
index()
method.
Pmw.Color.changecolor()
.
update_idletasks()
so that the width and height of the pages can
be determined. This may cause the notebook to flash onto the
screen at the default size before resizing to the natural size.
index()
method. If tabpos is None, return None.
class Demo: def __init__(self, parent): # Create and pack the NoteBook. notebook = Pmw.NoteBook(parent) notebook.pack(fill = 'both', expand = 1, padx = 10, pady = 10) # Add the "Appearance" page to the notebook. page = notebook.add('Appearance') notebook.tab('Appearance').focus_set() # Create the "Toolbar" contents of the page. group = Pmw.Group(page, tag_text = 'Toolbar') group.pack(fill = 'both', expand = 1, padx = 10, pady = 10) b1 = Tkinter.Checkbutton(group.interior(), text = 'Show toolbar') b1.grid(row = 0, column = 0) b2 = Tkinter.Checkbutton(group.interior(), text = 'Toolbar tips') b2.grid(row = 0, column = 1) # Create the "Startup" contents of the page. group = Pmw.Group(page, tag_text = 'Startup') group.pack(fill = 'both', expand = 1, padx = 10, pady = 10) home = Pmw.EntryField(group.interior(), labelpos = 'w', label_text = 'Home page location:') home.pack(fill = 'x', padx = 20, pady = 10) # Add two more empty pages. page = notebook.add('Helpers') page = notebook.add('Images') notebook.setnaturalsize()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 30 October 1999
Pmw.OptionMenu() - single item selection megawidget
An option menu consists of a menu button and an associated menu which pops up when the button is pressed. The text displayed in the menu button is updated whenever an item is selected in the menu. The currently selected value can be retrieved from the megawidget.
invoke()
method is called. The function is called with the
currently selected value as its single argument. The default is None.
setitems()
method. The default is None.
If None, a label component is not created. The default is None.
getvalue()
method.
index()
method. The value returned by
command is returned.
If index is not None, set the selected value to index, which
may have any of the forms accepted by the index()
method.
If index is None and the textvariable option of the menubutton component is the empty string, then if the previous selected value is one of the items, then do not change the selection. If the previous selected value is no longer in items, then set the selected value to the first value in items. If items is empty, set the selected value to the empty string.
If index is None and the textvariable option of the menubutton component is not the empty string, then do not set the selected value. This assumes that the variable is already (or will be) set to the desired value.
class Demo: def __init__(self, parent): # Create and pack the OptionMenu megawidgets. # The first one has a textvariable. self.var = Tkinter.StringVar() self.var.set('steamed') self.method_menu = Pmw.OptionMenu(parent, labelpos = 'w', label_text = 'Choose method:', menubutton_textvariable = self.var, items = ['baked', 'steamed', 'stir fried', 'boiled', 'raw'], menubutton_width = 10, ) self.method_menu.pack(anchor = 'w', padx = 10, pady = 10) self.vege_menu = Pmw.OptionMenu (parent, labelpos = 'w', label_text = 'Choose vegetable:', items = ('broccoli', 'peas', 'carrots', 'pumpkin'), menubutton_width = 10, command = self._printOrder, ) self.vege_menu.pack(anchor = 'w', padx = 10, pady = 10) self.direction_menu = Pmw.OptionMenu (parent, labelpos = 'w', label_text = 'Menu direction:', items = ('flush', 'above', 'below', 'left', 'right'), menubutton_width = 10, command = self._changeDirection, ) self.direction_menu.pack(anchor = 'w', padx = 10, pady = 10) menus = (self.method_menu, self.vege_menu, self.direction_menu) Pmw.alignlabels(menus) def _printOrder(self, vege): # Can use 'self.var.get()' instead of 'getcurselection()'. print 'You have chosen %s %s.' % \ (self.method_menu.getcurselection(), vege) def _changeDirection(self, direction): for menu in (self.method_menu, self.vege_menu, self.direction_menu): menu.configure(menubutton_direction = direction)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 23 October 1998
Pmw.PanedWidget() - frame subdivided into several resizable panes
A paned widget is a container megawidget which manages a number of resizable frames, known as panes. Each pane may act as the container for other widgets. The user may interactively resize the panes by dragging a small rectangle (the handle) or the line between the panes (the separator). The panes may be arranged horizontally or vertically. Each pane may have maximum and minimum limits of its size.
Each pane has the following options. These may be set when creating or configuring a pane. The value of each option may be an integer, which specifies a pane size in pixels, or a real number between 0.0 and 1.0, which specifies a pane size proportional to the size of the entire paned widget.
Frame, separator and handle components are created dynamically
by the add()
and insert()
methods. The components are of type
Tkinter.Frame and are created with component groups of
Frame, Separator and Handle respectively.
insert()
with before
set to the current number of panes. The method returns the name
component widget.
If the pane deleted was not the only pane in the paned widget, also delete the separator and handle components named separator-n and handle-n, where n is the number of panes remaining.
add()
.
The new pane is created as a Tkinter.Frame component named name. If this is not the only pane, a separator and handle are also created as components named separator-n and handle-n, where n is one less than the number of panes. The method returns the name component widget.
If oriented vertically, set the height of the paned widget to the sum of the requested heights of all panes and set the width to the maximum requested width of all panes.
class Demo: def __init__(self, parent): # Create a main PanedWidget with a few panes. self.pw = Pmw.PanedWidget(parent, orient='vertical', hull_borderwidth = 1, hull_relief = 'sunken', hull_width=300, hull_height=400) for self.numPanes in range(4): if self.numPanes == 1: name = 'Fixed size' pane = self.pw.add(name, min = .1, max = .1) else: name = 'Pane ' + str(self.numPanes) pane = self.pw.add(name, min = .1, size = .25) label = Tkinter.Label(pane, text = name) label.pack(side = 'left', expand = 1) button = Tkinter.Button(pane, text = 'Delete', command = lambda s=self, n=name: s.deletePane(n)) button.pack(side = 'left', expand = 1) # TODO: add buttons to invoke self.moveOneUp and self.moveOneUp. self.pw.pack(expand = 1, fill='both') buttonBox = Pmw.ButtonBox(parent) buttonBox.pack(fill = 'x') buttonBox.add('Add pane', command = self.addPane) buttonBox.add('Move pane', command = self.move) self.moveSrc = 0 self.moveNewPos = 1 self.moveBack = 0 def move(self): numPanes = len(self.pw.panes()) if numPanes == 0: print 'No panes to move!' return if self.moveSrc >= numPanes: self.moveSrc = numPanes - 1 if self.moveNewPos >= numPanes: self.moveNewPos = numPanes - 1 print 'Moving pane', self.moveSrc, 'to new position', self.moveNewPos self.pw.move(self.moveSrc, self.moveNewPos) self.moveSrc, self.moveNewPos = self.moveNewPos, self.moveSrc if self.moveBack: if self.moveNewPos == numPanes - 1: self.moveNewPos = 0 if self.moveSrc == numPanes - 1: self.moveSrc = 0 else: self.moveSrc = self.moveSrc + 1 else: self.moveNewPos = self.moveNewPos + 1 self.moveBack = not self.moveBack def addPane(self): self.numPanes = self.numPanes + 1 name = 'Pane ' + str(self.numPanes) print 'Adding', name pane = self.pw.add(name, min = .1, size = .25) label = Tkinter.Label(pane, text = name) label.pack(side = 'left', expand = 1) button = Tkinter.Button(pane, text = 'Delete', command = lambda s=self, n=name: s.deletePane(n)) button.pack(side = 'left', expand = 1) self.pw.updatelayout() def deletePane(self, name): print 'Deleting', name self.pw.delete(name) self.pw.updatelayout() def moveOneUp(self, name): self.pw.move(name, name, -1) def moveOneDown(self, name): self.pw.move(name, name, 1)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 14 April 2001
Pmw.PromptDialog() - selection dialog displaying an entry field
The prompt dialog is a dialog window which displays an entry field which can be used to prompt the user for a value.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
component('entry').delete()
.
component('entry').index()
.
component('entry').insert()
.
class Demo: def __init__(self, parent): # Create the dialog to prompt for the password. self.dialog = Pmw.PromptDialog(parent, title = 'Password', label_text = 'Password:', entryfield_labelpos = 'n', entry_show = '*', defaultbutton = 0, buttons = ('OK', 'Cancel'), command = self.execute) self.dialog.withdraw() # Create the confirmation dialog. self.confirm = Pmw.MessageDialog( title = 'Are you sure?', message_text = 'Are you really sure?', defaultbutton = 0, buttons = ('OK', 'Cancel')) self.confirm.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show prompt dialog', command = self.dialog.activate) w.pack(padx = 8, pady = 8) def execute(self, result): if result is None or result == 'Cancel': print 'Password prompt cancelled' self.dialog.deactivate(result) else: result = self.confirm.activate() if result == 'OK': print 'Password entered ' + self.dialog.get() self.dialog.deactivate()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.RadioSelect() - a set of buttons, some of which may be selected
A radio select is a container megawidget which manages a number of buttons. The buttons may be laid out either horizontally or vertically. In single selection mode, only one button may be selected at any one time. In multiple selection mode, several buttons may be selected at the same time and clicking on a selected button will deselect it.
The buttons displayed can be either standard buttons, radio buttons or check buttons. When selected, standard buttons are displayed sunken and radio and check buttons are displayed with the appropriate indicator color and relief.
add()
method. If 'button', the default type is Tkinter.Button. If
'radiobutton', the default type is Tkinter.Radiobutton. If
'checkbutton', the default type is Tkinter.Checkbutton.
If 'radiobutton', single selection mode is automatically set. If 'checkbutton', multiple selection mode is automatically set. The default is 'button'.
invoke()
is called.
In single selection mode, the function is called with a single argument, which is the name of the selected button.
In multiple selection mode, the function is called with the first argument being the name of the button and the second argument being true if the button is now selected or false if it is now deselected. The default is None.
If None, a label component is not created. The default is None.
add()
method. If
there is no label component, then no frame component is
created and the hull component acts as the container. By default, this component is a Tkinter.Frame.
Button components are created dynamically by the add()
method. The default type of the buttons depends on the value
of the buttontype option.
Button components are created with a component group of Button.
index()
method.
getvalue()
method.
In multiple selection mode, return a list of the names of the currently selected buttons.
index()
method. The value returned by command is returned.
In single selection mode, select only the button specified by the string textOrList.
In multiple selection mode, select only the buttons specified by the list textOrList.
class Demo: def __init__(self, parent): # Create and pack a horizontal RadioSelect widget. horiz = Pmw.RadioSelect(parent, labelpos = 'w', command = self.callback, label_text = 'Horizontal', frame_borderwidth = 2, frame_relief = 'ridge' ) horiz.pack(fill = 'x', padx = 10, pady = 10) # Add some buttons to the horizontal RadioSelect. for text in ('Fruit', 'Vegetables', 'Cereals', 'Legumes'): horiz.add(text) horiz.invoke('Cereals') # Create and pack a multiple selection RadioSelect widget. self.multiple = Pmw.RadioSelect(parent, labelpos = 'w', command = self.multcallback, label_text = 'Multiple\nselection', frame_borderwidth = 2, frame_relief = 'ridge', selectmode = 'multiple', ) self.multiple.pack(fill = 'x', padx = 10) # Add some buttons to the multiple selection RadioSelect. for text in ('Apricots', 'Eggplant', 'Rice', 'Lentils'): self.multiple.add(text) self.multiple.invoke('Rice') # Create and pack a vertical RadioSelect widget, with checkbuttons. self.checkbuttons = Pmw.RadioSelect(parent, buttontype = 'checkbutton', orient = 'vertical', labelpos = 'w', command = self.checkbuttoncallback, label_text = 'Vertical,\nusing\ncheckbuttons', hull_borderwidth = 2, hull_relief = 'ridge', ) self.checkbuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10) # Add some buttons to the checkbutton RadioSelect. for text in ('Male', 'Female'): self.checkbuttons.add(text) self.checkbuttons.invoke('Male') self.checkbuttons.invoke('Female') # Create and pack a RadioSelect widget, with radiobuttons. radiobuttons = Pmw.RadioSelect(parent, buttontype = 'radiobutton', orient = 'vertical', labelpos = 'w', command = self.callback, label_text = 'Vertical,\nusing\nradiobuttons', hull_borderwidth = 2, hull_relief = 'ridge', ) radiobuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10) # Add some buttons to the radiobutton RadioSelect. for text in ('Male', 'Female', 'Both', 'Neither'): radiobuttons.add(text) radiobuttons.invoke('Both') def callback(self, tag): # This is called whenever the user clicks on a button # in a single select RadioSelect widget. print 'Button', tag, 'was pressed.' def multcallback(self, tag, state): # This is called whenever the user clicks on a button # in the multiple select RadioSelect widget. if state: action = 'pressed.' else: action = 'released.' print 'Button', tag, 'was', action, \ 'Selection:', self.multiple.getcurselection() def checkbuttoncallback(self, tag, state): # This is called whenever the user clicks on a button # in the checkbutton RadioSelect widget. if state: action = 'pressed.' else: action = 'released.' print 'Button', tag, 'was', action, \ 'Selection:', self.checkbuttons.getcurselection()
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 6 June 2002
Pmw.ScrolledCanvas() - canvas with optional scrollbars
A scrolled canvas consists of a standard canvas widget with optional scrollbars which can be used to scroll the canvas. The scrollbars can be dynamic, which means that a scrollbar will only be displayed if it is necessary, that is, if the scrollregion of the canvas is larger than the canvas.
If None, a label component is not created. The default is None.
Otherwise, the size of the megawidget is determined by the width and height of the canvas component, along with the size and/or existence of the other components, such as the label, the scrollbars and the scrollmargin option. All these affect the overall size of the megawidget. The default is 0.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
component('canvas')
.
class Demo: def __init__(self, parent): # Create the ScrolledCanvas. self.sc = Pmw.ScrolledCanvas(parent, borderframe = 1, labelpos = 'n', label_text = 'ScrolledCanvas', usehullsize = 1, hull_width = 400, hull_height = 300, ) # Create a group widget to contain the scrollmode options. w = Pmw.Group(parent, tag_text='Scroll mode') w.pack(side = 'bottom', padx = 5, pady = 5) hmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Horizontal:', items = ['none', 'static', 'dynamic'], command = self.sethscrollmode, menubutton_width = 8, ) hmode.pack(side = 'left', padx = 5, pady = 5) hmode.invoke('dynamic') vmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Vertical:', items = ['none', 'static', 'dynamic'], command = self.setvscrollmode, menubutton_width = 8, ) vmode.pack(side = 'left', padx = 5, pady = 5) vmode.invoke('dynamic') buttonBox = Pmw.ButtonBox(parent) buttonBox.pack(side = 'bottom') buttonBox.add('yview', text = 'Show\nyview', command = self.showYView) buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown) buttonBox.add('center', text = 'Center', command = self.centerPage) # Pack this last so that the buttons do not get shrunk when # the window is resized. self.sc.pack(padx = 5, pady = 5, fill = 'both', expand = 1) self.sc.component('canvas').bind('<1>', self.addcircle) testEntry = Tkinter.Entry(parent) self.sc.create_line(20, 20, 100, 100) self.sc.create_oval(100, 100, 200, 200, fill = 'green') self.sc.create_text(100, 20, anchor = 'nw', text = 'Click in the canvas\nto draw ovals', font = testEntry.cget('font')) button = Tkinter.Button(self.sc.interior(), text = 'Hello,\nWorld!\nThis\nis\na\nbutton.') self.sc.create_window(200, 200, anchor='nw', window = button) # Set the scroll region of the canvas to include all the items # just created. self.sc.resizescrollregion() self.colours = ('red', 'green', 'blue', 'yellow', 'cyan', 'magenta', 'black', 'white') self.oval_count = 0 self.rand = 12345 def sethscrollmode(self, tag): self.sc.configure(hscrollmode = tag) def setvscrollmode(self, tag): self.sc.configure(vscrollmode = tag) def addcircle(self, event): x = self.sc.canvasx(event.x) y = self.sc.canvasy(event.y) width = 10 + self.random() % 100 height = 10 + self.random() % 100 self.sc.create_oval( x - width, y - height, x + width, y + height, fill = self.colours[self.oval_count]) self.oval_count = (self.oval_count + 1) % len(self.colours) self.sc.resizescrollregion() # Simple random number generator. def random(self): self.rand = (self.rand * 125) % 2796203 return self.rand def showYView(self): print self.sc.yview() def pageDown(self): self.sc.yview('scroll', 1, 'page') def centerPage(self): top, bottom = self.sc.yview() size = bottom - top middle = 0.5 - size / 2 self.sc.yview('moveto', middle)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 20 September 1998
Pmw.ScrolledField() - single line scrollable output field
A scrolled field displays a single line of text. If the text is too wide to display in the megawidget it can be scrolled to the left and right by the user by dragging with the middle mouse button. The text is also selectable by clicking or dragging with the left mouse button.
It can be used instead of a Tkinter.Label widget when displaying text of unknown width such as application status messages.
If None, a label component is not created. The default is None.
class Demo: def __init__(self, parent): # Create and pack the ScrolledField. self._field = Pmw.ScrolledField(parent, entry_width = 30, entry_relief='groove', labelpos = 'n', label_text = 'Scroll the field using the\nmiddle mouse button') self._field.pack(fill = 'x', expand = 1, padx = 10, pady = 10) # Create and pack a button to change the ScrolledField. self._button = Tkinter.Button(parent, text = 'Change field', command = self.execute) self._button.pack(padx = 10, pady = 10) self._index = 0 self.execute() def execute(self): self._field.configure(text = lines[self._index % len(lines)]) self._index = self._index + 1 lines = ( 'Alice was beginning to get very tired of sitting by her sister', 'on the bank, and of having nothing to do: once or twice she had', 'peeped into the book her sister was reading, but it had no', 'pictures or conversations in it, "and what is the use of a book,"', 'thought Alice "without pictures or conversation?"', 'Alice\'s Adventures in Wonderland', 'Lewis Carroll', )
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 23 August 1998
Pmw.ScrolledFrame() - frame with optional scrollbars
A scrolled frame consists of a scrollable interior frame within a clipping frame. The programmer can create other widgets within the interior frame. If the frame becomes larger than the surrounding clipping frame, the user can position the frame using the horizontal and vertical scrollbars.
The scrollbars can be dynamic, which means that a scrollbar will only be displayed if it is necessary. That is, if the frame is smaller than the surrounding clipping frame, the scrollbar will be hidden.
If 'fixed', the interior frame is set to the natural width, as requested by the child widgets of the frame. If 'expand' and the requested width of the interior frame is less than the width of the clipping frame, the interior frame expands to fill the clipping frame. If 'shrink' and the requested width of the interior frame is more than the width of the clipping frame, the interior frame shrinks to the width of the clipping frame. If 'elastic', the width of the interior frame is always set to the width of the clipping frame. The default is 'fixed'.
If None, a label component is not created. The default is None.
Otherwise, the size of the megawidget is determined by the width and height of the clipper component, along with the size and/or existence of the other components, such as the label, the scrollbars and the scrollmargin option. All these affect the overall size of the megawidget. The default is 0.
If 'fixed', the interior frame is set to the natural height, as requested by the child widgets of the frame. If 'expand' and the requested height of the interior frame is less than the height of the clipping frame, the interior frame expands to fill the clipping frame. If 'shrink' and the requested height of the interior frame is more than the height of the clipping frame, the interior frame shrinks to the height of the clipping frame. If 'elastic', the height of the interior frame is always set to the height of the clipping frame. The default is 'fixed'.
place
to position widgets: if a widget (in this case the
frame component) is placed
inside a frame (in this case the
clipper component) and it extends across one of the edges of the
frame, then the widget obscures the border of the frame.
Therefore, if the clipper has no border, then this overlapping
does not occur. By default, this component is a Tkinter.Frame.
component('frame')
.
Usually, this method does not need to be called explicitly, since the position of the frame component and the scrollbars are automatically updated whenever the size of the frame or clipper components change or the user clicks in the scrollbars. However, if horizflex or vertflex is 'expand', the megawidget cannot detect when the requested size of the frame increases to greater than the size of the clipper. Therefore, this method should be called when a new widget is added to the frame (or a widget is increased in size) after the initial megawidget construction.
If mode == 'moveto', adjust the view of the interior so that the fraction value of the total width of the contents is off-screen to the left. The value must be between 0.0 and 1.0.
If mode == 'scroll', adjust the view of the interior left or right by a fixed amount. If what is 'units', move the view in units of horizfraction. If what is pages, move the view in units of the width of the scrolled frame. If value is positive, move to the right, otherwise move to the left.
If mode == 'moveto', adjust the view of the interior so that the fraction value of the total height of the contents is off-screen to the top. The value must be between 0.0 and 1.0.
If mode == 'scroll', adjust the view of the interior up or down by a fixed amount. If what is 'units', move the view in units of vertfraction. If what is pages, move the view in units of the height of the scrolled frame. If value is positive, move to down, otherwise move up.
class Demo: def __init__(self, parent): # Create the ScrolledFrame. self.sf = Pmw.ScrolledFrame(parent, labelpos = 'n', label_text = 'ScrolledFrame', usehullsize = 1, hull_width = 400, hull_height = 220, ) # Create a group widget to contain the flex options. w = Pmw.Group(parent, tag_text='Flex') w.pack(side = 'bottom', padx = 5, pady = 3) hflex = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Horizontal:', items = ['fixed', 'expand', 'shrink', 'elastic'], command = self.sethflex, menubutton_width = 8, ) hflex.pack(side = 'left', padx = 5, pady = 3) hflex.invoke('fixed') vflex = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Vertical:', items = ['fixed', 'expand', 'shrink', 'elastic'], command = self.setvflex, menubutton_width = 8, ) vflex.pack(side = 'left', padx = 5, pady = 3) vflex.invoke('fixed') # Create a group widget to contain the scrollmode options. w = Pmw.Group(parent, tag_text='Scroll mode') w.pack(side = 'bottom', padx = 5, pady = 0) hmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Horizontal:', items = ['none', 'static', 'dynamic'], command = self.sethscrollmode, menubutton_width = 8, ) hmode.pack(side = 'left', padx = 5, pady = 3) hmode.invoke('dynamic') vmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Vertical:', items = ['none', 'static', 'dynamic'], command = self.setvscrollmode, menubutton_width = 8, ) vmode.pack(side = 'left', padx = 5, pady = 3) vmode.invoke('dynamic') self.radio = Pmw.RadioSelect(parent, selectmode = 'multiple', command = self.radioSelected) self.radio.add('center', text = 'Keep centered vertically') self.radio.pack(side = 'bottom') buttonBox = Pmw.ButtonBox(parent) buttonBox.pack(side = 'bottom') buttonBox.add('add', text = 'Add a button', command = self.addButton) buttonBox.add('yview', text = 'Show yview', command = self.showYView) buttonBox.add('scroll', text = 'Page down', command = self.pageDown) # Pack this last so that the buttons do not get shrunk when # the window is resized. self.sf.pack(padx = 5, pady = 3, fill = 'both', expand = 1) self.frame = self.sf.interior() self.row = 0 self.col = 0 for count in range(15): self.addButton() def sethscrollmode(self, tag): self.sf.configure(hscrollmode = tag) def setvscrollmode(self, tag): self.sf.configure(vscrollmode = tag) def sethflex(self, tag): self.sf.configure(horizflex = tag) def setvflex(self, tag): self.sf.configure(vertflex = tag) def addButton(self): button = Tkinter.Button(self.frame, text = '(%d,%d)' % (self.col, self.row)) button.grid(row = self.row, column = self.col, sticky = 'nsew') self.frame.grid_rowconfigure(self.row, weight = 1) self.frame.grid_columnconfigure(self.col, weight = 1) if self.sf.cget('horizflex') == 'expand' or \ self.sf.cget('vertflex') == 'expand': self.sf.reposition() if 'center' in self.radio.getcurselection(): self.sf.update_idletasks() self.centerPage() if self.col == self.row: self.col = 0 self.row = self.row + 1 else: self.col = self.col + 1 def showYView(self): print self.sf.yview() def pageDown(self): self.sf.yview('scroll', 1, 'page') def radioSelected(self, name, state): if state: self.centerPage() def centerPage(self): # Example of how to use the yview() method of Pmw.ScrolledFrame. top, bottom = self.sf.yview() size = bottom - top middle = 0.5 - size / 2 self.sf.yview('moveto', middle)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 February 2001
Pmw.ScrolledListBox() - listbox with optional scrollbars
A scrolled listbox consists of a standard listbox widget with optional scrollbars which can be used to scroll the listbox. The scrollbars can be dynamic, which means that a scrollbar will only be displayed if it is necessary. That is, if the listbox does not contain enough entries, the vertical scrollbar will be automatically hidden and if the entries are not wide enough, the horizontal scrollbar will be automatically hidden.
If None, a label component is not created. The default is None.
Otherwise, the size of the megawidget is determined by the width and height of the listbox component, along with the size and/or existence of the other components, such as the label, the scrollbars and the scrollmargin option. All these affect the overall size of the megawidget. The default is 0.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
setlist(())
.
get()
method of the listbox component,
except that if first is None all list
elements are returned.
getvalue()
method.
If textOrList is a string, select only the list item specified.
Otherwise, select only the list items specified by textOrList, which must be a sequence of strings.
size()
method. Without this explicit forwarding, the size()
method (aliased to grid_size()
) of the hull would be invoked,
which is probably not what the programmer intended.
class Demo: def __init__(self, parent): # Create the ScrolledListBox. self.box = Pmw.ScrolledListBox(parent, items=('Sydney', 'Melbourne', 'Brisbane'), labelpos='nw', label_text='Cities', listbox_height = 6, selectioncommand=self.selectionCommand, dblclickcommand=self.defCmd, usehullsize = 1, hull_width = 200, hull_height = 200, ) # Create a group widget to contain the scrollmode options. w = Pmw.Group(parent, tag_text='Scroll mode') w.pack(side = 'bottom', padx = 5, pady = 5) hmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Horizontal:', items = ['none', 'static', 'dynamic'], command = self.sethscrollmode, menubutton_width = 8, ) hmode.pack(side = 'top', padx = 5, pady = 5) hmode.invoke('dynamic') vmode = Pmw.OptionMenu(w.interior(), labelpos = 'w', label_text = 'Vertical:', items = ['none', 'static', 'dynamic'], command = self.setvscrollmode, menubutton_width = 8, ) vmode.pack(side = 'top', padx = 5, pady = 5) vmode.invoke('dynamic') buttonBox = Pmw.ButtonBox(parent) buttonBox.pack(side = 'bottom') buttonBox.add('yview', text = 'Show\nyview', command = self.showYView) buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown) buttonBox.add('center', text = 'Center', command = self.centerPage) # Pack this last so that the buttons do not get shrunk when # the window is resized. self.box.pack(fill = 'both', expand = 1, padx = 5, pady = 5) # Do this after packing the scrolled list box, so that the # window does not resize as soon as it appears (because # alignlabels has to do an update_idletasks). Pmw.alignlabels((hmode, vmode)) # Add some more entries to the listbox. items = ('Andamooka', 'Coober Pedy', 'Innamincka', 'Oodnadatta') self.box.setlist(items) self.box.insert(2, 'Wagga Wagga', 'Perth', 'London') self.box.insert('end', 'Darwin', 'Auckland', 'New York') index = list(self.box.get(0, 'end')).index('London') self.box.delete(index) self.box.delete(7, 8) self.box.insert('end', 'Bulli', 'Alice Springs', 'Woy Woy') self.box.insert('end', 'Wallumburrawang', 'Willandra Billabong') def sethscrollmode(self, tag): self.box.configure(hscrollmode = tag) def setvscrollmode(self, tag): self.box.configure(vscrollmode = tag) def selectionCommand(self): sels = self.box.getcurselection() if len(sels) == 0: print 'No selection' else: print 'Selection:', sels[0] def defCmd(self): sels = self.box.getcurselection() if len(sels) == 0: print 'No selection for double click' else: print 'Double click:', sels[0] def showYView(self): print self.box.yview() def pageDown(self): self.box.yview('scroll', 1, 'page') def centerPage(self): top, bottom = self.box.yview() size = bottom - top middle = 0.5 - size / 2 self.box.yview('moveto', middle)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 30 August 1998
Pmw.ScrolledText() - text widget with optional scrollbars
A scrolled text consists of a standard text widget with optional scrollbars which can be used to scroll the text. The scrollbars can be dynamic, which means that a scrollbar will only be displayed if it is necessary. That is, if the text widget does not contain enough text (either horizontally or vertically), the scrollbar will be automatically hidden. If it is displayed, the horizontal scrollbar is under the text widget. Similarly, if it is displayed, the vertical scrollbar is to the right of the text widget.
Row and column headers may also be displayed, which scroll in sync with the text widget and may be useful when displaying tabular data. To assist in ensuring that columns line up when using a column header, a fixed width font should be used.
If None, a label component is not created. The default is None.
Otherwise, the size of the megawidget is determined by the width and height of the text component, along with the size and/or existence of the other components, such as the label, the scrollbars and the scrollmargin option. All these affect the overall size of the megawidget. The default is 0.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
get()
method of the text component,
except that if first is None the entire
contents of the text widget are returned.
setvalue()
method.
class Demo: def __init__(self, parent): # Create the ScrolledText with headers. fixedFont = Pmw.logicalfont('Fixed') self.st = Pmw.ScrolledText(parent, # borderframe = 1, labelpos = 'n', label_text='ScrolledText with headers', columnheader = 1, rowheader = 1, rowcolumnheader = 1, usehullsize = 1, hull_width = 400, hull_height = 300, text_wrap='none', text_font = fixedFont, Header_font = fixedFont, Header_foreground = 'blue', rowheader_width = 3, rowcolumnheader_width = 3, text_padx = 4, text_pady = 4, Header_padx = 4, rowheader_pady = 4, ) self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1) funcs = 'atan cos cosh exp log log10 sin sinh sqrt tan tanh' funcs = string.split(funcs) # Create the header for the row headers self.st.component('rowcolumnheader').insert('end', 'x') # Create the column headers headerLine = '' for column in range(len(funcs)): headerLine = headerLine + ('%-7s ' % (funcs[column],)) headerLine = headerLine[:-3] self.st.component('columnheader').insert('0.0', headerLine) self.st.tag_configure('yellow', background = 'yellow') # Create the data rows and the row headers numRows = 50 tagList = [] for row in range(1, numRows): dataLine = '' x = row / 5.0 for column in range(len(funcs)): value = eval('math.' + funcs[column] + '(' + str(x) + ')') data = str(value)[:7] if value < 0: tag1 = '%d.%d' % (row, len(dataLine)) tag2 = '%d.%d' % (row, len(dataLine) + len(data)) tagList.append(tag1) tagList.append(tag2) data = '%-7s' % (data,) dataLine = dataLine + data + ' ' dataLine = dataLine[:-3] header = '%.1f' % (x,) if row < numRows - 1: dataLine = dataLine + '\n' header = header + '\n' self.st.insert('end', dataLine) self.st.component('rowheader').insert('end', header) apply(self.st.tag_add, ('yellow',) + tuple(tagList)) # Prevent users' modifying text and headers self.st.configure( text_state = 'disabled', Header_state = 'disabled', )
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 30 August 1998
Pmw.SelectionDialog() - selection dialog displaying a scrolled list
The selection dialog is a dialog window which displays a scrolled list which can be used to prompt the user for a value.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
size()
method. Without this explicit forwarding, the size()
method (aliased to grid_size()
) of the hull would be invoked,
which is probably not what the programmer intended.
class Demo: def __init__(self, parent): # Create the dialog. self.dialog = Pmw.SelectionDialog(parent, title = 'My SelectionDialog', buttons = ('OK', 'Cancel'), defaultbutton = 'OK', scrolledlist_labelpos = 'n', label_text = 'What do you think of Pmw?', scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross'), command = self.execute) self.dialog.withdraw() # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show selection dialog', command = self.dialog.activate) w.pack(padx = 8, pady = 8) def execute(self, result): sels = self.dialog.getcurselection() if len(sels) == 0: print 'You clicked on', result, '(no selection)' else: print 'You clicked on', result, sels[0] self.dialog.deactivate(result)
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.TextDialog() - a dialog displaying a scrolled text
A text dialog is a dialog window which displays a text message to the user along with one or more buttons to press.
activate()
. The default is None.
If the value of command is not callable, the default behaviour
is to deactivate the window if it is active, or withdraw the
window if it is not active. If it is deactivated, deactivate()
is called with the button name or None as described above. The default is None.
deactivate()
. The default is None.
activate()
method to control whether the
window is made transient during modal dialogs. See the
activate()
method. The default is 'parent'.
(hull_borderwidth = 1, hull_relief = 'raised')
. By default, this component is a Pmw.ButtonBox.
(borderwidth = 1, relief = 'raised')
. By default, this component is a Tkinter.Frame.
bbox()
method. Without this explicit forwarding, the bbox()
method (aliased to grid_bbox()
) of the hull would be invoked,
which is probably not what the programmer intended.
class Demo: def __init__(self, parent): # Create the dialog. dialog = Pmw.TextDialog(parent, scrolledtext_labelpos = 'n', title = 'My TextDialog', defaultbutton = 0, label_text = 'Lawyer jokes') dialog.withdraw() dialog.insert('end', jokes) dialog.configure(text_state = 'disabled') # Create button to launch the dialog. w = Tkinter.Button(parent, text = 'Show text dialog', command = dialog.activate) w.pack(padx = 8, pady = 8) jokes = """ Q: What do you call 5000 dead lawyers at the bottom of the ocean? A: A good start! Q: How can you tell when a lawyer is lying? A: His lips are moving. Q: Why won't sharks attack lawyers? A: Professional courtesy. Q: What do have when a lawyer is buried up to his neck in sand? A: Not enough sand. Q: How do you get a lawyer out of a tree? A: Cut the rope. Q: What is the definition of a shame (as in "that's a shame")? A: When a bus load of lawyers goes off a cliff. Q: What is the definition of a "crying shame"? A: There was an empty seat. Q: What do you get when you cross the Godfather with a lawyer? A: An offer you can't understand. Q. What do lawyers use as contraceptives? A. Their personalities. Q. What's brown and black and looks good on a lawyer? A. A doberman. Q. Why are lawyers buried 12 feet underground? A. Deep down their good. Q. What's the difference between a catfish and a lawyer? A. One's a slimy scum-sucking scavenger, the other is just a fish. """
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 18 May 2002
Pmw.TimeCounter() - counter for display and input of time
A time counter is similar to a regular Pmw.Counter except that the user may increment and decrement the hours, minutes and seconds individually.
invoke()
is called. The default is None.
If None, a label component is not created. The default is None.
getvalue()
method.
class Demo: def __init__(self, parent): self._time = Pmw.TimeCounter(parent, labelpos = 'w', label_text = 'HH:MM:SS', min = '00:00:00', max = '23:59:59') self._time.pack(padx=10, pady=5) button = Tkinter.Button(parent, text = 'Show', command = self.show) button.pack() def show(self): stringVal = self._time.getstring() intVal = self._time.getint() print stringVal + ' (' + str(intVal) + ')'
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 25 May 2002
The value passed to this function is used to construct the text displayed by Pmw.AboutDialog megawidgets created subsequently.
The value passed to this function is used to construct the text displayed by Pmw.AboutDialog megawidgets created subsequently.
The value passed to this function is used to construct the text displayed by Pmw.AboutDialog megawidgets created subsequently.
This function takes a sequence of Pmw.Groups and adjusts the vertical position of the tags in each group so that they all have the height of the tallest tag. This can be used when groups are positioned side-by-side but the natural height of the tags are different because, for example, different fonts with different sizes are used.
Adjust the size of the labels of all the widgets to be equal, so that the body of each widget lines up vertically. This assumes that each widget is a megawidget with a label component in column 0 (ie, the labelpos option was set to 'w', 'wn' or 'ws'). If sticky is set to a combination of 'n', 's', 'e' and 'w', the label will be positioned within its cell accordingly. For example to make labels right justified, set sticky to 'e', 'ne' or 'se'.
Validator function for Pmw.EntryField alphabetic standard validator.
Validator function for Pmw.EntryField alphanumeric standard validator.
Create a wrapper function which displays a busy cursor while
executing command and return the wrapper. When the wrapper
function is called, it first calls Pmw.showbusycursor()
, then
the command (passing any arguments to it), then Pmw.hidebusycursor()
.
The return value of command is returned from the wrapper.
If updateFunction is specified, it is called just before the
call to Pmw.hidebusycursor()
. This is intended to be the
Tkinter update()
method, in which case it will clear any events
that may have occurred while command was executing. An example
of this usage is in the ShowBusy
demonstration: run the
demonstration, click on the entry widget then click on the button
and type some characters while the busy cursor is displayed. No
characters should appear in the entry widget.
Note that the Tkinter update()
method should only be called when
it is known that it can be safely called. One case where a
problem has been found is when a filehandler has been created (on
a non-blocking Oracle database connection), but the filehandler
does not read from the connection. The connection is read (by a
call to the Oracle fetch function ofen) in a loop which also
contains a call to _tkinter.dooneevent()
. If update()
is
called from dooneevent()
and there is data to be read on the
connection, then the filehandler will be called continuously, thus
hanging the application.
Unconditionally remove the event block and busy cursor from all
windows. This undoes all outstanding calls to
Pmw.showbusycursor()
.
Return the Julian Day Number corresponding to the date in text. A Julian Day Number is defined as the number of days since 1 Jan 4713 BC. The date must be specified as three integers separated by the separator character. The integers must be in the order specified by format, which must be a combination of 'd', 'm' and 'y' in any order. These give the order of the day, month and year fields. Examples of valid input are:
'dmy': 31/01/99 31/1/1999 31/1/99 'mdy': 01/31/99 1/31/1999 1/31/99 'ymd': 99/01/31 1999/1/31 99/1/31
If the application's pivot year (default 50) is not None and the year specified in text has only one or two digits, then the year is converted to a four digit year. If it is less than or equal to the pivot year, then it is incremented by the application's century value (default 2000). If it is more than the pivot year then it is incremented by the century value less 100.
The function Pmw.setyearpivot()
can be used to change the
default values for the application's
pivot and century.
Validator function for Pmw.EntryField date standard validator.
This is a general purpose method for displaying background errors to the user. The errors would normally be programming errors and may be caused by errors in Tk callbacks or functions called by other asynchronous events.
If the global error report file (set by calling
Pmw.reporterrorstofile()
) is None, the error message `text` is
written to standard error and also shown in a text window. If
displayerror
is called while previous error messages are being
displayed, the window is raised and the new error is queued. The
queued errors may be viewed by the user or ignored by dismissing
the window.
If the global error report file is not None, `text` is written
to the file. file may be any object with a write()
method,
such as sys.stderr
.
Draw a triangle in the Tkinter.Canvas canvas in the given color. The value of direction may be 'up', 'down', 'left' or 'right' and specifies which direction the arrow should point. The values of baseOffset and edgeOffset specify how far from the edges of the canvas the points of the triangles are as a fraction of the size of the canvas.
Forward methods from one class to another.
This function adds methods to the class fromClass. The names of the methods added are the names of the methods of the class toClass (and its base classes) except those which are already defined by fromClass or are found in the exclude list. Special methods with one or more leading or trailing underscores are also excluded.
When one of the added methods is called, the method of the same name is called on an instance defined by toPart and the return value passed back. If toPart is a string, then it specifies the name of an attribute (not a component) of the fromClass object. The class of this attribute should be toClass. If toPart is not a string, it must be a function taking a fromClass object and returning a toClass object.
This function must be called outside of and after the definition of fromClass.
For example:
class MyClass: def __init__(self): ... self.__target = TargetClass() ... def foo(self): pass def findtarget(self): return self.__target Pmw.forwardmethods(MyClass, TargetClass, '__target', ['dangerous1', 'dangerous2']) # ...or... Pmw.forwardmethods(MyClass, TargetClass, MyClass.findtarget, ['dangerous1', 'dangerous2'])
In both cases, all TargetClass
methods will be forwarded from
MyClass
except for dangerous1
, dangerous2
, special methods like
__str__
, and pre-existing methods like foo
.
Return the window at the top of the grab stack (the window
currently with the grab) or None if the grab stack is empty (no
window has the grab). See also pushgrab()
.
Validator function for Pmw.EntryField hexadecimal standard validator.
Undo one call to Pmw.showbusycursor()
. If there are no
outstanding calls to Pmw.showbusycursor()
, remove the event
block and busy cursor.
If the focus window has not been changed since the corresponding
call to Pmw.showbusycursor()
, or if forceFocusRestore is true,
then the focus is restored to that saved by Pmw.showbusycursor()
.
Initialise Pmw. This performs several functions:
Set up a trap in the Tkinter Toplevel constructor so that a
list of Toplevels can be maintained. A list of all Toplevel
windows needs to be kept so that Pmw.showbusycursor()
can
create busy cursors for them.
Set up a trap in the Tkinter Toplevel and Frame destructors so that Pmw is notified when these widgets are destroyed. This allows Pmw to destroy megawidgets when their hull widget is destroyed and to prune the list of Toplevels.
Modify Tkinter's CallWrapper class to improve the display of
errors which occur in callbacks. If an error occurs, the
new CallWrapper class calls Pmw.clearbusycursor()
to
remove any outstanding busy cursors and calls
Pmw.displayerror()
to display the error.
Using the window given by root, set the WM_DELETE_WINDOW
root window protocol to destroy the root window. This means
that the root window is destroyed if the window manager
deletes it. This is only done if the protocol has not been
set before the call to Pmw.initialise()
. This protocol is
required if there is a modal dialog displayed and the window
manager deletes the root window. Otherwise the application
will not exit, even though there are no windows.
Set the base font size for the application to size. This
is used by Pmw.logicalfont()
as the default point size for
fonts. If this is not given, the default is 14, except
under NT where it is 16. These are reasonable default
sizes for most screens, but for unusually high or low screen
resolutions, an appropriate size should be supplied. Note
that Tk's definition of point size, is somewhat
idiosyncratic.
Set the Tk option database for root according to fontScheme. This changes the default fonts set by Tk. fontScheme may be one of
Pmw.logicalfont()
.
Pmw.logicalfont()
. The default font is bold
Helvetica. The font for entry widgets is Helvetica.
The font for text widgets is Courier The size of all
fonts is the application base font size as described
above.
If root is None, use the Tkinter default root window as the
root, if it has been created, or create a new Tk root window.
The initialise()
method returns this root.
If useTkOptionDb is true, then, when a megawidget is created, the Tk option database will be queried to get the initial values of the options which have not been set in the call to the constructor. The resource name used in the query is the same as the option name and the resource class is the option name with the first letter capitalised. If useTkOptionDb is false, then options for newly created megawidgets will be initialised to default values.
If noBltBusy is true, then Pmw.showbusycursor()
will not
display a busy cursor, even if the BLT busy command is
present.
If disableKeyboardWhileBusy is false, then do not disable
keyboard input while displaying the busy cursor. Normally,
Pmw ignores keyboard input while displaying the busy cursor
by setting the focus for each toplevel window to the Blt
busy window. However, under NT, this may cause the toplevel
windows to be raised. If this is not acceptable, programs
running on NT can request show/hidebusycursor to not ignore
keyboard input by setting disableKeyboardWhileBusy to true
in Pmw.initialise()
.
It is not absolutely necessary to call this function to be able to use Pmw. However, some functionality will be lost. Most importantly, Pmw megawidgets will not be notified when their hull widget is destroyed. This may prevent the megawidget from cleaning up timers which will try to access the widget, hence causing a background error to occur.
If alpha is false, return the list of base versions of Pmw that are currently installed and available for use. If alpha is true, return the list of alpha versions.
Validator function for Pmw.EntryField integer standard validator.
Return the year, month and day of the Julian Day Number jdn. If julian is 1, then the date returned will be in the Julian calendar. If julian is 0, then the date returned will be in the modern calendar. If julian is -1, then which calendar to use will be automatically determined by the value of jdn and papal. If papal is true, then the date set by Pope Gregory XIII's decree (4 October 1582) will be used as the last day to use the Julian calendar. If papal is false, then the last day to use the Julian calendar will be according to British-American usage (2 September 1752).
Return the full name of a Tk font, being a hyphen-separated list
of font properties. The logical name of the font is given by
name and may be one of 'Helvetica', 'Times', 'Fixed',
'Courier' or 'Typewriter'. Pmw uses this name to define the
default values of many of the font properties. The size of the
font is the base font size for the application specified in the
call to Pmw.initialise()
increased or decreased by the value of
sizeIncr. The other properties of the font may be specified by
other named arguments. These may be 'registry', 'foundry',
'family', 'weight', 'slant', 'width', 'style',
'pixel', 'size', 'xres', 'yres', 'spacing',
'avgwidth', 'charset' and 'encoding'.
Return the list of known logical font names that can be given
to Pmw.logicalfont()
.
Validator function for Pmw.EntryField numeric standard validator.
Remove window from the grab stack. If there are not more
windows in the grab stack, release the grab. Otherwise set the
grab and the focus to the next window in the grab stack. See also
pushgrab()
.
The grab functions (pushgrab()
, popgrab()
, releasegrabs()
and grabstacktopwindow()
) are an interface to the Tk grab
command which implements simple pointer and keyboard grabs. When
a grab is set for a particular window, Tk restricts all pointer
events to the grab window and its descendants in Tk's window
hierarchy. The functions are used by the activate()
and
deactivate()
methods to implement modal dialogs.
Pmw maintains a stack of grabbed windows, where the window on the top of the stack is the window currently with the grab. The grab stack allows nested modal dialogs, where one modal dialog can be activated while another modal dialog is activated. When the second dialog is deactivated, the first dialog becomes active again.
Use pushgrab()
to add grabWindow to the grab stack. This
releases the grab by the window currently on top of the stack (if
there is one) and gives the grab and focus to the grabWindow.
If globalMode is true, perform a global grab, otherwise perform
a local grab. The value of deactivateFunction specifies a
function to call (usually grabWindow.deactivate) if popgrab() is
called (usually from a deactivate() method) on a window which is
not at the top of the stack (that is, does not have the grab or
focus). For example, if a modal dialog is deleted by the window
manager or deactivated by a timer. In this case, all dialogs
above and including this one are deactivated, starting at the top
of the stack.
For more information, see the Tk grab manual page.
Validator function for Pmw.EntryField real standard validator.
Release grab and clear the grab stack. This should normally not
be used, use popgrab()
instead. See also pushgrab()
.
Sets the global error report file, which is initially None. See
Pmw.displayerror()
Set the list of alpha versions of Pmw to use for this session to the arguments. When searching for Pmw classes and functions, these alpha versions will be searched, in the order given, before the base version. This must be called before any other Pmw class or function, except functions setting or querying versions.
Use the keyword arguments to set attributes controlling the effect
on window (which must be a Tkinter.Toplevel) of future calls
to Pmw.showbusycursor()
. The attributes are:
Pmw.showbusycursor()
. If a window
is excluded, then the cursor will not be changed to a busy cursor
and events will still be delivered to the window. By default,
windows are affected by calls to Pmw.showbusycursor()
.
Deiconify and raise the toplevel window and set its position and size according to geom. This overcomes some problems with the window flashing under X and correctly positions the window under NT (caused by Tk bugs).
Set the version of Pmw to use for this session to version. If
Pmw.setversion()
is not called, the latest installed version of
Pmw will be used. This must be called before any other Pmw class
or function, except functions setting or querying versions.
Set the pivot year and century for the application's date
processing. These values are used in the datestringtojdn()
method, which is used by Pmw.Counter and Pmw.EntryField
and derived classes. The initial values of pivot and century
are 50 and 2000 repectively. Return a tuple containing the
old values of pivot and century.
Block events to and display a busy cursor over all windows in this
application that are in the state 'normal' or 'iconic', except
those windows whose exclude busycursor attribute has been set to
true by a call to Pmw.setbusycursorattributes()
.
If a window and its contents have just been created,
update_idletasks()
may have to be called before
Pmw.showbusycursor()
so that the window is mapped to the screen.
Windows created or deiconified after calling
Pmw.showbusycursor()
will not be blocked.
To unblock events and remove the busy cursor, use
Pmw.hidebusycursor()
. Nested calls to Pmw.showbusycursor()
may be made. In this case, a matching number of calls to
Pmw.hidebusycursor()
must be made before the event block and
busy cursor are removed.
If the BLT extension to Tk is not present, this function has no
effect other than to save the value of the current focus window,
to be later restored by Pmw.hidebusycursor()
.
Return the real number represented by text. This is similar to
string.atof()
except that the character representing the decimal
point in text is given by separator.
Return the number of seconds corresponding to the time in text. The time must be specified as three integers separated by the separator character and must be in the order hours, minutes and seconds. The first number may be negative, indicating a negative time.
Validator function for Pmw.EntryField time standard validator.
Print debugging trace of calls to, and callbacks from, the Tk interpreter associated with the root window . If root is None, use the Tkinter default root. If on is true, start tracing, otherwise stop tracing. If withStackTrace is true, print a python function call stacktrace after the trace for each call to Tk. If file is None, print to standard error, otherwise print to the file given by file.
For each call to Tk, the Tk command and its options are printed as a python tuple, followed by the return value of the command (if not the empty string). For example:
python executed: button = Tkinter.Button() button.configure(text = 'Hi') tracetk output: CALL TK> 1: ('button', '.3662448') -> '.3662448' CALL TK> 1: ('.3662448', 'configure', '-text', 'Hi')
Some calls from python to Tk (such as update, tkwait, invoke, etc) result in the execution of callbacks from Tk to python. These python callbacks can then recursively call into Tk. When displayed by tracetk(), these recursive calls are indented proportionally to the depth of recursion. The depth is also printed as a leading number. The return value of a call to Tk which generated recursive calls is printed on a separate line at the end of the recursion. For example:
python executed: def callback(): button.configure(text = 'Bye') return 'Got me!' button = Tkinter.Button() button.configure(command = callback) button.invoke()
tracetk output: CALL TK> 1: ('button', '.3587144') -> '.3587144' CALL TK> 1: ('.3587144', 'configure', '-command', '3638368callback') CALL TK> 1: ('.3587144', 'invoke') CALLBACK> 2: callback() CALL TK> 2: ('.3587144', 'configure', '-text', 'Bye') CALL RTN> 1: -> 'Got me!'
Pmw.initialise() must be called before tracetk() so that hooks are put into the Tkinter CallWrapper class to trace callbacks from Tk to python and also to handle recursive calls correctly.
If alpha is false, return the base version of Pmw being used
for this session. If Pmw.setversion()
has not been called, this
will be the latest installed version of Pmw. If alpha is true,
return the list of alpha versions of Pmw being used for this
session, in search order. If Pmw.setalphaversions()
has not
been called, this will be the empty list.
Return the Julian Day Number corresponding to year, month and
day. See jdntoymd()
for description of other arguments)
Pmw 1.3 - 7 Aug 2007 - Home
Pmw.Color - contains functions for handling colors and color schemes
This module is a set of functions for manipulating colors and for modifying the color scheme of an application or a widget. Many of the functions in this module take or return colors. These values may represent colors in the following ways:
'orange'
or '#ffa500'
[1.0, 0.6, 0.0]
.
As used in these functions, the brightness of a color is the perceived grey level of the color as registered by the human eye. For example, even though the colors red, blue and yellow have the same intensity (1.0), they have different brightnesses, 0.299, 0.114 and 0.886 respectively, reflecting the different way these colors appear to the eye. The brightness of a color is a value between 0.0 (dark) and 1.0 (bright).
A color scheme is a set of colors defined for each of the
default color options in the Tk option database. Color schemes
can be used in two ways. Firstly, using Pmw.Color.setscheme()
,
the Tk option database can be set to the values in the color
scheme. This will not have any effect on currently existing
widgets, but any new widgets created after setting the options
will have these colors as their defaults. Secondly, using
Pmw.Color.changecolor()
the color scheme can be used to change
the colors of a widget and all its child widgets.
A color scheme is specified by defining one or more color options
(one of the defined options must be background
). Not all
options need be specified - if any options are not defined, they
are calculated from the other colors. These are the options used
by a color scheme, together with their values if not specified:
background: (must be specified) foreground: black activeForeground: same as foreground insertBackground: same as foreground selectForeground: same as foreground highlightColor: same as foreground disabledForeground: between fg and bg but closer to bg highlightBackground: same as background activeBackground: a little lighter that bg selectBackground: a little darker that bg troughColor: a little darker that bg selectColor: yellow
There are many functions in this module. As well as
Pmw.Color.setscheme()
and Pmw.Color.changecolor()
, some of the
most useful are Pmw.Color.spectrum()
,
Pmw.Color.changebrightness()
and
Pmw.Color.getdefaultpalette()
.
(light, dark)
of color names that can be used as
the light and dark border shadows on a widget where the background
is colorName. This is the same method that Tk uses for shadows
when drawing reliefs on widget borders. The root argument is
only used to query Tk for the rgb values of colorName.
For example to change a widget to have a red color scheme with a white foreground:
Pmw.Color.changecolor(widget, background = 'red3', foreground = 'white')
The colors of widgets created after this call will not be affected.
Note that widget must be a Tk widget or toplevel. To change the color of a Pmw megawidget, use it's hull component. For example:
widget = megawidget.component('hull') Pmw.Color.changecolor(widget, background = 'red3')
To do this, a few widgets are created as children of root, their defaults are queried, and then the widgets are destroyed. (Tk supplies no other way to get widget default values.)
Note that root must be a Tk widget or toplevel. To use a Pmw megawidget as the root, use it's hull component. For example:
root = megawidget.component('hull') Pmw.Color.getdefaultpalette(root)
'#RRGGBB'
suitable for use with Tk color functions.
For example to initialise an application to have a red color scheme with a white foreground:
Pmw.Color.setscheme(root, background = 'red3', foreground = 'white')
This function does not modify the colors of already existing widgets. Use Pmw.Color.changecolor() to do this.
Note that root must be a Tk widget or toplevel. To use the Tk option database of the root window of a Pmw megawidget, use the megawidget's hull component. For example:
root = megawidget.component('hull') Pmw.Color.setscheme(root, background = 'red3')
If returnHues is false, the return values are the names of the colors represented by the hues together with saturation and intensity and corrected by correction.
If returnHues is true, the return values are hues.
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 25 May 2002
Pmw.Blt - interface to some BLT widgets and commands
This module contains function interfaces to the BLT busy
command
as well as the classes Pmw.Blt.Vector, Pmw.Blt.Graph,
Pmw.Blt.Stripchart and Pmw.Blt.Tabset, which are interfaces to
the vector, graph, stripchart and tabset commands of version 2.4
of the BLT extension to Tk. The interfaces are complete except
for Pmw.Blt.Vector where several creation options, methods and
operations have not been implemented.
The blt graph and barchart widgets are essentially the same and so
only the graph widget has been ported. The element_create()
method is not implememted for Pmw.Blt.Graph, so instead:
to create a line element, use the line_create()
method and
to create a bar element, use the bar_create()
method.
To operate on elements, use the element_*()
methods, such as
element_bind()
, element_activate()
, etc.
Note: Full documentation of Pmw.Blt.Graph is available in A User's Guide to Pmw.Blt written by Bjorn Ove Thue and Hans Petter Langtangen. You can also download the full HTML document of the guide for local viewing.
busy forget
command.
busy hold
command.
busy release
command.
vector expr
command.
vector names
command.
Pmw 1.3 -
7 Aug 2007
- Home
Manual page last reviewed: 25 May 2002
Pmw is a toolkit for building high-level compound widgets, or megawidgets, constructed using other widgets as component parts. It promotes consistent look and feel within and between graphical applications, is highly configurable to your needs and is easy to use.
Pmw consists of:
A few base classes, providing a foundation for building megawidgets.
A library of flexible and extensible megawidgets built on the base classes, such as buttonboxes, notebooks, comboboxes, selection widgets, paned widgets, scrolled widgets and dialog windows.
A lazy importer/dynamic loader which is automatically invoked when Pmw is first imported. This gives unified access to all Pmw classes and functions through the Pmw. prefix. It also speeds up module loading time by only importing Pmw sub-modules when needed.
Complete reference documentation, covering all classes and functions including all megawidgets and their options, methods and components. Helpful tutorial material is also available.
A test framework and tests for Pmw megawidgets.
A slick demonstration of the megawidgets.
An interface to the BLT busy, graph and vector commands.
The interface to Pmw megawidgets is similar to basic Tk widgets, so it is easy for developers to include both megawidgets and basic Tk widgets in their graphical applications. In addition, Pmw megawidgets may themselves be extended, using either inheritance or composition.
The use of the Pmw megawidgets replaces common widget combinations with higher level abstractions. This simplifies code, making it more readable and maintainable. The ability to extend Pmw megawidgets enables developers to create new megawidgets based on previous work.
Pmw 1.3 - 7 Aug 2007 - Home
6 January 1997
Release of version 0.1
14 February 1997
Fixed bug in Counter demo for the Macintosh - the maximum size of an integer is smaller than the value returned by time.time().
Fixed bug in Grid demo for Tk 4.2 - grid_bbox returns garbage if it is called without update_idletasks. Also, grid_bbox can only have two arguments in Tk 4.1.
Modified ScrolledText demo so that the text widget contains enough text to require a vertical scrollbar.
Changes to PmwBase:
Prefixed the name of several private variables with a double underscore.
Added symbolic constants for the indexes into an optionInfo list.
Changed names of several methods and variables to be more descriptive.
Removed options() method.
Simplified configuration option data structures. Modified option handling code so that default options are set correctly. If an option is created before initialise() is called then initialise() checks if the option is set by the keyword arguments to initialise(). If not, then it is given the value found in the Tk option database, if a value exists, or the default value. If an option is created after initialise() is called, then it is given the value found in the Tk option database, if a value exists, or the default value.
Replaced usage of self._hull in megawidgets by interior() method.
Added autoclear option to ComboBox.
Fixed bug in ComboBox - fast clicking on the arrow button could result in an attempt to grab a window that was not yet visible.
Added "sys.exc_traceback = None" to the except clauses of all try statements so that references to objects in the stack trace would not be left.
Added takefocus option to PushButton.
Modified the getcurselection() method of ScrolledListBox so that it returns a string if the selection mode is 'single' or 'browse', rather than a tuple with one element. This also affects methods forwarded and derived from ScrolledListBox.
Modified ScrolledListBox so that it avoids unnecessary updates by using idle timer.
Modified ScrolledText to use grid instead of pack.
Added shutdown() function to Tk module to clean up all references to the Tcl interpreter and then delete it.
Fixed bug in Tk module for the Macintosh - update() was being called in initialise() before the Tcl interpreter was created.
14 February 1997
Version 0.1.1 completed and released internally.
6 March 1997
Pmw now uses the standard Tkinter module. The Tk module has been dropped. This means that the Tk module functions such as after, bell, bind, update, etc, are no longer available and the equivalent Tkinter methods should be used.
To restore some of the features of the Tk module, Pmw.initialise() now adds run-time hooks into Tkinter to get notification of when Tk widgets are created and destroyed. It also modifies the CallWrapper class so that errors during callbacks and bindings can be displayed in a window. If Pmw.initialise() is not called, Tkinter is not modified and these features are not available.
If a Tk widget which is acting as the hull of a megawidget is destroyed, then the megawidget is destroyed as well. This can only happen if Pmw.initialise() is called.
Pmw.initialise() now takes the Tkinter root as its argument.
The parent of megawidgets now defaults to the Tk root. Previously, the parent of non-toplevel megawidgets had to be given.
Added PmwBase.tracetk() function to get trace of calls to the Tcl interpreter for debugging.
Added functions to PmwBase to display a busy cursor over the application such as when a modal dialog is displayed or it is blocked doing a long calculation. Uses busy command of the blt extension, if present.
Created a nifty new demo which demonstrates most of the megawidgets in a convenient way.
Added a TextDialog.
Added functionality to handle the grabbing of nested modal dialogs correctly.
Added an activatecommand option to Dialog which allows, for example, the PromptDialog widget to set the keyboard focus when it is activated.
Added tests for Counter and logicalfont.
The ScrolledListBox selectioncommand is no longer given the widget as its first argument.
Several method, function and component names were changed, to be consistent with the coding conventions.
Some of the effects of moving from the Tk module to Tkinter are:
The Tk module used to exit if there were no non-root toplevel windows shown. This is no longer the case and so the application must handle this explicitly, particularly if the root window is withdrawn and the last non-root toplevel is deleted by the window manager.
The Tk module bind functions and methods used to take a noEvent argument to indicate that the Tk event should not be passed to the callback. Tkinter does not support this.
The Tk module initialise() function should be replaced by "root = Tkinter.Tk()" and root should be used instead of "Tk.Root()"
The Tk module quit() function should be replace by "root.destroy()".
Toplevels are not hidden when created. To be consistent, MegaToplevels are not hidden either.
The hide and show methods are not available for Tkinter Toplevels, only MegaToplevels
There is no grid_configure method.
Tkinter.Canvas.coords() returns a python list, not a tuple.
The Tkinter cget and configure widget methods always return strings for the option values. The Tk module used to convert the string to the appropriate python type (such as string, integer, float, Variable, Image, callback function).
Tkinter Menu and Toplevel classes incorrectly have a pack method.
Menu class has no geometry method.
Canvas focus returns '' rather than None.
Text mark_gravity returns '' rather than None.
13 March 1997
Release of version 0.2
17 March 1997
Set default WM_DELETE_WINDOW protocol of Tkinter.Toplevel to destroy() and removed duplicated protocol request from all demos.
Modified text of ShowBusy demo to indicate that busy cursor will only be seen if the BLT extension is present.
Replaced call to update() in PmwLabeledWidget.py with update_idletasks().
Changed name of PromptDialog component from 'entry' to 'entryfield'.
28 April 1997
Version 0.3 released internally
19 August 1997
Many changes made (see the version 0.4 porting guide for more details).
The option propagation mechanism that iwidgets uses is too cumbersome, too hard to understand and, in python, too slow. Developed a new mechanism which is more explicit in naming options. This resulted in most options which were simply propagated to components being removed. Removed keep(), rename() and ignore() methods and "usual" options.
For speed, Pmw no longer queries the Tk option database for
default values for megawidget options. Hence, resource names and
classes do not need to be supplied when creating options and
None is returned for the resource name and class when using
configure()
to query the options. Option "types" no longer
used.
Changed method and component names to be more consistent.
Replaced most uses of pack() with grid().
Megawidgets no longer inherit from LabeledWidget. Instead they call createlabel() to optionally create the label component.
Removed child site from EntryField and rewrote ComboBox accordingly.
Wrote lots more documentation, including automatically generated reference manuals.
Removed PushButton and rewrote ButtonBox to directly create Tkinter.Buttons rather than PushButtons.
Added initialisation options - options which can be set at creation time but not later using configure().
Added aliases for components.
Modified the base classes so that during option configuration, components are configured before configuration called functions are called.
Added several more megawidgets.
Added interface to BLT graph and vector commands.
Created PmwLazy module for lazy importing of Pmw - avoids loading megawidgets which are not used.
Added several more functions for handling color and fonts.
Replaced Counter and EntryField time with timeN and time24
Pmw.initialise() will now create Tkinter.Tk if not given root.
1 September 1997
Release of version 0.4
5 September 1997
Modified the base classes so that the Tk option database resource class of megawidgets can be overridden in the call to the constructor using the hull_class option.
The separators in Pmw.PanedWidget are now active - they can be grabbed, like the handles, and moved around. The cursor now changes to the correct left/right or up/down cursor when over a separator or handle. (Clemens Hintze)
Fixed bug in MessageInfo demo Dismiss button. If it is invoked, an error occurs saying "not enough arguments". (Mark Colclough)
9 September 1997
Added the useTkOptionDb argument to Pmw.initialise which specifies that the initial values of megawidget options are to be set by querying the Tk option database.
When used to query options, the configure() method now returns the resource class and name of the options.
19 September 1997
Changed functions datestringtoint() and timestringtoint() to datestringtojdn() and timestringtoseconds(). Changed return value of datestringtojdn() to be Julian Day Numbers rather than seconds since the epoch.
Fixed a bug in the date Counter due to use of time.timezone, by replacing, when calculating date increments, calls to the time module with calls to datestringtojdn().
Added century pivot year (setyearpivot function) to Counter date datatypes to handle two-digit years.
Added date_dmy4, date_mdy4 and date_y4md datatypes to Counter.
Modified demos All.py and ScrolledText.py so that demos can be called from directories other than the demos directory. (Case Roole and Guido van Rossum)
Changed the default for the Pmw.Balloon label_justify option to left to improve appearance of multi-line balloons. Pmw.Balloon now replaces newlines with spaces in the statusHelp string so that the strings look better when displayed in a Pmw.MessageBar. (Andreas Kostyrka)
Pmw.Blt now calls package require BLT when checking for the existence of Blt, so that it can be loaded if it is not statically linked. (Clemens Hintze, Matthias Klose)
Copied earthris.gif and flagup.bmp files from Tcl distribution to test directory, just in case they have not been installed. (Jonathan Kelly)
Lots of improvements to the documentation and documenting recent changes.
16 October 1997
Modified Pmw.Balloon and Pmw.ComboBox to work around a bug in the Windows95 version of Tk which caused the popup windows to appear in the wrong place. (Fredrik Lundh and Jerome Gay)
Added Pmw.maxfontwidth() function. (Rob Pearson)
24 October 1997
Changed PmwBase._reporterror to handle the class exceptions of python 1.5. (Case Roole)
29 October 1997
Fixed a bug in forwardmethods() function which occurred if the toClass class had a method called type.
7 November 1997
Changed tests/Test._getErrorValue to handle the class exceptions of python 1.5. (Michael McLay)
Changed bug fix in forwardmethods() function to use the
exec execString in d
construct. (Guido van Rossum)
Can now use Pmw.MegaArchetype as a base class just to get option handling; it will not create the hull component unless requested. Moved __str__() and interior() methods from Pmw.MegaToplevel and Pmw.MegaWidget to Pmw.MegaArchetype class.
10 November 1997
Added textclass option to Pmw.ScrolledText and listboxclass option for Pmw.ScrolledListBox to allow embedding of custom widgets.
Added Mitch Chapman's FontText module to the demos
directory
and used it to display the demo source code in color.
Added two notebook megawwidgets, Pmw.NoteBookR and Pmw.NoteBookS. (Case Roole and Joe Saltiel)
Added Pmw.ScrolledCanvas megawidget. (Joe Saltiel)
Added Pmw.TreeBrowse megawidget. (Michael McLay)
Added Pmw.Group megawidget and modified to use grid()
instead
of pack()
. (Case Roole)
Release of version 0.5
12 November 1997
Added pyclass option to components and removed textclass option from Pmw.ScrolledText and listboxclass option from Pmw.ScrolledListBox. (Suggested by Shen Wang)
Added label component to Pmw.ButtonBox megawidget.
Fixed mis-spelling of PmwTreeBrowse in Pmw.py.
Release of version 0.5.1
5 December 1997
The pyclass option can now be None. If so, createcomponent returns None.
Removed tagtype option from Pmw.Group. Can now use the more general tag_pyclass instead.
Added tcl call to load {} Blt
when testing for presence of Blt.
Added julian and papal options to Pmw.ymdtojulian and Pmw.juliantoymd functions and made sure divisions give the same result as C even when operands are negative.
Exported ymdtojulian and juliantoymd functions.
Fixed bug in activate method. Did not prepend TclError with Tkinter.
When the Blt busy hold command is called from showbusycursor, the
bindtags on the busy window are set so that no events cause
callbacks to occur for the toplevel or all bindings. Also, while
a busy window is up, the focus is changed to the busy window so
that no keyboard events are accepted. This fixes a bug where the
Tkinter._nametowidget function could crash with a KeyError: _Busy
if there was a binding on a toplevel window and the mouse
was pressed while the busy cursor was up.
9 December 1997
Fixed bug in Pmw.datestringtojdn() when dealing with century year, such as 2000.
10 December 1997
Added where option to Pmw.ScrolledText.importfile()
. (Graham
Matthews)
16 December 1997
Modified Pmw.RadioSelect and Pmw.ButtonBox so that you can no longer index their buttons using regular expressions. This feature seemed to have little use and caused problems with buttons labeled for example a* and b*. (Problem reported by Rob Hooft)
Added updateFunction option to Pmw.busycallback(). If set, the function will be called just after the command given to Pmw.busycallback(). If the function is set the Tkinter update() method, then this will clear any events that may have occurred while the command was executing.
30 December 1997
Changed ymdtojulian and juliantoymd functions to jdntoymd and ymdtojdn, because the meaning of "julian" is ambiguous, whereas the meaning of "Julian Day Number" is not (maybe).
Converted Pmw to use python 1.5 package mechanism. (Michael McLay and Case Roole)
Removed Pmw.py and PmwLazy files. Added __init__.py, PmwLoader.py and Pmw.def files. (Case Roole)
Applications can now specify at runtime which version of Pmw to use and also which alpha versions, if any. (Case Roole)
Modified Pmw code for the version of Tkinter released with python 1.5.
Release of version 0.6
5 January 1998
Fixed alpha version handling so that alpha versions do not have to supply PmwBase.py and PmwUtils.py. (Case Roole)
Added example alpha directory and documentation. (Case Roole)
7 January 1998
Added selectmode option to Pmw.RadioSelect megawidget. (Roman Sulzhyk)
Added some changes to Pmw.ScrolledCanvas to get around some bugs. (Joe Saltiel)
Release of version 0.6.1
8 January 1998
Added some more changes to Pmw.ScrolledCanvas. (from Joe Saltiel)
12 January 1998
Added Pmw.OptionMenu megawidget. (Roman Sulzhyk)
20 February 1998
Added new Pmw.MenuBar features to delete menus and menuitems, enable and disable menu bar and to add cascade menus. (Rob Pearson)
Added extra arguments to Pmw.Color.spectrum for more control over color choice.
23 February 1998
Added canvasbind() method to Pmw.Balloon.
Fixed demos/All.py so that it will correctly determine which Pmw version to use even if it is in a directory symlinked to the demos directory.
Removed "import DemoVersion" from all demos, except All.py, so that they will work unchanged when copied outside of the Pmw distribution.
Release of version 0.6.2
26 February 1998
Fixed PmwLoader so that it works on Macintoshes. (Jack Jansen)
2 March 1998
Fixed PmwBase and PmwBlt so that an attempt is made to dynamically load Blt before it is used. Previously only attempted to load Blt when calling showbusycursor.
16 March 1998
Added hulldestroyed() method.
Modified displayerror() function to use value given to reporterrorstofile() if it is set.
Fixed bug in Pmw.EntryField which occurred when the command option destroyed the megawidget.
Pmw.EntryField invoke method now passes on the value returned by the command function.
3 April 1998
Added Pmw.ScrolledFrame megawidget. (Joe Saltiel)
Color.rgb2hsi() now uses the built-in min()
and max()
functions.
20 April 1998
Moved time and date functions from PmwCounter.py to new file, PmwTimeFuncs.py.
Added optional separator argument to timestringtoseconds
and
datestringtojdn
functions. These functions are now stricter
when checking if a string is a valid date or time. For example,
it now checks for correct day in month, month in year, etc. These
changes also affect the Pmw.Counter date and time validators.
The datestringtojdn
function now accepts all combinations of
'd', 'm', 'y' as format string.
Moved functions to bottom of file and class to top of file in PmwEntryField.py and PmwCounter.py.
The validation for Pmw.EntryField integer, hexadecimal and real types now use string.atol or string.atof rather than regular expressions.
The validation for the Pmw.EntryField real type accepts a separator argument, for those who prefer a comma instead of a full stop/period/point as the decimal dividing symbol.
The Pmw.EntryField time* and date_* validators have been removed. The functionality can be replaced by using the new time and date validators with min and max fields.
The Pmw.EntryField maxwidth option has been removed. The functionality can be replaced by using the max field of the validator.
Added an extravalidators option to Pmw.EntryField. This allows new types of validation to be added, particularly in classes derived from Pmw.EntryField. It also allows the use of different names for the same validation, by using aliases. Added SpecialEntry demo to show extravalidators option, based on work by Joachim Schmitz.
Fixed a bug in Pmw.EntryField when combining use of value and entry_textvariable options.
The Pmw.EntryField validate option now also accepts a dictionary to handle minimum and maximum validation and to allow the passing of other arguments to the validating functions, such as date, time and number formats and separators.
Fixed bug in Pmw.EntryField where the entry would scroll to the start of the text if an invalid character was typed.
Added checkentry() method to Pmw.EntryField, so that it can be updated if the entry widget is tied to a textvariable.
10 May 1998
The activate() method now takes a geometry option to allow more flexible positioning of the modal dialog.
Fixed rarely occurring bug in deactivate() method if it is called (perhaps from a timer) during the call to wait_visibility() in the activate() method. This bug used to generate an error and the application would not exit properly.
Fixed another rarely occurring bug in deactivate() method if it is called while another application has the grab.
Removed "sys.exc_traceback = None" for except clauses which used to be required by python 1.4 so that references to objects in the stack trace would not be left.
Now uses sys.exc_info() function when displaying exception traceback.
The state option of Pmw.Balloon and the orient option of several others now generate an exception if they have a bad value.
Added a deactivatecommand option to Pmw.MegaToplevel which can be used, for example, to cancel timers.
Made changes to Pmw.Counter so that the entry display continuously changes when arrow key presses are repeated quickly.
Made changes to Pmw.Counter so that the insertion cursor is maintained while counting and the entry scrolls to the end if the value is long.
Pmw.Counter now behaves correctly when counting past the maximum and minimum values of the EntryField.
28 May 1998
Made all Pmw.EntryField standard validators publicly available
as Pmw.numericvalidator
, etc.
Now uses faster string.replace()
instead of regsub.gsub()
when
applicable.
If the balloonHelp argument of the Pmw.Balloon bind methods is None, no balloon is displayed.
Merged the code from the PmwUtils module (forwardmethods()) into PmwBase, since it was always used, was used nowhere else, and made freezing a little more complicated.
Added a short delay between calling Tkinter bell() method (sounds nicer).
The functions datestringtojdn()
and timestringtoseconds()
now
return ValueError on invalid input.
Created bundlepmw.py, to help when freezing in Pmw. Placed in bin directory.
29 May 1998
Fixed rare bug in Pmw.Counter which occured if the counter was unmapped while the mouse button was held down over an arrow button.
Created contrib directory and placed PmwVerticalGuage.py in it. (Chris Wright)
Patched PmwNoteBookR.py. (Siggy Brentrup)
Added addoptions() method to Pmw.MegaArchetype class. (Dieter Maurer)
By default, MenuBar creates hotkeys for menus and menu items for keyboard traversal. Added traversSpec argument to MenuBar add methods. (Michael McLay)
31 May 1998
Cleaned up bbox() methods in Pmw.ScrolledCanvas and Pmw.ScrolledListBox.
The createcomponent() method now disallows the creation of component names containing an underscore, since the query functions would not be able to find them.
2 June 1998
Release of version 0.7
3 June 1998
Moved Pmw.TreeBrowse megawidget to contrib directory.
17 June 1998
Added PmwFullTimeCounter.py to contrib directory (Daniel Michelson)
1 July 1998
Changed mispelt file PmwVerticalGuage.py to PmwVerticalGauge.py in contrib directory.
7 July 1998
Fixed bug in Pmw.Counter real datatype. Sometimes incorrectly counted negative decimal fractions. (Reported by David Ascher)
12 July 1998
The format argument of Pmw.datestringtojdn() now defaults to 'ymd'.
Removed Tkinter_test.py from tests since it does not test any Pmw functionality (only Tkinter) and it fails under MS-Windows 95.
23 August 1998
Changed several exception types to be more consistent.
Made the interface to Pmw.Blt.Vector more like the builtin python list type.
It is no longer an error to call Pmw.setversion() or Pmw.setalphaversions() after initialisation, as long as the requested version matches the actual version.
Fixed Pmw.NoteBookR so that it behaves better when the highlightthickness is changed.
The setyearpivot() function now returns a tuple containing the old values of pivot and century.
Added PmwFileDialog.py to contrib directory (Rob Hooft)
Modified demos so that full tracebacks are displayed if an error occurs when importing a module.
Removed justify() method from Pmw.ScrolledListBox, since it is just a wrapper around the xview and yview methods of the listbox. Also, it was not a permanent justification, as the name implied.
20 September 1998
Changed implementation of Pmw.ScrolledCanvas.
Added borderframe option to Pmw.ScrolledText and Pmw.ScrolledCanvas.
18 October 1998
Major overhaul of all scrolled widgets. Modified all to use similar structure, given the peculiarities of each. Fixed several subtle bugs.
Pmw.ScrolledFrame: now uses a frame positioned within a clipping frame using the place geometry manager. Added borderframe, horizflex, horizfraction, usehullsize, vertflex, vertfraction options. Added reposition() method. Removed getFrame() method; use interior() method instead.
Pmw.ScrolledListBox: added usehullsize option.
Pmw.ScrolledText: added borderframe and usehullsize options.
Pmw.ScrolledCanvas: simplified widget structure. Added borderframe, canvasmargin, scrollmargin and usehullsize options. Added label.
Modified Pmw.OptionMenu to use standard widgets rather than call tcl procedure. Added initialitem option. Now handles menubutton_textvariable component option correctly.
1 November 1998
Documented more Pmw functions and Pmw.ComboBox.
15 November 1998
Fixed some bugs, cleaned up code and wrote documentation for Pmw.Group. Removed ringpadx and ringpady options, since this functionality is more generally available by padding the megawidget itself and by padding the children of the megawidget. Modified Pmw.aligngrouptags so that it takes into account the borderwidth and highlightthickness of the ring and so that it works when there is no tag widget. Added tagindent option.
18 November 1998
Renamed canvasbind() and canvasunbind() methods of Pmw.Balloon to tagbind() and tagunbind() and modified so that they work with both Tkinter.Canvas items and Tkinter.Text tagged items.
19 November 1998
Added havebltbusy() method to Pmw.Blt. (Robin Becker)
21 November 1998
Modified contrib/PmwFileDialog.py so that when a file is selected with the mouse, the highlight (in the file list) persists and the file list does not scroll to the top. (Rob Hooft)
Modified Pmw.Balloon so that it can be bound to a tag associated with several Canvas or Text items. (Magnus Kessler)
21 November 1998
Cleaned up appearance and colors of Pmw.NoteBookR tabs. (Georg Mischler)
Added buttontype option to Pmw.RadioSelect to support radiobuttons and checkbuttons. (Georg Mischler)
23 November 1998
Updated usage of bind_class(tag)
due to change in return value
in Tkinter module in python 1.5.2. (Magnus Kessler, Fredrik Lundh)
The default time displayed in Pmw.TimeCounter is now the current local time, not GMT as before.
The times displayed in the Counter demonstration are now the current local time, not GMT as before.
7 December 1998
Modified Pmw.ComboBox to take advantage of the fix to the Tkinter
bind()
method callback handling of Event.widget
in python
1.5.2. It works even if the selectioncommand destroys the
combobox. For simple comboboxes, the invoke() method now returns
the return value of the selectioncommand.
Modified Pmw.EntryField to take advantage of the fix to the
Tkinter bind()
method callback handling of Event.widget
in
python 1.5.2. It works even if a user-supplied callback
(command, invalidcommand, validator or stringtovalue)
destroys the entryfield. Cleans up correctly when destroyed. The
invoke() method now returns the return value of the command.
The invoke() method of Pmw.TimeCounter now returns the return value of the command.
Modified Pmw.ButtonBox to use the new (in Tk8.0) default option of the Tkinter Button widget instead of a separate frame. Changed default padding to be more compact. Removed "ring" frame component and "ringborderwidth", "ringpadx" and "ringpady" options. (Georg Mischler)
Changed 'pmw1' fontScheme to set default fonts only when running under posix, since the default fonts on other systems look better.
10 December 1998
Release of version 0.8
20 January 1999
Added master option to Pmw.MegaToplevel and removed master argument from the activate method.
Replaced rand module in demos with a simple random number generator (since rand is not built-in on all versions of python).
22 February 1999
Modified __init__.py
so that it only accepts directories whose
names begin with Pmw_M_N and which have a /lib/PmwLoader.py/
file.
13 May 1999
Changed Pmw.ScrolledCanvas, Pmw.ScrolledText and Pmw.ScrolledListBox to speed up scrolling if the scrollmodes are not both dynamic.
Changed busy cursor and activate/deactivate code so that it works correctly under fast mouse clicking or fast keyboarding (using accelerators). Also fixed so that grab is correctly restored after a Pmw.ComboBox popup list is unmapped inside a modal dialog. (Clemens Hintze)
Several dialogs now give focus to one of their components (listbox or entry widget) when activated. (Clemens Hintze)
Fixed Pmw.ComboBox so that it unposts popup if the combobox is unmapped and returns grab and focus correctly if destroyed.
Improved tracetk() output to be more readable. Also displays nested calls to the Tk mainloop better and shows callbacks from tcl to python.
Upgraded Blt support to blt2.4i. Graph widget is not backwards compatible with blt2.1.
19 May 1999
Fixed bug in Pmw.Balloon in placement of balloons over canvas items when the canvas was scrolled. (Tessa Lau)
20 May 1999
Added new Tk event types (new in Tk 8.0 and 8.0.5) to PmwBase error display method. Also added check for unknown event types to safeguard against future changes. (Magnus Kessler)
Added exclude argument to showbusycursor()
. (Rob Hooft)
1 June 1999
Added wrappers for Blt Stripchart and Tabset widgets. (Nick Belshaw)
Changed createcomponent() so that arguments to the constructor of the component can now be specified as either multiple trailing arguments to createcomponent() or as a single tuple argument.
7 June 1999
Added call to update_idletasks() in Pmw.ScrolledCanvas, Pmw.ScrolledFrame, Pmw.ScrolledText and Pmw.ScrolledListBox to avoid endless mapping/unmapping of two dynamic scrollbars when the window is first mapped and only one scrollbar is needed. (Reported by Mark C Favas, solution suggested by Dieter Maurer.)
10 June 1999
Fixed bug in bundlepmw.py when called with -noblt option. (Reported by Kevin O'Connor)
Pmw.ComboBox now unposts the dropdown listbox before the selection callback is invoked, to avoid problems when the callback takes a long time to run. (Reported by Randall Hopper)
11 June 1999
Release of version 0.8.1
29 June 1999
PmwMessageBar.message() now replaces newlines with spaces before displaying message. Also applies to helpmessage().
2 July 1999
Improved toplevel window positioning under NT, and stopped most of the ugly flashing.
5 July 1999
The pmw1 fontScheme is now supported under NT, as is the size
option to Pmw.initialise()
.
6 July 1999
Changed the names of positional arguments in the following methods, so that they have less chance of conflicting with keyword arguments: MegaArchetype.createcomponent(), ButtonBox.insert(), ButtonBox.add(), MenuBar.addcascademenu(), MenuBar.addmenuitem() and RadioSelect.add().
9 July 1999
Added images and example code to the megawidget reference manuals. (Suggested by Joerg Henrichs)
Fixed showbusycursor() under NT. It now calls update() instead of update_idletasks() to force display of cursor. (Solution suggested by George Howlett)
Improved display of arrows in ComboBox, Counter and TimeCounter.
16 July 1999
Removed Pmw.maxfontwidth() function, since better functionality is now supplied by the Tk "font measure" command.
Removed Pmw.fontexists() function, since in Tk8.0 all fonts exist.
28 July 1999
Fixed bug in date counter with separator other than '/' and time counter with separator other than ':'. (David M. Cooke, Alan Robinson)
Under NT, the font named 'fixed' is not fixed width, so added alias from 'Fixed' to 'Courier'.
Changed the bind()
and tagbind()
methods of Pmw.Balloon to
remove a potential memory leak. The methods now store the
funcids of the callback functions, so that if the same widget or
tag is bound twice, the balloon can remove the old bindings.
(Peter Stoehr)
Changed NoteBookR so that lowercmd, creatcmd and raisecmd are called in that order when a page is selected. Also fixed bug which always raised page 0 when notebook is resized. (Scott Evans, Charles Choi)
1 August 1999
Added dynamicGroups argument to defineoptions()
method and
modified ButtonBox, MenuBar, PanedWidget, RadioSelect to register
their dynamic groups.
Pmw.initialise()
can now be called multiple times, with
different root arguments, but only sequentially. Pmw does not
(yet) support multiple simultaneous interpreters. Modified
Pmw.EntryField so that it recreates class bindings when
Tkinter.root changes.
4 August 1999
Added relmouse option to Pmw.Balloon. Fixed Pmw.Balloon so that the balloon is not displayed off-screen. (Tessa Lau)
16 August 1999
Added disableKeyboardWhileBusy option to initialise(). To ignore keyboard input while displaying the busy cursor, Pmw sets the focus for each toplevel window to the Blt busy window. However, under NT, this causes each window to be raised. If this is not acceptable, programs running on NT can request show/hidebusycursor not to ignore keyboard input.
25 August 1999
Added Pmw.Blt.busy_forget() and used it in Pmw.hidebusycursor() when running under NT. There is a bug in the Blt busy release command under NT where it sometimes fails to display the busy cursor. Using busy forget avoids the problem.
27 September 1999
Added busyCursorName option to Pmw.initialise() and added cursor argument to Pmw.Blt.busy_hold(). (Mark Favas)
20 October 1999
Replaced Pmw.NoteBookR and Pmw.NoteBookS with completely rewritten Pmw.NoteBook.
Renamed Pmw.OptionMenu.get() to Pmw.OptionMenu.getcurselection() and Pmw.PanedWidget.remove() to Pmw.PanedWidget.delete(), to be more consistent with other megawidgets.
The index() method of several megawidgets now use Pmw.END, Pmw.SELECT and Pmw.DEFAULT instead of strings, since these may conflict with component names.
Pmw.OptionMenu.index() now uses Pmw.SELECT to return index of the currently selected menu item, rather than None.
Added destroy() method to Pmw.MegaArchetype to handle cleaning up of _hullToMegaWidget mapping.
Removed exclude argument from Pmw.showbusycursor() and added Pmw.excludefrombusycursor() function instead. (Rob Hooft)
Fixed several bugs for Windows NT.
Added Pmw.ButtonBox.button() and Pmw.RadioSelect.button().
Added Pmw.Color.bordercolors().
21 October 1999
Release of version 0.8.3. (Version 0.8.2 was not released.)
30 October 1999
Added arrownavigation option and previouspage() and nextpage() methods to Pmw.NoteBook. (Peter Funk)
Renamed the setnaturalpagesize()
method of Pmw.NoteBook to
setnaturalsize()
to be consistent with Pmw.PanedWidget.
Changed Pmw.excludefrombusycursor() to Pmw.setbusycursorattributes(). Removed busyCursorName option from Pmw.initialise() and added cursorName attribute to Pmw.setbusycursorattributes().
Added documentation source and build scripts to ftp site.
6 November 1999
Fixed memory leaks when destroying megawidgets. Added automatic check for memory leak to test script used by all tests. Pmw.initialise() now uses a hook into Tkinter.Widget.destroy rather than Tkinter.Frame.destroy to handle the case of Pmw.NoteBook being destroyed (since the notebook hull is a canvas and not a frame). Window manager delete protocol callbacks are now cleaned up. Pmw.ScrolledListBox event bindings now do not leak. (Reported by Jeff Weeks)
Removed key bindings for Pmw.ScrolledListBox except space and return keys.
20 November 1999
Fixed bug in Pmw.Balloon when the canvas or text item that triggered the balloon is deleted before the balloon is displayed by the initwait timer. (Magnus Kessler)
Added 'nograb' to globalMode option of activate()
method. (Rob Hooft)
Added __setitem__ method to Pmw.MegaArchetype, so that megawidget
options can be now set using megawidget['option'] = value
style.
(Oliver Gathmann)
27 December 1999
Converted from regex
module to re
module, since regex
is not
implemented for Jpython. (Finn Bock)
30 December 1999
Added clear()
method to Pmw.ScrolledListBox (suggested by Carson
Fenimore).
15 March 2000
Fixed problem in PmwBase when deleting windows that were created before Pmw was initialised (such as splash windows displayed while the application is coming up). (Mark Favas)
Added splash window to Pmw demo. (Mark Favas)
30 April 2000
Added Pmw.MainMenuBar megawidget, which uses the menubar feature of Tk to provide platform specific menu bars.
Fixed Pmw.Counter and several other megawidgets so that certain hull constructor keywords, such as hull_relief and hull_borderwidth, are not overriden in the constructor.
Thanks to Peter Cashin for his help on how to unpack gzipped tar files on Microsoft Windows operating systems.
Added Pmw.HistoryText megawidget. This can be used as the basis of an interactive text-based database query gui. It maintains a history of each query and allows editing of prior queries.
Added references to the Pmw.Blt.Graph documentation by Bjorn Ove Thue and Hans Petter Langtangen.
Searched for and fixed memory leaks. There are no more known memory leaks.
For commands created by bind
: these are cleaned up by Tkinter
when the widget is destroyed. Pmw.Balloon, which repeatedly
binds to the same widget (or item, using tag_bind
), has been
fixed by passing the old command into the call to unbind
or
tag_unbind
which is cleaned up by Tkinter.
For commands created by class_bind
: most class bindings are
only created once (per Tk interpreter) and so do not need to be
cleaned up. The exception is adding and deleting menus in
Pmw.MenuBar. This has now been fixed to clean up class_bind
commands when deleting menus.
Callbacks given to command, xscrollcommand, yscrollcommand, etc
options are cleaned up by Tkinter when the widget is destroyed.
Cases where Pmw repeatedly sets such options have now been fixed
to clean up the old command before configuring the new one.
These are in setitems
in Pmw.OptionMenu and when modifying the
scrollcommand options in several of the scrolled widgets.
Pmw now cleans up calbacks it registers with the WM_DELETE_WINDOW protocol for toplevel windows.
Added ManualTests.py to tests directory for tests which need to be run by hand.
12 May 2000
Release of version 0.8.4.
17 May 2000
Modified Pmw.Counter to deal with the presence (python up to 1.5.2) or absence (python 1.6 and after) of an L at the end of the ascii representation of a long. (Mark Favas)
Fixed bug in Pmw.ScrolledFrame when given invalid flex options. (Stephen D Evans)
23 January 2001
Moved Pmw home from www.dscpl.com.au to pmw.sourceforge.net.
Added pmw2 font scheme, since the font used for balloon text with pmw1 is too small on Linux.
Removed syntax coloring from code window in demos. It did not look good and the pattern matching was not always correct.
Changed font size used for demos to 12 for Unix, since 14 looked too big under Linux.
Minor fixes to tests for Tk 8.3.
8 February 2001
Release of version 0.8.5
18 February 2001
Added xview() and yview() methods to Pmw.ScrolledFrame (suggested by Christer Fernstrom).
Made tktrace output more readable.
Added noBltBusy option to Pmw.initialise.
Fixed bug where combobox dropdown list could stay mapped after entryfield was unmapped.
Improved scrolling in scrolled frame.
21 February 2001
Fixed tests for recent version of Blt graph (reported by Venkatesh Prasad Ranganath).
Fixed problem in Pmw.ScrolledFrame in python 1.5 - string.atof does not accept a number as argument, but it does in python 2.0.
24 February 2001
Modified Pmw.OptionMenu documentation to specify that list elements must be strings (problem reported by Guy Middleton).
Fixed bug in Pmw.OptionMenu where the wrong item was displayed when an integer item in the menu was selected with the mouse (even though items should be strings).
Added work around to Pmw.ScrolledFrame for bug in Tk when retrieving value from scrollbars soon after creation.
27 February 2001
Added HistoryText and MainMenuBar to bin/bundlepmw.py - accidently left out.
13 April 2001
Changed default foreground (text) of Pmw.Balloown to black. (Eric Pettersen)
Added default fontScheme to Pmw.initialise().
Added -fontscheme and -fontsize options to demo.
Added updatelayout() to Pmw.PanedWidget for use when dynamically adding and deleting panes. (G Cash)
Added move() to Pmw.PanedWidget to move panes. (G Cash)
20 April 2001
Fixed bug in Pmw.Balloon where the balloon would reappear if the mouse button was pressed down inside a widget and then, while the mouse button was being held down, the mouse was moved outside of the widget and then moved back over the widget.
Fixed bug in Pmw.Balloon when destroying widgets while the balloon was up. In this case, the balloon remained displayed even though the widget had been destroyed. (Reported by Stefan Schone.)
Fixed bug in Pmw.Balloon when destroying widgets during the initwait period. In this case, an error occurred when the initwait timer went off when it tried to access the destroyed widget. (Reported by Stefan Schone.)
Fixed Pmw.Balloon so that unbinding withdraws the balloon if the widget being unbound is the widget which triggered the balloon.
Modified Pmw.Balloon so that when deleting a canvas or text item,
tagunbind()
can be called which will withdraw the balloon if it
was triggered by the item. Unfortunately this can not be
automated as for widgets since Tk does not support <Destroy>
bindings on canvas or text items, so there is no way that
Pmw.Balloon can be notified of the deletion of an item.
Updated tests for python 2.1.
21 May 2001
Pmw.OptionMenu now defaults to taking focus (on <Tab> key).
15 May 2002
Fixed bug in Pmw.Graph.element_closest() where element names should follow option arguments. (Val Shkolnikov)
5 June 2002
Added command option to Pmw.TimeCounter.
Finished all documentation.
Fixed bug in documentation creation script which, since python 2.0, printed default values of real options (such as the horizfraction option of Pmw.ScrolledFrame) with too many digits (such as 0.050000000000000003).
Fixed bug in setgeometryanddeiconify for cygwin python (John Williams).
4 July 2002
Added master option to MegaToplevel.show()
Improved MegaToplevel.show()
so that tkraise is not called
unecessarily, thus avoiding 2 second delay under certain window
managers (such as sawfish) in most circumstances. There are still
problems with the Enlightenment window manager.
18 August 2002
Added columnheader, rowheader and rowcolumnheader components to Pmw.ScrolledText. (Rob Pearson)
Added getvalue()
and setvalue()
methods to several megawidgets
as a consistent way to set and get the user-modifiable state.
(Cimarron Taylor)
Made sub-classing simpler when no new options or components are being created. A sub-class of a Pmw megawidget does not need to have an __init__() method. If it does, it does not need to call defineoptions(). Also, initialiseoptions() no longer requires an argument (for backwards compatibility it may take an argument, but it is ignored).
24 August 2002
Release of version 1.0
26 August 2002
Minor fixes.
Release of version 1.1
4 September 2002
Added collapse, expand and toggle methods and collapsedsize option to Pmw.Group. (Rob Pearson)
5 September 2002
Added sticky option to several megawidgets.
18 September 2002
Added appendtext method to Pmw.ScrolledText. (Graham Dumpleton)
26 September 2002
Modified Pmw.ScrolledListBox to call dblclickcommand on <Double-ButtonRelease-1> rather than <Double-ButtonPress-1> which caused problems if the double button press unmapped the ScrolledListBox. In this case, the second button release of the double click is given to another widget. (Eric Pettersen)
14 June 2003
Changes for python 2.3 and Tcl/Tk 8.4.2:
Wrapped calls to cget() for Tkinter widgets in a call to str(). Before python 2.3 cget() always returned a string. Under python 2.3, Tkinter sometimes returns non-string values (such as int, or Tcl_Obj). Made similar change when using configure() to retrieve values. Fixed tests to handle integer and Tcl_Obj return value from cget(). (Charles Doutriaux)
Fixed uses of col
field of grid command. Must use full
column
under Tcl/Tk 8.4.2.
Fixed PmwEntryField.py, PmwMessageBar.py, PmwScrolledField.py so that the text is not greyed out under Tcl/Tk 8.4.2. This was caused by a change in behaviour of the 'disabled' state and the Tk entry widget. Now use new 'readonly' state for Tcl/Tk 8.4.2.
Test script now ignores Blt test for Tcl/Tk 8.4.2, since it causes Blt 2.4z to core dump. Blt needs to be fixed.
Changed Dialog test to work around problem caused by Tk 8.4.2 enforcing transient behaviour of windows. When activate() is called on a dialog whose parent is withdrawn, then the dialog window is made transient. Under old versions of Tk, the transient dialog was displayed, but under 8.4.2 the dialog is not displayed. Work around is to deiconify parent of dialog.
5 August 2003
Release of version 1.2
Changes for python 2.4 and 2.5:
5 August 2007
In module PmwBase.py: An explicit cast is now required from exception to string (str) .
Release of version 1.3
Pmw 1.3 - 7 Aug 2007 - Home
This is a long list of suggestions and enhancements for Pmw. If you are interested in doing any of these, please let the Pmw maintainer (gregm@iname.com) know.
New Pmw megawidgets
Multicolumn listbox.
Useful features - smooth scrolling, embedded images, different fonts and colours, text correctly masked when it is longer than its column width, interactive resizing of columns.
Probably should be implemented as canvas widget rather than by using multiple frames or multiple listboxes. There would be a lot of work needed to position all the elements - you can't just pack or grid them.
File dialog.
Main window class (App class), with menu bar, information line with status boxes and an about box. (See iwidgets' mainwindow class for example.) This should handle creation of multiple main windows, recycling of unused main windows and should exit if last open main window is closed.
Searchable text megawidget.
Tree browser.
Check out Doug Hellmann's contributed megawidgets at <http://www.mindspring.com/~doughellmann/Projects/PmwContribD> or <http://members.home.net/doughellmann/PmwContribD/> and integrate into Pmw.
Changes to current megawidgets
MegaToplevel
Modify activate() geometry argument to allow window positioning relative to the pointer, another window or the screen and allow the centering of the window relative to the positioning point or by a specified offset. Also add the ability to position the window so that the mouse is over a particular widget in the toplevel.
Should handle all combinations of
when (always/first) where (center/geometry/mouse) parent (screen/window) and None (don't position)
Check Tix4.1.0/library/DialogS.tcl center method for how to center over another window
Check iwidget's shell.itk for code to center widget over screen or another widget.
See Pmw.Balloon code for how to position over pointer.
Tcl code to center over another (parent) window:
# center client relative to master (default xoff, yoff = -1) set geomaster [split [wm geometry $master] "x+"] set geoclient [split [wm geometry $client] "x+"] if {$xoff == -1} { set xoff [expr ( ([lindex $geomaster 0] - [lindex $geoclient 0]) / 2)] } set newxpos [expr [lindex $geomaster 2] + $xoff] if {$yoff == -1} { set yoff [expr ( ([lindex $geomaster 1] - [lindex $geoclient 1]) / 2)] } set newypos [expr [lindex $geomaster 3] + $yoff] wm geometry $client +$newxpos+$newypos
More tcl code to center dialog over another (parent) window:
(args: parent dlg) # First, display the dialog offscreen to get dimensions. set screenW [winfo screenwidth $parent] set screenH [winfo screenheight $parent] set w [expr $screenW + 1] wm geometry $dlg +$w+0 update # Get relative center of parent. set w [winfo width $parent] set h [winfo height $parent] set w [expr $w/2] set h [expr $h/2] # Get and add screen offset of parent. set w [expr $w + [winfo rootx $parent]] set h [expr $h + [winfo rooty $parent]] # Get dimensions of dialog. set dlgW [winfo width $dlg] set dlgH [winfo height $dlg] # Make adjustments for actual dimensions of dialog. set w [expr $w - $dlgW / 2] set h [expr $h - $dlgH / 2] # Let's keep the entire dialog onscreen at all times. # Center in screen if things are awry. set recenter 0 if { $w < 0 } { set recenter 1 } if { $h < 0 } { set recenter 1 } if { [expr $w + $dlgW] > $screenW } { set recenter 1 } if { [expr $h + $dlgH] > $screenH } { set recenter 1 } if { $recenter } { set w [expr ($screenW -$dlgW) / 2] set h [expr ($screenH - $dlgH) / 2] } wm geometry $dlg +$w+$h
Add geometry argument to show() (same as activate() above).
Dialog
Add label (header?) to Dialog class. May not be necessary, or too complicated.
ButtonBox
When a horizontal ButtonBox is stretched, the left button stays anchored to the left edge and there is too much space between the last button and the right edge.
Add an option to either evenly space the buttons across the button box, or to keep them together and justify them to the left, right or center. Check that deleting buttons works correctly.
ComboBox
Remove arrowrelief option from ComboBox and do what counter does: gets value of arrow's relief just before sinking it, then restores it later.
Change bindings: remove all bindings from arrow key and remove arrow key from <tab> focus sequence; only implement these bindings on the entry widget:
Up popup dropdown list, scroll up if already displayed Down popup dropdown list, scroll down if already displayed Esc popdown dropdown list, return entry to previous value Enter popdown dropdown list, execute current selection
Remove bindings from listbox and scrollbar(s), so that all bindings are via the entry widget?
When entering keys when list is displayed, scroll list to first entry beginning with entered keys. If no match, scroll list to top.
Remove many of the arrow bindings from Pmw.ComboBox - there are just too many key bindings on the arrow button. There is no need for it to respond to keys such as the up/down keys when the adjacent Entry widget already does so. I propose to remove all Pmw.ComboBox arrow button key bindings except for <space>, which can be used to bring up the dropdown list. The Entry widget behaviour would remain unchanged: when it has focus, you can use the up/down keys to go to the next/previous entries and then use <Return> to invoke the selection command.
Alternatively, make the bindings the same as the MS-Windows combobox. (Use the url entry field in Navigator or IE as an example of MS-Windows behaviour). These have been reported to be:
All mouse actions are exclusively triggered by the left button.
Right button displays "Direkthilfe" on my german system ("Direct Help"). This is a floating button, that triggers display of a tool tip like the |?| button that appears next to the |x| at the right end of the title bar of some native windows dialogs.
The arrow is very slim (acutally flat: width/height is about 2/1)
Entry and popup have the same color ("window color")
The popup has a 1 pixel dark border, no spacing between popup and scrollbar.
If the box has the focus, the full entry is displayed in "selected" style.
If the box has the focus, up and left keys rotate items up, down and right keys rotate items down, all with immediate effect.
If the box has the focus, keys a-z (not case sensitive) rotate through the items with same first character, with immediate effect.
No separate focus for the arrowbutton
Discussing how the combobox behaves with arrow keys when it has the focus: "The concept is almost identical to what you already have, just gives more visual feedback. In your current implementation you allow to rotate through the values with the up and down arrow keys, showing the strings in the entryfield, and accepting the values when the user presses the spacebar (hmmm, how can I exit this without moving back to the original value manually?). On Windows, the choice is not shown in the entryfield, but the popup opens when you press the up or down arrow keys, as if you clicked on the arrowbutton, and you then navigate the values in the listbox. This avoids the display of not finally selected values in the entryfield and is a lot more obvious and less confusing. The current behaviour certainly confused me, which is why I first proposed the changes to the moveup/down methods." (Georg Mischler)
Also, check bindings on other megawidgets for consistency.
Modify Pmw.ComboBox so that the width of the entry widget is forced to be the same as the width of the dropdown listbox. If the "width" option to the standard listbox is 0, Tk sets the requested width of the listbox to be just large enough to hold the widest element in the listbox. Using this option, I can see that listbox.winfo_reqwidth() is changing as I insert items into an unmapped listbox. The question is, how do I get notified of these events so that I can set the width of the entry?
The problem is that the listbox is in another toplevel which has not yet been displayed, so I can't bind to <Configure> to determine its width.
One suggestion is to override the insert and delete methods of the Listbox class. The problem with this is what if the font changed, or the borderwidth, etc? You would need to override and check many more methods.
Add ability to tearoff dropdown list (suggested by Dean N. Williams).
Should be able to disable/enable arrow button.
Counter
Add option for different increment/decrement behaviour. For example, assuming increment is 1:
Current behaviour - move to the next multiple of the increment, eg: 1.0 -> 2.0, 1.234 -> 2.0
Add or subtract the increment to whatever is displayed, eg: 1.0 -> 2.0, 1.234 -> 2.234
Move to the next multiple of the increment, offset by some value. eg: (if offset is 0.5) 0.5 -> 1.5, 1.234 -> 1.5, 1.678 -> 2.5
Add wrap option (to wrap around at limits) (then don't need time24 arg to 'time' datatype).
Add a state option to disable Counter.
Add option to Counter to allow the buttons to be on the same side, one on top of the other, like Tix, Itcl, Motif, Windows 95, etc. There should probably also be an option to lay the current large buttons on the same side of the entry field, next to each other.
Redo TimeCounter using vertical Counter, add limitcommand option to Counter to allow overflow from seconds to minutes to hours
Arrowed megawidgets (Counter, ComboBox, TimeCounter)
Potential construction speed up if Canvas arrows are replaced by Label with Bitmap or BitmapImage. The hard part would be to make the bitmap change size depending on size of Label.
Pmw.drawarrow should draw arrows which look like Tk cascade menu arrows.
EntryField
Can it be modified to change all entered characters to upper or lower case automatically? Or first-upper or first-of-each-word-upper?
If the validity of the currently displayed text is ERROR, allow any changes, even those which result in invalid text. This is useful when invalid data has been given to the value option and the user is trying to correct it.
LabeledWidget
Add tix-style border.
MenuBar
Maybe Pmw.MenuBar should also have (optional) balloon help for menu items as well as menu buttons. I am not sure whether users would find this useful.
The status help hints do not appear when using F10/arrow keys.
Look at the Tk8.0 menu demo and check the help bindings for ideas, in particular, how can you get help when using keyboard bindings.
Check the new menu features in Tk8.0 for creating "native" menu bars and the special ".help" menu.
Add index() method.
Add a 'position' option to addmenu and deletemenu methods. This option should accept an index number, a menuName or Pmw.END.
Look at itcl menubar for ideas.
Balloon
Positioning of the balloon with respect to the target widget or canvas item: There are a number of ways that Pmw.Balloon could be improved. For example, currently the the top left corner of the balloon is positioned relative to the bottom left corner of the target, offset by the [xy]offset options. These options apply to all targets - they can not be set differently for different targets.
To make it more configurable, the user should be able to specify, for each target:
the base position in the target relative to which the balloon should be placed (n, s, e, w, nw, sw, ne, se, c) (Currently sw)
the x and y offsets (Default (20, 1))
the position in the balloon that should be placed at the offset position (n, s, e, w, nw, sw, ne, se, c) (Currently nw)
Note, if this is anything other than nw, update_idletasks() will need to be called to get the size of the balloon before it is positioned - there is a possibility that this may cause weird ugly flashing.
whether either the base x or y position should be taken relative to the current mouse position rather than as one of the corners of the target. This would be useful for large targets, such as text widgets, or strange shaped canvas items. This could be specified using special base positions, such as (nm, sm, em, wm). For example, for 'sm', the x base position is the mouse x position and y base position is the bottom (south) edge of the target.
The user should be able to specify global defaults for all of these, as well as be able to override them for each target. The Pmw.Balloon options and their defaults could be:
basepoint sw # Position on target. anchor nw # Position on the balloon xoffset 20 # x distance between basepoint and anchor yoffset 1 # y distance between basepoint and anchor
To be able to override these, the bind() and tagbind() methods would have to accept these as additional arguments. Each would default to None, in which case the default values at the time the balloon is deiconified would be used.
I'm not sure about how to handle the case when the balloon is configured to come up under the mouse. When this happens the balloon flashes on and off continuously. This can happen now if you set the yoffset to a negative number. Should the balloon widget detect this and do something about it?
Add showballoon(x, y, text) method to Balloon and use in balloon help for a listbox:
On 3 Dec, Michael Lackhoff wrote:
And another question: Is it possible to create a balloon-help for the entries in the listbox? Not all the information is in the listbox and it would be nice if a balloon help could give addtional information.
Rather than popup a balloon help window as the mouse moves over items in the listbox, I think it would be better if it pops up after you clicked on an item (or a short time afterwards). Pmw.Balloon displays the balloon help a short time after the mouse enters a widget, so is not directly usable in this case. However, a method could be added to Pmw.Balloon to request it to popup the balloon at a particular x,y position. This method could be called from the listbox_focus method above. Something like:
def listbox_focus(self, event): self.indexlist.component('listbox').focus_set()
text = self.indexlist.getcurselection() # expand text to whatever you want: text = 'This is ' + text self.balloon.showballoon(x, y, text)
The Pmw.Balloon showballoon() method would have to set a timer which sometime later calls another method which displays the text. You would also need to bind <ButtonRelease-1> to a hideballoon() method which withdraws the popup.
The balloon can be displayed off-screen if the window is near the edge of the screen. Add a fix so that the balloon always stays on the screen (but does not popup under the mouse, otherwise it will immediately pop down).
Add a fix so that the balloon does not disappear if the mouse enters it. Could do this by setting a short timer on the Leave event before withdrawing the balloon and if there is an Enter event on the balloon itself, do not withdraw it.
For tagged items in text widgets, the balloon is placed relative to the character in the tagged item closest to the mouse. This is not consistent: in the other cases (including canvas), the balloon is placed relative to the bottom left corner of the widget or canvas item. This should also be the case for text items.
Is the new (in Tk8) "<<MenuSelect>>" event useful for balloon and/or status help.
MessageBar
Finish logmessage functionality.
Add colours and fonts to MessageBar message types. For example, systemerror message types could have bold font on a red background.
Add message logging history view (like the ddd debugger).
NoteBook
Notebook should recalculate layout if the requested size of a tab changes (eg font size, text, etc).
The tabpos option should accept s, e and w as well as n.
Possible new options (borrowed from iwidgets):
equaltabs
If set to true, causes horizontal tabs to be equal in in width and vertical tabs to equal in height.
Specifies whether to force tabs to be equal sized or not. A value of true means constrain tabs to be equal sized. A value of false allows each tab to size based on the text label size. The value may have any of the forms accepted by the Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
For horizontally positioned tabs (tabpos is either s or n), true forces all tabs to be equal width (the width being equal to the longest label plus any padX speci- fied). Horizontal tabs are always equal in height.
For vertically positioned tabs (tabpos is either w or e), true forces all tabs to be equal height (the height being equal to the height of the label with the largest font). Vertically oriented tabs are always equal in width.
Could have a special value which sets equal sized and also forces tabs to completely fill notebook width (apparently like Windows).
tabgap
Specifies the amount of pixel space to place between each tab. Value may be any pixel offset value. In addi- tion, a special keyword overlap can be used as the value to achieve a standard overlap of tabs. This value may have any of the forms acceptable to Tk_GetPixels.
raiseselect
Sets whether to raise selected tabs slightly (2 pixels).
Specifes whether to slightly raise the selected tab from the rest of the tabs. The selected tab is drawn 2 pixels closer to the outside of the tabnotebook than the unselected tabs. A value of true says to raise selected tabs, a value of false turns this feature off. The default is false. The value may have any of the forms accepted by the Tcl_GetBoolean, such as true, false, 0, 1, yes, or no.
bevelamount
Specifies pixel size of tab corners. 0 means no corners.
There should be a way to temporarily hide a page, without deleting it (like pack_forget). (Suggested by Michel Sanner)
OptionMenu
Should accept focus and obey up and down arrow keys.
PanedWidget
Add index() method
Modify all methods so that they accept Pmw.END as a pane identifier as well as an index or a name.
Check iwidgets pane and panedwindow classes.
RadioSelect
Add insert() and delete() methods.
The index method should have forInsert argument.
Add Pmw.SELECT to index() method. For single selectmode this returns an integer, for multiple selectmode this returns a list of integers.
Add option to set background color on selected buttons. Maybe should also be able set selected foreground as well. Any others?
LogicalFont
Add boldFixed fonts,
Search for closest size font if no exact match.
Maybe replace with Tk8.0 font mechanism.
Can the Tk8.0 font measuring functionality be used in Pmw somehow?
Scrolled widgets
Can some common scrolling methods be factored out, either as a base class, "ScrolledMixin" mixin class or as helper functions? Candidate methods: constructor, destroy, interior, _hscrollMode, _vscrollMode, _configureScrollCommands, _scrollXNow, _scrollYNow, _scrollBothLater, _scrollBothNow, _toggleHorizScrollbar, _toggleVertScrollbar.
ScrolledField should have optional arrow buttons, so that it can still be scrolled even if the mouse does not have a middle button.
Miscellaneous
Add a button to the Pmw "Stack trace window" which optionally removes all grabs:
I normally interact with the "Stack trace window" immediately, and dismiss it afterwards. In many cases where a bug appears like this, the rest of the application is still functional (many of the problems appearing at this stage of development of my application are unforeseen exceptions communicating with a robot on the other end of a socket, not affecting the GUI per se). For that reason I'd prefer if the "stack trace window" would push another grab on the grab stack (if any grabs are active at the moment the exception occurs). Could the window have an extra "Terminate application" option for this case?
need to handle component option queries in configure():
foo = Pmw.AboutDialog(applicationname = 'abc XYZ') foo.component('message').configure('text') - works foo.cget('message_text') - works foo.configure('message_text') - doesn't
Implement bindings (ComboBox, etc) via a dictionary lookup, to allow people to invent new bindings, such as for handicapped users. (Suggested by Michael McLay)
Modify bundlepmw.py so that it checks Pmw.def to see that no files have been missed.
Potential cheap speedup by adding this to each module, or inside functions if it has a loop containing calls to builtins:
from __builtin__ import *
Look at how update_idletasks and after_* are used in Pmw - are they consistent? could it be improved? What are the problems of using these on other bits of an application (such as when the size of the toplevel is being determined for the window manager).
If lots of errors occur (such as in a fast time callback) the error window may not appear, since Tk will wait until it is idle - which may never occur. The solution is to call update_idletask when updating the error window, but only after a short time has passed. This will provide better user response. However, it may not be possible to do this if some python interpretes (omppython, for example) do not handle calls to update_idletasks at certain times.
In the Pmw FAQ, in the "Why don't Pmw megawidgets have a 'state' option?" section, it mentions several Pmw megawidgets that can not be disabled. Fix them.
Add RCSID version string to all files.
When raising exceptions use the third argument to raise:
raise SimulationException, msg, sys.exc_info()[2]
When update_idletasks is called all pending changes are flushed to the window system server. However, it may take some time for the server to display the changes. If it is required that the display be up-to-date, update_idletasks should be followed by a call that blocks until processed by the server and a reply received. This may be useful in Pmw.busycallback to ensure the busy cursor remains visible until the display is actually modified.
There is a small bug which appears only with Tk8.0 (the bug is not apparent with Tk4.2). If a dialog is activated and pops up directly over the cursor and the dialog has a default button, then pressing the <strong>Return</strong> key will not invoke the default button. If you move the mouse out of and then back into the dialog, pressing the <strong>Return</strong> key will work. This behaviour has been noticed in Tcl-only programs, so it is probably a bug in Tk. (Tested on Solaris.)
Modify PmwBlt.py to use blt2.4 instead of blt8.0.unoff. Nick Belshaw <nickb@earth.ox.ac.uk> is looking at wrapping the new BLT StripChart and TabSet into Pmw.
Perhaps Pmw should have its own exception defined, like TkInters's TclError, perhaps called PmwError.
This one is caused by a bug in the implementation of Tcl/Tk for Microsoft Windows NT (and maybe other Microsoft products). Mouse release events can get lost if the grab_set and grab_release commands are used and the mouse goes outside of the window while the mouse button is down. This can occur while Pmw modal dialogs are active. Below is some Tkinter-only code which demonstrates the problem. Maybe there is a work around.
# Test script to demonstrate bug in Tk #implementation of grab under NT. # Click on "Dialog" to bring up the modal # dialog window. Then button down on the scale, # move the mouse outside the window, # then button up. The scale slider will still # be sunken and clicks on the "OK" button # will be ineffective. import Tkinter def activate(): waitVar.set(0) toplevel.deiconify() toplevel.wait_visibility() toplevel.grab_set() # Problem here toplevel.focus_set() toplevel.wait_variable(waitVar) def deactivate(): toplevel.withdraw() toplevel.grab_release() # and here waitVar.set(1) root = Tkinter.Tk() toplevel = Tkinter.Toplevel() waitVar = Tkinter.IntVar() toplevel.withdraw() scale = Tkinter.Scale(toplevel, orient='horizontal', length=200) scale.pack() button = Tkinter.Button(toplevel, text='OK', command=deactivate) button.pack() button = Tkinter.Button(text='Dialog', command=activate) button.pack() button = Tkinter.Button(text='Exit', command=root.destroy) button.pack() root.mainloop()
Documentation
Document how to get Pmw working on a Mac, for example:
Unzip and untar
This depends on what you use to unpack the tar file. If you use (macgzip and) SunTar you have to tell it that files with ".py" extensions are text files (in the preferences/file type section). If you use stuffit expander: this can be made to do the conversion correctly, but it could be that this only works if you set the .py extension correctly in Internet Config.
Where do you untar Pmw?
How do you get line terminators correct (carriage return/line feed)?
Is there any problem with file name case? (mixed upper/lower case)
Is there any problem with file name length?
(Joseph Saltiel says: It was the same type of operation as in Windows/Unix. Run a program that unzips it and untars it. It seems to get case and length right on its own.)
Let python know where Pmw is
If Pmw is in its own folder you will have to add the parent of that folder to the sys paths in Edit PythonPaths. If it is in the Python home folder, you do not need to do this.
Make sure that the Pmw folder is called "Pmw" and not something else. Since Pmw is a package, python expects to find a "Pmw" folder somewhere in sys.path.
(Joseph Saltiel says: With the Python distribution on the Mac there is an application called editPythonPrefs, when you run it it gives you a list of a paths. These paths are similiar to the PYTHONPATH variable. I just added the path to Pmw at the bottom of this list.)
Document general ideas about building guis, eg:
When I write gui applications, I usually defer creation of windows as much as possible - this means that the application starts up quickly because it usually only has to create the main window. Whenever another window is required for the first time, it is created then. When the user has finished with the window, the window is withdrawn, not deleted, so that next time it is required it much faster to come up.
In summary - don't create a window until you need and don't destroy a window if you may want it again.
The amount of memory required to keep the windows should not be very much - except for very long running programs where the user may create thousands of different windows.
Add class hierarchy diagram to documentation:
MegaArchetype MegaToplevel etc MegaWidget etc
Add to doco something like: "Another way to extend a Pmw
megawidget is to specify a non-default type for one of the
components. For example text_pytype = FontText
."
Document pyclass and pyclass = None (options for null components are ignored; the only time this can be used is with the Group's tag component - all other's use the component widget in some way)
Create index of all Pmw methods, functions, options, components.
Add description of how to run the Pmw demos without installing.
Add description of how to install Pmw.
Describe grid structure of megawidgets, so that it is possible to extend megawidgets by adding new widgets into the interior (hence avoiding a childsite in most megawidgets)
Document error display and difference between callback and binding error reports.
Document difference between 'Helvetica 12' and 'Helvetica size: 12' in logicalfont.
Add to howtouse, to describe using the option database to set options for a specific megawidget:
import Pmw root = Pmw.initialise(useTkOptionDb = 1) root.option_add('*entryfield24*Label.text', 'German') e = Pmw.EntryField(hull_name = 'entryfield24', labelpos = 'w') e.pack() root.update()
Also document hull_name and hull_class.
Finish FAQ, ReleaseProcedure and StructuredText test.
Put html through gifwizard and html lint.
http://www.cen.uiuc.edu/cgi-bin/weblint (eg: http://www.cre.canon.co.uk/~neilb/weblint/manpage.html)
Delete comments from source if they have been added to docs (should not have two copies of anything).
Need to document non-standard initial values for component options, such as border in ButtonBox and Dialog's childsite.
Docs should have DEFAULT BINDINGS section (like iwidget combobox).
Promote home page:
http://www.geocities.com/homestead/promote.html http://www.submit-it.com/subopt.htm, etc
Create man pages as well as html (modify createmanuals to produce both).
Maybe something with html frames like: itcl2.2/html/index.html
Add to starting.html a note that Pmw is a python "package" and add a pointer to python documentation on packages.
Document scrolled widget implementations, explaining why they are all slightly different (because the underlying widgets which are being scrolled have different behaviors).
Make copyright clearer. Maybe borrow python's?
Demos
Check for missing demos.
In all demos can move the three lines beginning with "Import Pmw from the sibling directory", to inside "if __name__" clause. Also, "sibling directory" is now incorrect. Also, add note that this is only necessary when running demos without installing Pmw.
Change demo/All.py so that it displays the traceback if it cannot load or run a demo (easier for users to report errors).
Add option to demo/All.py: "Display demos in separate window" to allow resizing of sub-demos
TimeCounter and Spectrum demos beep when they come up, using:
root.option_add('*EntryField*value', 'VALUE')
In demos, add title = 'blah'
to top of file and replace
root.title(..)
with root.title(title)
at bottom.
Add comprehensive speed test demo which creates one or more of each (common) megawidget. Remove old SpeedTest demo.
Check demos work when called from ptui. (Changes have to do with calling compile/exec where __name__ is not the name of the All.py script, but is '__builtin__')
PromptDialog demo should not remember password.
Finish Counter, Radioselect demos.
Modify the All demo so that you can reload a demo module.
The syntax-coloured code viewer looks strange on Microsoft NT, because the size of the fonts differ. Check out Guido's idle-0.1 text colouring for Pmw code viewer.
Document restrictions on adding bindings to a megawidget: you probably need to bind to components of the megawidget and also check that you are not destroying bindings set up by the megawidget itself.
Add a demo that demonstrates setting the color scheme at run time.
Tests
Check for missing tests, such as TimeCounter, RadioSelect, SelectionDialog, MessageBar, MenuBar, ComboBoxDialog, Balloon.
Create test for useTkOptionDb option to Pmw.initialise().
Check that destroyed widgets' python classes are garbage collected (add test and/or demo).
Add tests for changecolor, setscheme, etc.
Need Resources test.
Create tests for deriving from Pmw classes (eg ComboBox).
Ideas
Add more Tix (www.xpi.com/tix/screenshot.html) and iwidgets widgets.
Look at spinner.itk for how to do vertical orientation on same side for Counter.
Investigate these new features in Tk8.0 and see if they could be used in Pmw:
embedded images in text widgets destroy command ignores windows that don't exist
Pmw 1.3 - 7 Aug 2007 - Home
This is a list of some of the known bugs in Pmw. If you fix any of these, please let the maintainer (gregm@iname.com) know.
Under the Enlightenment window manager, if show() is called when a window is already displayed (and is not obscured by other windows), then the application will hang for two seconds. This is either a bug in Tcl/Tk or in Enlightenment. See the comment in the Tk function WaitForConfigureNotify() in the Tk source file tk8.3.2/unix/tkUnixWm.c:
/* * One more tricky detail about this procedure. In some cases the * window manager will decide to ignore a configure request (e.g. * because it thinks the window is already in the right place). * To avoid hanging in this situation, only wait for a few seconds, * then give up. */
On NT, Pmw.MenuBar does not display message bar help for menu items. It seems that Tk menu widgets do not support <Motion> events on MS. This probably is an issue that should be taken up with the Tcl/Tk people. (Reported by Stefan Schone. Pmw.0.7)
Run the CounterDialog.py demo, select the show dialog button and press ok. Now exit the dialog (either with the exit button or the close box). The following error appears:
Menu ID 256 is already in use!Fatal Python Error: Tcl/Tk panic
This may be a problem with Mac version of Tk. (Reported by Anthony Wilson.)
Pmw.Balloons bind to widgets and canvas items. This means that bindings made by other users are deleted when the balloon makes its bindings. (For example, the "Delete" canvas item in the Balloon demo overrides that <ButtonPress> binding and so that balloon is not withdrawn when the mouse button is pressed over the item.)
The obvious solution is for Pmw.Balloon to add its bindings with a +. But this would make the unbind and tagunbind methods inconsistent - they would remove all bindings, not just the ones added by the balloon. A better way would be for the balloon to add a bindtag to each widget`s bindtag list - then it would not upset any other bindings and it could be deleted cleanly. (Reported by Joe Saltiel)
import Tkinter import Pmw def foo(event): print '<Enter> event on text' root = Pmw.initialise() balloon = Pmw.Balloon() canvas = Tkinter.Canvas() canvas.pack() text1 = canvas.create_text(50, 50, text = 'hello there') # As is, the balloon does not appear over the text, but foo # is called. Swap the following two lines and the balloon # appears but foo will not be called. canvas.tag_bind(text1, "<Enter>", foo) balloon.tagbind(canvas, text1, 'text 1 help') root.mainloop()
In Pmw.Balloon, the balloon should not be withdrawn when the pointer leaves a widget or item and it immediatly enters another widget or item with balloon help. Instead, the balloon should be moved and its contents changed immediately.
When a Pmw.Balloon is bound to a canvas item, moving the item becomes very slow. (Reported by Joe Saltiel)
> Second, after I fixed my ordering problem I noticed, there > is a pretty big delay in updating widgets that have balloon > messages bound to them. (For example dragging a box across > a screen, the box has a delayed reaction.) I believe this is > due to some of the timing functions used in PmwBalloon, I am > not sure if there is a way around it. I set all timers to > zero, and still had the problem.
When running Pmw demos under ptui the busy cursor does not appear.
If a combobox has a horizontal scrollbar and it displays its listbox above the entry, then it is misplaced.
Bug in Pmw.PanedWidget: repeat by creating new panes in Demo - existing panes jump to the right 1 or 2 pixels.
Bug in Pmw.PanedWidget: repeat by setting hull_borderwidth to 20 in demo - initial drag jumps to right by about 20 pixels. Also right hand side border is missing. (Fix may be similar to method used in Pmw.ScrolledFrame to give canvas border.)
Fix ButtonRelease events so they do not trigger without a corresponding ButtonPress event.
From Joe Saltiel: I was playing around with a scrolledlistbox and tkFileDialog. When I have the dialog open above the list box and I doubleclick on it, I invoke the selectioncmd of the listbox as well as the tkFileDialog box, should this be happening?
Attached is small sample program you can try. To get the bug to show you must do two things. First, when you open the file dialog box, make sure the item you are going to select if over(above) the scrolledlistbox. Second, you have to double click on that item. If you single click and hit "Open" you do not get the bug. Nor do you get it unless the file you click on is directly over the clickable region of the scrolledlist box.
import Tkinter import Pmw import tkFileDialog import string def askOpen(): file = tkFileDialog.askopenfile(filetypes=[("all files", "*")]) print file def printMe(): print "Me" root = Tkinter.Tk() Pmw.initialise(root) frame1 = Tkinter.Frame(root) lst = string.split("abc def ghi jkl mno pqr stu vwx yz") lstbox = Pmw.ScrolledListBox(frame1, items=lst, selectioncommand=printMe) lstbox.grid(row=0, column=0, columnspan=2) Tkinter.Button(frame1, text='open', command=askOpen).grid(row=1, column=0) Tkinter.Button(frame1, text='exit', command=root.destroy).grid(row=1, column=1) frame1.pack() root.mainloop()
Response: I have found where the problem is but I am not sure how to fix it. It appears that the tkFileDialog box closes on a ButtonPress event. The corresponding ButtonRelease event is then sent to whichever widget is under the cursor at the time of the Release. I have reproduced the problem with a Tcl-only script:
listbox .l .l insert 0 1 2 3 4 bind .l <ButtonRelease-1> {puts AAAGGHHH!} button .b -text open -command tk_getOpenFile pack .l .b
If you do a quick Press-Release-Press over the file dialog, it is withdrawn. If you then keep the mouse button down and move the mouse around, you will see that the button and the listbox still respond to it. If you do the final button Release over the listbox, its <ButtonRelease-1> binding is invoked.
I think the correct solution is to modify Pmw to be very careful when to accept ButtonRelease events. It will need to also bind to ButtonPress events and make sure that it gets a Press before it accepts the Release. I'll try to do the change as soon as possible, but the code involved is fairly complex so I it may take a little time.
Investigate bug in Tk8.0: When a dialog pops up over the pointer then the keyboard focus is not set and so <Return> does not invoke default button.
Under both X and NT, the arrows in the timecounter, counter and combobox do not match the scrollbar arrows.
Pmw.Group does not work correctly when the tag is a compound widget. The tag is placed such that the top of the tag is cut off. (Reported by Peter Stoehr.)
import Tkinter import Pmw root = Tkinter.Tk() Pmw.initialise(root, fontScheme = 'pmw1') exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) exitButton.pack(side = 'bottom') def makeGroup(tagClassName): tagClass = eval(tagClassName) group = Pmw.Group( tag_pyclass = tagClass, hull_background = 'red', groupchildsite_background = 'blue', ) group.pack(fill = 'both', expand = 1, padx = 6, pady = 6) child = Tkinter.Label(group.interior(), text = 'Group with tag ' + tagClassName, background = 'aliceblue', ) child.pack(padx = 10, pady = 5, expand = 1, fill = 'both') return group grp1 = makeGroup('Pmw.EntryField') grp2 = makeGroup('Pmw.ComboBox') grp3 = makeGroup('Tkinter.Entry') root.mainloop()
Also, Pmw.Group does not resize correctly if the simple widget changes size. For example:
grp3.configure(tag_font = ('Helveltica', '-160'))
Bug(s) in PmwScrolledCanvas. There is a bug in 0.8.1 PmwScrolledCanvas._setRegion. If there are no objects in the canvas, then error occurs on len(region) because region is None. Below is an attempt to fix it. Click on Show, then on Delete. The window then continuously resizes. If the ScrolledCanvas is created with canvasmargin = 0, the problem goes away. (Reported by Anders Henja.)
import Tkinter import Pmw def _setRegion(self): # Attempt to fix PmwScrolledCanvas._setRegion. self.setregionTimer = None region = self._canvas.bbox('all') canvasmargin = self['canvasmargin'] if region is None: region = (0, 0, 0, 0) region = (region[0] - canvasmargin, region[1] - canvasmargin, region[2] + canvasmargin, region[3] + canvasmargin) self._canvas.configure(scrollregion = region) def show(): canvas.component('canvas').delete('all') canvas.create_oval(0, 0, 800, 600, fill = 'red') canvas.configure(canvas_width = 600, canvas_height = 450) canvas.resizescrollregion() def delete(): canvas.component('canvas').delete('all') canvas.configure(canvas_width = 0, canvas_height = 0) canvas.resizescrollregion() root=Tkinter.Tk() Pmw.initialise(root) buttonbox=Pmw.ButtonBox() buttonbox.pack(fill='x',side='bottom',padx=5,pady=5) buttonbox.add('Show',command=show) buttonbox.add('Delete',command=delete) buttonbox.alignbuttons() canvas=Pmw.ScrolledCanvas(canvasmargin=2) canvas.__class__._setRegion = _setRegion canvas.pack(fill='both',side='right',expand=1) root.mainloop()
Bug in Pmw.Dialog: if defaultbutton is configured before buttons during self.initialiseoptions() (that is if self._constructorKeywords.keys() returns a different order), then setdefault() fails.
Bugs in Tk which affect Pmw.MainMenuBar:
Extra bindings assigned to a Tkinter.Menu widget using bindtags have no effect. Hence the method used in Pmw.MenuBar for status help (bind_class followed by bindtags) does not work and therefore binding to the menu widget is used instead.
The 'active' tag for the index()
method of Tkinter.Menu
always returns None. Hence, in the menu widget motion
binding, event.y
and the '@' format is used instead, for
all menus except the toplevel main menu.
For the toplevel main menu, event.x
must be used for the
index()
method, but it returns the wrong index. It
appears that the Tk widget is assuming vertical layout
to calculate distances, rather than horizontal.
For toplevel main menus, several Tk commands, such as
winfo_height()
, do not work. This prevents the use of
balloon help for Pmw.MainMenuBar.
Bug in Pmw.ComboBox: Tab to combobox arrow, use up/down arrow keys to change selection, hit return, nothing happens, <Shift Tab> to entry window, hit return, combobox changes
actually, it would be better if you could not tab to the arrow, only the entry field, like the Pmw.Counter.
the problem is if the entry field is not editable, what to do then?
Bug in TimeCounter: Arrow keys don't work when focus is on entry.
Bug in Pmw.NoteBook: The size of the tab does not change when the text value changes
Bug in Pmw.NoteBook: The name of the tab components has a "-" sign in it, which means that component options can not be used in the configure command. Eg:
n = Pmw.NoteBook() p = n.add('page1') n.configure(page1_background = 'red') # works n.configure(page1-tab_background = 'red') # fail, must do this: n.component('page1-tab').configure(background = 'red') # works
Pmw 1.3 - 7 Aug 2007 - Home
Copyright 1997-1999 Telstra Corporation Limited, Australia Copyright 2000-2002 Really Good Software Pty Ltd, Australia
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Pmw 1.3 - 7 Aug 2007 - Home
Pmw is a toolkit for building high-level compound widgets in Python using the Tkinter module.
It consists of a set of base classes and a library of flexible and extensible megawidgets built on this foundation. These megawidgets include notebooks, comboboxes, selection widgets, paned widgets, scrolled widgets, dialog windows, etc.
Local documentation
External links
See the Pmw megawidgets home page for the latest information about Pmw.
Comments, bugs, fixes to the Pmw discussion and announcement mailing list.
Pmw 1.3 - 7 Aug 2007
This document describes how to fetch and install Pmw, and how to run the demonstrations and tests.
Pmw.1.3 requires the _tkinter and Tkinter modules. It works with python versions 1.5.2 and greater (tested up to 2.2.1) and Tk versions 8.0 and greater (tested up to 8.3.2).
If the BLT extension to Tk is present, Pmw will use the BLT busy command during modal dialogs to display a clock cursor. Also, the Pmw.Blt interface to the BLT busy, graph, stripchart, tabset and vector commands will be available. BLT versions 2.4i and greater are supported (tested up to 2.4u). You can find BLT at http://www.tcltk.com/blt/.
Releases of the Pmw distribution are available via http from
http://download.sourceforge.net/pmw/
. This release is available
as
Pmw.1.3.tar.gz
, released on 7 August 2007.
This is a compressed tar file.
Under Linux, Unix, etc, you will need to
unpack it using tar
and you may also need to use
gzip
or gunzip
to uncompress it.
Under Microsoft Windows, you will need a program such as WinZip (http://www.winzip.com) that can
unpack the gzipped tar files. You may need to change the suffix of
the file to .tgz for WinZip to recognise it.
This will unpack into a directory named src containing the directory Pmw and the
installation utility setup.py. You now need to put this
directory Pmw somewhere python can find it, preferably in one of the
standard places, such as in the site-packages
directory
(eg: /usr/lib/python2.2/site-packages/Pmw
) or the
sys.prefix
directory (eg: C:\Program
Files\Python\Pmw
or /usr/lib/python2.2
).
One easy way to install the Pmw directory in the site-packages directory of your
installation is to use the setup.py utility.
This is done as follows:
python setup.py install
(as root)
or
sudo python setup.py install
(under Ubuntu or Mac OS X)
Alternatively, to install manually, for example under Unix, assuming you have placed the tar file in the
/tmp
directory, you can simply run the following
commands:
cd /usr/lib/python2.2/site-packages gunzip /tmp/Pmw.1.3.tar.gz (or gzip -d /tmp/Pmw.1.3.tar.gz) tar xvf /tmp/Pmw.1.3.tar
If you do not have write permission for these standard directories,
place the Pmw
directory somewhere on your PYTHONPATH
or
sys.path
. If this is not possible, place the Pmw
directory somewhere else and add the parent directory to your
PYTHONPATH
or sys.path
.
If you have previously installed Pmw version 0.6 or later, then the
new version can share the same Pmw
directory as the
previous versions. You will need to perform the tar
extraction in the directory containing (that is, the parent directory
of) the existing Pmw
directory. By default, your
applications will use the most recent version of Pmw. If required,
the function Pmw.setversion()
can be used to specify a
version to be used. See the reference manual for details. If you are
no longer using the older versions, you can safely remove the
corresponding subdirectories from the Pmw
directory.
If you need assistance in installing BLT under Unix, please contact me (gregm@iname.com) and I will try to help. For other operating systems, such as Microsoft or Macintosh, you should try asking the python newsgroup. If anyone can give me a description of how to install BLT under other operating systems please contribute it and I will place it here.
The doc
directory for each Pmw version contains all the
documentation for that version of Pmw. See the local home page for a complete list of documents. The
files in this directory are also available from the official Pmw home page.
An excellent tutorial and reference covering the Pmw interface to the powerful Blt graph widget, "A User's Guide to Pmw.Blt" written by Bjrn Ove Thue and Hans Petter Langtangen, is available. You can also download the full HTML document for local viewing.
A good way to get an overview of the functionality provided by Pmw
is to run the demonstrations and tests and look at the demonstration
code. To view a comprehensive demonstration of many of the features
of Pmw run the All.py
script, which can be found in the
demos
subdirectory of each version of Pmw.
You do not have to install Pmw to run the demonstrations and tests,
simply change into the appropriate directory and run the file
All.py
. See Demonstrations and tests for more
information about running the demonstrations and tests and how to
create your own.
Note that there are some bugs in later versions of BLT (at least 2.4t and 2.4u) which cause some tests of Pmw.Blt.Graph to crash with python2.0 under Linux. These tests have been commented out (until BLT is fixed).
If you create some whiz-bang megawidgets and would like to contribute
them to Pmw, they will be most welcome. You should be able to get
some idea of the coding style used in Pmw code by reading How to build Pmw megawidgets and by looking
at the Pmw library code itself in the lib
directory of
each Pmw version.
If you would like to contribute a megawidget, it would be preferable if it also came with a simple demonstration and a test script. See Demonstrations and tests for information about how to create new demonstrations and tests.
Each megawidget should also have a reference manual describing its options, components and methods.
The released reference manuals are
automatically generated by merging specially marked-up text with the
output from megawidget query methods, such as
components()
, options()
and
componentaliases()
, and various other introspective
devices. If you are interested to see how the documentation is generated,
you can fetch the marked-up text and the python script to convert the
text to html from
http://download.sourceforge.net/pmw/Pmw.1.3.docsrc.tar.gz
. Download this
file into the Pmw/Pmw_1_3
directory of the Pmw source
tree. Unzip and untar the file. This will create a
docsrc
sub-directory of Pmw/Pmw_1_3
. If
you want to keep the documentation which came with the Pmw
distribution, rename the old doc
directory. Then change
directory to docsrc
and run createmanuals.py
.
After printing lots of warnings about documentation that has not been
written yet, this will create a new doc
directory
containing all the html documentation.
Here is an example set of commands to unpack the documentation source and regenerate the documentation, assuming you have downloaded the source in the Pmw/Pmw_1_3 directory:
cd Pmw/Pmw_1_3 gunzip Pmw.1.3.docsrc.tar.gz tar xvf Pmw.1.3.docsrc.tar mv doc doc.old cd docsrc ./createmanuals.py
If running under Unix, you will need to run the
createmanuals.py
script with a valid DISPLAY environment
variable, since it creates each megawidget and then queries it for its
options, components, etc. This is because Tk (and hence Tkinter)
requires a connection to an X server to run.
The todo list contains a long list of of suggestions, bugs and enhancements for Pmw. If you are interested in doing any of these, please let the maintainer (gregm@iname.com) know. Some of the items in the todo list may be considered bugs. There are also some other problems due to idiosyncrasies in the implementation of Tk.
The official Pmw licence (see copyright) basically lets you do anything with Pmw as long as you don't hurt anyone. There is also another licence, the "Postcard Licence":
"I'd like to get a postcard from you! I'm interested in who is using Pmw, where you live and where in the world Pmw is doing it's job"Please send me an e-mail to gregm@iname.com to get my postal address.
The initial ideas for Pmw were blatantly stolen from the itcl extensions [incr Tk] by Michael McLennan and [incr Widgets] by Mark Ulferts. Several of the megawidgets are direct translations from the itcl to python.
The base classes and most megawidgets were written by Greg McFarlane and Peter Munnings. Contributed megawidgets include: Pmw.TimeCounter by Joe VanAndel, Pmw.Group and an early version of Pmw.NoteBook by Case Roole, Pmw.ScrolledCanvas, Pmw.ScrolledFrame and another early version of Pmw.NoteBook by Joe Saltiel and Pmw.OptionMenu by Roman Sulzhyk. A big thank you to the following people for their bug reports, fixes, enhancements and suggestions: David Ascher, Robin Becker, Siggy Brentrup, Mark Colclough, Jerome Gay, Clemens Hintze, Rob Hooft Jack Jansen, Jonathan Kelly, Magnus Kessler, Matthias Klose, Andreas Kostyrka, Fredrik Lundh, Magnus Lycka, Graham Matthews, Dieter Maurer, Michael McLay, Daniel Michelson, Georg Mischler, Rob Pearson, Case Roole, Joe Saltiel, Roman Sulzhyk, Shen Wang, Chris Wright, and Guido van Rossum. Special thanks to Case Roole and Michael McLay for help with getting Pmw to work with python packages and many other nifty features. My deepest apologies if I have forgotten anyone. Please let me know.
The Pmw home page and project site is made available courtesy of SourceForge.
The current maintainer is Greg McFarlane. I monitor the Pmw discussion and announcement mailing list so please send any problems, comments, suggestions or enhancements to the list. You may also contact me directly at gregm@iname.com.
Pmw 1.3 - 7 Aug 2007 - Home
Pmw comes with an extensive range of demonstrations and tests. The demonstrations can be used to get a feel for what is provided by Pmw and the demonstration code can be viewed to see examples of how to use Pmw. The tests can be executed to check that there are no problems with running Pmw in your environment.
The Pmw demos
directory contains demonstration scripts
showing many of the features of Pmw megawidgets. To view a
comprehensive package of all the demonstrations, including a view of
the source code, run the All.py
script. Run
All.py -help
for a short description of the script's
options.
All of the demonstrations may also be run separately. Most of the
demonstrations show some of the features of one of the Pmw
megawidgets. For example, to see a demonstration of the ButtonBox
megawidget, change into the demos
directory and
run
python ButtonBox.py
Other demonstrations, which show other features of Pmw include
BltGraph.py demonstrates the Pmw interface to the BLT graph and vector commands BltTabset.py demonstrates the Pmw interface to the BLT tabset command Colors.py how to set color schemes ConfigClass.py how to configure the python class of a megawidger component ErrorHandling.py how Pmw displays run time errors in a window ExampleDemo.py template for new demonstrations Grid.py the Tkinter Grid geometry manager LogicalFont.py how to use standard values for fonts MessageInfo.py how to extend the Pmw MegaToplevel class NestedDialogs.py how nested modal dialogs behave Resources.py how to use the option database to modify Tk widget option defaults Resources_Pmw.py how to use the option database to modify megawidget option defaults ShowBusy.py demonstrates the Pmw interface to the BLT busy command SpecialEntry.py deriving from Pmw.EntryField Spectrum.py some of the Pmw color handling functions SpeedTest.py tests the speed of creating Pmw megawidgets TextDisplay.py how to extend the Pmw MegaWidget class WidgetDestroy.py megawidget destruction
If you create a new megawidget you can create a demonstration for it
by using the file
ExampleDemo.py
as a
template. This template allows the demonstration to be run
individually or to be automatically included as part of the
demonstration package All.py
. You should take a copy of
the template and name the new file after your megawidget. You should
then replace each instance of the word EXAMPLE
with the
name of your megawidget and replace the code in the
__init__
method with code to create and initialise one or
more instances of your megawidget, which should be a child of
parent
. You can add other methods as necessary.
The Pmw tests
directory contains a test framework
and a set of test scripts for Pmw.
The tests cover the standard Tkinter module and most of the Pmw megawidgets.
The tests make a great
demonstration of the flexibility of the megawidgets. Simply change
into the tests
directory and run
python All.py
.
If all tests pass there should be no output printed to standard output. If any of the tests fail, please send the test output to the maintainer at gregm@iname.com.
All of the tests may be run separately. Most of the tests test the features of one of the Pmw megawidgets. For example, to execute the test for the ButtonBox megawidget, run
python ButtonBox_test.py
The Test.py file contains general testing functions and is imported by all test files. Other files, which test other features of Pmw include
Blt_test.py BLT vector and graph interface Colors_test.py setting color schemes MegaWidget_test.py creation of megawidget classes Options_test.py option and component handling PmwBase_test.py more option and component handling Tkinter_test.py Tk widgets in the Tkinter module
If you create a new megawidget you should create a test for it. There
is no template file for creating tests, but by looking at the other
Pmw tests (for example,
ScrolledText_test.py
) you
will get some idea of how to create a test for your megawidget.
The test files are designed to be run both individually or
automatically by the test package All.py
. Each test file
must define the testData
tuple. This consists of a
sequence of 2-element tuples, each tuple being a test specification
for one megawidget. Usually a file tests only one megawidget and so
there is only one test specification. The first element in the
specification is the megawidget class and the second is a sequence of
(yet more) 2-element tuples. In each of these tuples, the first
element is a sequence of individual tests to perform on an instance of
the megawidget and the second element is a dictionary to use for
the keyword arguments when creating the instance. Each individual
test is a tuple, the meaning of which depends on the type of the first
element, which may be either a string, a function or a method of the
megawidget class, as explained below.
If the first element is a string, then it is treated as an option of the megawidget and configure() is called to set the option to the value specified by the second element. After setting the option, cget() is called to query the option. If the test tuple has three elements, then the value returned by cget() must equal the value specified by the third element. Otherwise, the value returned must equal the value specified by the second element. For example,
('vscrollmode', 'static'), ('text_relief', 'sunken'), ('vscrollmode', 'bogus', 'ValueError: bad vscrollmode ' + 'option "bogus": should be static, dynamic, or none'),
If the first element is a function or method, then the function or method is called. The arguments to the call are given by the second element. (As a special case, if the second element is not a tuple, it is used as the only argument to the call.) The test tuple may have 2, 3 or 4 elements.
If it has two elements, then the value returned by the call must be None. For example,
(c.exportfile, '/tmp/ScrolledText_test.py'), (os.unlink, '/tmp/ScrolledText_test.py'),
If it has four elements, then the third element is a dictionary to use for the keyword arguments in the call and the value returned by the call must equal the value specified by the fourth element. For example,
(c.search, ('abc', '0.0'), {'nocase': 1}, '2.24'),
If is has three elements and the third element is a dictionary, then it is used for the keyword arguments in the call and the value returned by the call must be None. For example
(c.configurepane, 'first', {'size' : 200}),
If is has three elements and the third element is not a dictionary, then the value returned by the call must equal the value specified by the third element. For example,
(c.components, (), ['hull', 'label']), (c.add, ('Legumes',), 'ValueError: name "Legumes" already exists'),
Some special functions and values supplied by the Test module that may be used in the tests include:
Test.callback callback taking no arguments Test.callback1 callback taking one argument Test.callbackN callback taking any number of arguments Test.currentWidget returns the widget instance being tested Test.num_options returns number of options for the widget Test.earthris a sample Tkinter.PhotoImage Test.flagup a sample Tkinter.BitmapImage Test.floatvar a Tkinter.DoubleVar Test.stringvar a Tkinter.StringVar
To slow down a test (to see what is being displayed), add the following line which sets the delay between tests to (say) 1000 milliseconds:
Test.setdelay(1000)
To print information about what is being tested, add the line:
Test.setverbose(1)
Pmw 1.3 - 7 Aug 2007 - Home
This document briefly describes how to design and code Pmw megawidgets by inheriting from the Pmw base classes. It shows step by step how to build a simple example megawidget. This megawidget allows the user to select one of a range of numbers and it also indicates if the selected number is greater than a given threshold.
The megawidget will be built using a Tkinter.Scale widget to allow the user to select a number in a range, and a Tkinter.Frame widget to act as an indicator, displaying red (say) if the selected number exceeds the threshold. It will look something like this:
The programmer using this megawidget will need access to the scale widget, since they will need to set the scale's range. Therefore the scale will be made a component of the megawidget. The programmer will probably not need access to the indicator frame, but, just in case the need arises to change the borderwidth or relief of the indicator, we will make it a component too. This illustrates a convention about components - for maximum configurability, make all sub-widgets components.
Apart from the component options now available through the scale and indicator components, the megawidget will need a few options of its own. It will need a threshold option to set the threshold. It may also need options to set the colors of the indicator when the selected value is both above and below the threshold. Other options could be orient or indicatorpos to specify the relative position of components and margin, padx or pady to specify spacing between and around the components. For this example, we will define three options - threshold, colors and value. The colors option will be a 2-element sequence specifying two colors (below threshold, above threshold). The value option will be the initial value of the scale.
The first things to do are to decide on a name for the new megawidget, decide which base class to inherit from and to begin to write the constructor. Most Pmw megawidgets are derived from either Pmw.MegaWidget, Pmw.MegaToplevel or Pmw.Dialog. In this case, since the widget is not to be contained within its own toplevel window, we will inherit from Pmw.MegaWidget. The constructors of megawidgets take one argument (the widget to use as the parent of the megawidget's hull, defaulting to the root window) and any number of keyword arguments.
class ThresholdScale(Pmw.MegaWidget): """ Megawidget containing a scale and an indicator. """ def __init__(self, parent = None, **kw):
Next, we need to define the options supplied by this megawidget.
Each option is specified by a 3-element sequence. The first element
is the option's name. The second element is the default value. The
third element is either a callback function,
Pmw.INITOPT or None. In the first
case, the function is called at the end of construction (during the
call to self.inialiseoptions
) and also
whenever the option is set by a call to
configure
. Pmw.INITOPT indicates that
the option is an initialisation option - it cannot be set by calling
configure
. None indicates that the
option can be set by calling configure
, but that there
is no callback function.
The call to self.defineoptions
also includes the
keyword arguments passed in to the constructor. The value given to
any option specified in the keywords will override the default
value.
# Define the megawidget options. optiondefs = ( ('colors', ('green', 'red'), None), ('threshold', 50, None), ('value', None, Pmw.INITOPT), ) self.defineoptions(kw, optiondefs)
After defining the options, the constructor of the base class should be called. The options need to be defined first so that a derived class can redefine the default value of an option defined in a base class. This is because the value specified by the derived class must be made available before the base class constructor is called. The keyword arguments should not be passed into the base class constructor since they have already been dealt with in the previous step.
# Initialise base class (after defining options). Pmw.MegaWidget.__init__(self, parent)
Now we should create the components. The components are created as children (or grandchildren ...) of the megawidget's interior.
# Create the components. interior = self.interior()
The first component to create is the indicator. The
createcomponent
method creates the sub-widget and
registers the widget as a component of this megawidget. It takes
five arguments plus any number of keyword arguments. The arguments
are name, aliases, group, class and constructor arguments. See the
Pmw.MegaArchetype reference manual)
for full details.
# Create the indicator component. self.indicator = self.createcomponent('indicator', (), None, Tkinter.Frame, (interior,), width = 16, height = 16, borderwidth = 2, relief = 'raised') self.indicator.grid()
The scale component is created in a similar way. In this case, the initial value of the scale is also set to the value of the value initialisation option.
# Create the scale component. self.scale = self.createcomponent('scale', (), None, Tkinter.Scale, (interior,), command = self._doCommand, tickinterval = 20, length = 200, from_ = 100, to = 0, showvalue = 0) self.scale.grid() value = self['value'] if value is not None: self.scale.set(value)
At the end of the constructor, the initialiseoptions
method is called to check that all keyword arguments have been used
(that is, the caller did not specify any unknown or misspelled
options) and to call the option callback functions.
# Check keywords and initialise options. self.initialiseoptions()
All other methods must now be defined. In this case, only one method is required - a method called whenever the scale changes and which sets the indicator color according to the threshold.
def _doCommand(self, valueStr): if self.scale.get() > self['threshold']: color = self['colors'][1] else: color = self['colors'][0] self.indicator.configure(background = color)
To complete the megawidget, methods from other classes can be
copied into this class. In this case, all Tkinter.Scale methods
not already defined by the megawidget are made available as methods
of this class and are forwarded to the scale component. Note that
the third argument to Pmw.forwardmethods
is the name of
the instance variable referring to the Tkinter.Scale widget and not
the name of the component. This function is called outside of and
after the class definition.
Pmw.forwardmethods(ThresholdScale, Tkinter.Scale, 'scale')
Important note: If a megawidget defines options
using defineoptions()
, then this method must be
called in the megawidget constructor before the call to the base
class constructor and a matching call to
initialiseoptions()
must made at the end of the
constructor. For example:
def __init__(self, parent = None, **kw): optionDefs = ... self.defineoptions(kw, optionDefs) BaseClass.__init__(self, parent) ... self.initialiseoptions()
The code below creates two of our example megawidgets. The first is created with default values for all options. The second is created with new values for the options. It also redefines some of the options of the components.
# Create and pack two ThresholdScale megawidgets. mega1 = ThresholdScale() mega1.pack(side = 'left', padx = 10, pady = 10) mega2 = ThresholdScale( colors = ('green', 'yellow'), threshold = 75, value = 80, indicator_width = 32, scale_width = 25) mega2.pack(side = 'left', padx = 10, pady = 10)
The complete code for this example can be seen here.
These exercises build on the example presented so far.
mega1
so that the scale
widget displays the current value next to the slider. (You may
need to look at the Tk scale manual page to find which option to
the scale component to set.) You will be able to
do this without modifying the ThresholdScale class code.
_doCommand
method so that it
displays the current value of the scale in this label.
createlabel()
method in
the Pmw.MegaArchetype reference
manual and add labelpos and
labelmargin initialisation options which allow
the creation of a label for the megawidget.
An example of how these changes can be made can be seen here.
If you have completed a megawidget that may be useful to others, you may like to consider contributing it to Pmw. See Contributions welcome for how to contribute.
As a final note, the Pmw code makes an attempt to follow these coding conventions.
=
with spaces when used with keyword
parameters in function calls.
Pmw 1.3 - 7 Aug 2007 - Home
There are two aspects of Pmw, unrelated to megawidgets, that require special attention. Firstly, Pmw is made up of many sub-modules, potentially making access to its various classes and functions cumbersome for the user. Secondly, Pmw is regularly being modified and added to, thus requiring the release of new versions. Therefore, techniques for making access to the sub-modules easy and efficient and for dealing with the different versions have been developed. These techniques are incorporated into the dynamic loader which Pmw creates when it is first imported.
The first purpose of the loader is to give access to all Pmw classes
and functions through a single entry point, the Pmw. prefix. For
example, to access the ComboBox class (which resides in one of the
sub-modules of Pmw), you just have to use Pmw.ComboBox
. Without
the loader, this would be a more complicated reference, such as,
hypothetically, Pmw.PmwComboBox.ComboBox
.
The second purpose of the loader is to delay the importing of the sub-modules until they are needed. This improves the startup time of applications which only use a few Pmw megawidgets. It also allows more megawidgets to be added to the library without slowing down applications which do not use them.
The third purpose of the loader is to allow a script using Pmw to specify which version of Pmw it requires. This allows an application to continue working correctly even after newer releases of Pmw have been made which are not compatible with the version expected by the application. Several versions of Pmw can be installed at once, with the actual version used being specified by each application. In addition, the loader can be configured to search in one or more alpha versions of Pmw. These versions may contain new megawidgets, or new versions of existing megawidgets, that are currently not in the base releases.
Several functions are available to set and query the version of
Pmw being used. These are Pmw.setversion()
and
Pmw.setalphaversions()
which specify the version and alpha
versions (if any) to use for this session; Pmw.version()
which
returns the version(s) being used by this session; and
Pmw.installedversions()
which returns the version(s) of Pmw
currently installed. These are described in the
Pmw functions reference manual.
When Pmw is first imported, an instance of PmwLoader is created
and placed into sys.modules['Pmw']
. From that point on, any
reference to attributes of the Pmw 'module' is handled by the
loader. The real Pmw package is stored in sys.modules['_Pmw']
.
The loader searches the Pmw package base directory for
sub-directories with the prefixes Pmw_
and Alpha_
, which
contain Pmw base releases and alpha releases. The version numbers
are given by the part of the directory name following the prefix.
These versions are available for use and are those returned by the
Pmw.installedversions
function. The initial version is set to
the base release with the greatest version number. When the first
reference to a Pmw class or function is made, the loader reads the
files named Pmw.def in the current base version directory and
also in the alpha directories (if any). These files list all the
classes and functions supported by the version. Pmw attributes
are first searched for in the alpha directories and then in the
base version directory. The first directory which supports the
reference is used. In this way, alpha versions override base
versions.
The directory Alpha_99_9_example
contains a simple example of
how to structure an alpha version. The following code can be used
to request that the alpha version be used and then creates an
instance of a new megawidget defined in the alpha version.
import Pmw Pmw.setalphaversions('99.9.example') # Create a standard message dialog using the base Pmw version. ordinary = Pmw.MessageDialog( message_text = 'Ordinary\nPmw Dialog') # Create an example dialog using the alpha Pmw version. alpha = Pmw.AlphaExample()
Freezing Pmw
Since the dynamic loader requires that Pmw be installed at run
time, it can not be used when freezing Pmw. In this case, a
single module containing all Pmw code is required, which can then
be frozen with the rest of the application's modules. The
bundlepmw.py
script in the Pmw bin
directory can be used to
create such a file. This script concatenates (almost) all Pmw
megawidget files into a single file, Pmw.py
, which it writes to
the current directory. The script is called like this:
bundlepmw.py [-noblt] [-nocolor] /path/to/Pmw/Pmw_X_X_X/lib
The last argument should be the path to the lib
directory of the
required version of Pmw. By default, the Pmw.py
file imports
the PmwBlt
and PmwColor
modules and so, to freeze an
application using Pmw, you will need to copy the files PmwBlt.py
and PmwColor.py
to the application directory before freezing.
If you are sure that your application does not use any of the
Pmw.Blt
or Pmw.Color
functions, you can use the -noblt
or
-nocolor
options. In this case Pmw.py
will be modified so
that it does not import these module(s) and so will not need to be
included when freezing the application.
If your application only uses a few Pmw megawidgets, you can
remove the references to the usused ones in the files
list in
the bundlepmw.py
code. To make the change, take a copy of the
script and modify it. This will make the Pmw.py
file smaller.
However, be sure that you do not delete megawidgets that are
components or base classes of megawidgets that you use.
Pmw 1.3 - 7 Aug 2007 - Home
This document contains a brief guide to porting existing code between different versions of Pmw. It includes significant functionality changes but does not include bug fixes or compatible enhancements. For details of all changes, see Changes to Pmw versions.
*Porting from 1.2 to 1.3:
Bug fix, documention and new features only. No backwards-incompatible changes.
Porting from 0.8.5 to 1.0, 1.1 and 1.2
Bug fix, documention and new features only. No backwards-incompatible changes.
Porting from 0.8.4 to 0.8.5
Bug fix release only. No interface changes.
Porting from 0.8.3 to 0.8.4
Change the setnaturalpagesize()
method of Pmw.NoteBook to
setnaturalsize()
(to be consistent with Pmw.PanedWidget).
Change Pmw.excludefrombusycursor() to Pmw.setbusycursorattributes(). Replace busyCursorName option of Pmw.initialise() with cursorName attribute of Pmw.setbusycursorattributes().
Several rarely used key bindings for Pmw.ScrolledListBox were removed, changing the behaviour of the megawidget.
Porting from 0.8.1 to 0.8.3
The megawidgets Pmw.NoteBookR and Pmw.NoteBookS have been replaced by a new Pmw.NoteBook. The interfaces are not compatible, so see the Pmw.NoteBook reference manual for details.
Change the get() method of Pmw.OptionMenu to getcurselection() and the remove() method of Pmw.PanedWidget to delete().
If you use 'end', 'default' or None in calls to the index() method of several megawidgets, change these to Pmw.END, Pmw.DEFAULT and Pmw.SELECT, respectively.
The exclude argument has been removed from Pmw.showbusycursor(). Use Pmw.excludefrombusycursor() instead.
The names of some of the positional arguments in the following methods have changed: MegaArchetype.createcomponent(), ButtonBox.insert(), ButtonBox.add(), MenuBar.addcascademenu(), MenuBar.addmenuitem() and RadioSelect.add().
The Pmw.maxfontwidth() function has been removed. Use the
font_measure()
Tkinter method, or if that has not yet been
implemented:
someWidget.tk.call('font', 'measure', someFont, 'W')
The Pmw.fontexists() function has been removed. This is because, since Tk8.0, all fonts exist, so it no longer has any meaning.
Porting from 0.8 to 0.8.1
The Blt.Graph now supports blt2.4i which is not backwards compatible with blt2.1.
Porting from 0.7 to 0.8
The format argument of Pmw.datestringtojdn() now defaults to 'ymd'. If you want to display dates with year, month and day in a different order, add a format option to Pmw.datestringtojdn() or to the datatype option of Pmw.Counter or the validate option of Pmw.EntryField.
The justify() method from Pmw.ScrolledListBox has been removed. Use the xview() or yview() methods instead.
Replace the getFrame() method of Pmw.ScrolledFrame with the interior() method.
Replace the ringpadx and ringpady options of Pmw.Group by padding the megawidget itself or by padding the children of the megawidget.
Replace the canvasbind() and canvasunbind() methods of Pmw.Balloon with tagbind() and tagunbind().
The return value of Pmw.EntryField command callback is now ignored. Previously, if the callback destroyed the megawidget, it was required to return the string 'break', to work around a problem in the event handling mechanism in Tkinter. With python 1.5.2, Tkinter has been fixed. Therefore, user-supplied callback functions should use Pmw.hulldestroyed to check if the megawidget has been destroyed before performing any operations on it.
If you require the 'pmw1' fontScheme when running under Microsoft Windows and Macintosh, you will need to set the Tk font options manually.
Porting from 0.6 to 0.7
Replace the maxwidth option of Pmw.EntryField with the 'max' field of the validate option.
To specify that there should be no validation performed for a Pmw.EntryField, the validate option must be None, not '' as before.
The date and time values of the Pmw.EntryField validate option (such as 'date_dmy' and 'time24', etc) are no longer supported. Instead use a dictionary as the value of the validate option with 'date' or 'time' in the 'validator' field. Include other fields in the dictionary to further specify the validation.
Pmw.Counter no longer supports the old date and time values for the datatype option. Use a dictionary with a 'counter' field of 'date' or 'time' and other fields to further specify the counting.
Pmw.Counter no longer supports the min and max options. Use the Pmw.EntryField validate option instead.
The bbox method of Pmw.ScrolledListBox now refers to the bbox method of the listbox component, not the hull component.
By default, Pmw.MenuBar now automatically adds hotkeys to menus
and menu items for keyboard traversal. To turn this off, use the
hotkeys = 0
option.
The createcomponent() method now disallows the creation of component names containing an underscore. If any component names contain an underscore, rename them.
Porting from 0.5 to 0.6
To port applications using Pmw version 0.5 to version 0.6, make sure you are using python1.5. Then, simply change any lines in your application like this:
from PmwLazy import Pmw
to this:
import Pmw
Also, if you have added the lib
directory of a specific version
of Pmw to sys.path
or PYTHONPATH
, this can be removed, as long
as Pmw can now be found from the default path, such as in the
python site-packages
directory.
Porting from 0.2 to 0.4
To get Pmw.0.2 default fonts (helvetica with bold italic menus and italic scales) initialise with:
Pmw.initialise(fontScheme = 'pmw1')
If no fontScheme is given, the standard Tk default fonts are used.
Remove all calls to setdefaultresources(), usual(), keep(), renameoptions(), ignore() and defineoptiontypes().
Move call to defineoptions() to before call to base class constructor, create optiondefs tuple from self.defineoptions arguments, then call defineoptions().
Remove resource class and name from optiondefs.
The last element in the optiondefs tuple (callback function) must be given (may be None).
Add to classes currently without any options:
optiondefs = () self.defineoptions(kw, optiondefs)
Use createcomponent() to create components - this replaces the calls to the component widget constructor and to registercomponent().
Do not inherit from Pmw.LabeledWidget. Instead, replace with Pmw.MegaWidget with labelpos and labelmargin options and a call to self.createlabel(). If calling createlabel(), must replace pack() with grid().
When calling a megawidget constructor, include subcomponent name when setting subcomponent options (eg labeltext -> label_text)
The items option of ScrolledListBox is an initialisation option only - use setlist() method after initialisation.
The autorelief option for Counter, EntryField, ScrolledText, TextDialog has been removed.
ScrolledListBox.getcurselection() always returns a tuple of strings, possibly of zero length.
Counter increment is always initialised to 1.
The 'time' Counter datatype option has been replaced by 'timeN' and 'time24'.
The 'time' EntryField validate option has been replaced by 'timeN' and 'time24'.
Replace call to initialise() with initialiseoptions(), removing "kw" arg. This should always be the last line in a megawidget constructor.
Replace hide() with withdraw().
Now need iconpos option for MessageDialogs with icon_bitmap option set.
Example megawidget class definition:
class MyBigWidget(Pmw.MegaWidget): def __init__(self, parent = None, **kw): # Define the megawidget options. optiondefs = ( ('errorbackground', 'pink', None), ('maxwidth', 0, self._myfunc), ('myinit', 'good', Pmw.INITOPT), ) self.defineoptions(kw, optiondefs) # Initialise the base class (after defining the options). Pmw.MegaWidget.__init__(self, parent) # Create the components. interior = self.interior() self._widget = self.createcomponent('component', (('alias', 'component_alias'),), None, Tkinter.Button, (interior,)) self._widget.grid(column=0, row=0, sticky='nsew') self.createlabel(interior) # Initialise instance variables. self.deriveddummy = None # Check keywords and initialise options. self.initialiseoptions(MyBigWidget)
Pmw 1.3 - 7 Aug 2007 - Home
This document briefly describes the features of the Pmw megawidget
toolkit and how to use the megawidgets. Using examples, it
describes those features common to all Pmw megawidgets. For a
description of individual Pmw megawidgets see the
reference manuals.
For complete information on general Pmw megawidget functionality see the
Pmw.MegaArchetype reference manual.
For a lot more example code, run any of the files in the
Pmw demos
directory.
A simple example of a megawidget is a counter. This widget contains an entry field and two small arrow buttons. Users may enter a value directly into the entry field or they may use the buttons to increment and decrement the value displayed without having to use the keyboard. Having this and other megawidgets in your toolbox allows you to choose the best graphical interface for your application.
To run the examples in the tutorial, make sure that the
Pmw lib
directory is in sys.path
. You
should be able to cut and paste the examples into an interactive
python session, or you can copy them to a file and run the file with
python.
The following two lines should be entered before any of the
examples. These import and initialise Pmw.
For more information on Pmw.initialise()
see the
Pmw functions reference manual.
import Pmw root = Pmw.initialise()
If necessary, you can have more control over how Tkinter and Pmw are initialised by using this form of initialisation:
import Tkinter root = Tkinter.Tk() import Pmw Pmw.initialise(root)
Now that you have the formalities out of the way, you can create and pack a counter megawidget (see Pmw.Counter reference manual) using its default configuration like this:
counter1 = Pmw.Counter() counter1.pack(padx = 10, pady = 10)
Now enter a number and click on the arrow buttons to see the number increment or decrement. The result looks something like this:
The above example creates the counter as a child of the root window. If you want to create it as a child of another window (for example, a Tkinter.Frame widget called 'frame'), add the parent as an argument to the constructor:
counter1a = Pmw.Counter(frame)
Once a megawidget has been created, you can call any of its other methods in a similar way to Tk widgets. The following sets the value of the counter and then increments it:
counter1.setentry(41) counter1.increment()
Like any widget, a megawidget may have options to allow it to be configured for a particular use. Options allow the megawidget user to modify the appearance and behaviour of the megawidget. The counter megawidget has several such options. One of them, datatype, specifies how the counter should count up and down, such as, for example, by integers, reals, times or dates. The default value is 'numeric', which means the counter expects integers to be entered and will support incrementing and decrementing by whole numbers.
Another option is
increment, which specifies how many units should be
added or subtracted when the counter is incremented or decremented.
Using these options, you can create a time counter, supporting the
format HH:MM:SS, and counting in minutes, like
this (note also the call to the setentry
method to set
the contents of the entry field):
counter2 = Pmw.Counter( datatype = 'time', increment = 60) counter2.setentry('00:00:00') counter2.pack(padx = 10, pady = 10)
Many megawidget options can be modified using the
configure()
method. For example, you can change the
value of the increment option to 10 minutes like
this:
counter2.configure(increment = 60 * 10)
Some megawidget options can only be set when creating the megawidget.
These options can not be set by calling the configure()
method, but they can be queried in all the usual ways. For example,
the counter has an orient initialisation option
which specifies whether the arrow buttons should appear to the
left and right of the entry field ('horizontal')
or above and below ('vertical'). You can create a
numeric counter with arrow buttons above and below the entry
field like this:
counter3 = Pmw.Counter(orient = 'vertical') counter3.pack(padx = 10, pady = 10)
You can query the value of megawidget options (initialisation or not) in similar ways as for normal Tkinter widgets. For example, the following code prints the values of some of the counter options.
print counter3.cget('increment') --> 1 print counter3.configure('orient') --> ('orient', 'orient', 'Orient', 'horizontal', 'vertical')
When a Tk widget option is queried, its value is always
returned as a string, regardless of the type used when setting the
option. However, when a Pmw megawidget option is queried, a
reference to the object used when setting the option is returned.
In other words it is not always a string. For example, the type
returned by cget('increment')
above was integer.
Megawidgets are made up of other widgets, which we call
components. Each component is known by a logical name and
may be either a simple Tk widget, or may itself be a megawidget.
Pmw gives the megawidget user access to not only the functionality
supported directly by the megawidget through its options and methods,
but also to the components of the megawidget and their options and
methods. To access a component directly, use the
component()
method. For example, to call method
doit of component comp
of megawidget mega:
mega.component('comp').doit()
There is a short-hand way to access the options of components, by using the notation component_option. This allows, for example, a counter megawidget to be configured with different colored backgrounds for each of its arrow button components (these components are called downarrow and uparrow):
counter2.configure( downarrow_background = 'green', uparrow_background = 'red')
All megawidgets are enclosed in a containing widget which is created automatically by the Pmw base classes. For normal megawidgets the container is a Tkinter Frame widget. For megawidgets which are toplevel windows, the container is a Tkinter Toplevel widget. The containing widget is accessible as the hull component.
To access options of the containing widget use the form hull_option. For example to create a counter megawidget with a wide sunken border around it:
counter4 = Pmw.Counter( hull_relief = 'sunken', hull_borderwidth = 5 )
Some megawidgets, such as Dialog and LabeledWidget, also have a
frame into which users can pack other widgets. This frame may be a
component but can also be accessed with the interior()
method. For the Pmw.MegaToplevel and Pmw.MegaWidget classes, the
interior widget is the same as the hull widget. For other
megawidgets, the hull is the outer, containing widget and the
interior is the empty frame which can be used to extend the
megawidget by including extra internal widgets.
Components may themselves be megawidgets and so their (sub-)components can be referred to using the notation component_sub-component. For example, the entryfield component of the counter is a Pmw.EntryField megawidget (which handles the input validation). In turn, this has a Tkinter.Entry component named entry. Therefore, you can change the background of the counter's Tkinter.Entry widget with:
counter2.configure(entryfield_entry_background = 'yellow')
Most component path names (like entryfield_entry) have a shorter alias defined for them. In this case, you can use the equivalent:
counter2.configure(entry_background = 'yellow')
Each megawidget component is an instance of some python class. The default class of each component is given in the reference manual. By using the special pyclass component option, you can specify a different python class to use when creating the component. For example, to create a Pmw.Counter megawidget which has a Tkinter.Button as its label, rather than the default Tkinter.Label:
counter5 = Pmw.Counter( labelpos = 'w', label_text = 'Hello', label_pyclass = Tkinter.Button )
Since a Pmw megawidget is a normal python class, it both inherits methods from its base classes and also may have other methods defined for it in the usual way. Pmw also supports a third way that a megawidget may gain methods - by 'forwarding' methods to one or more of its subwidgets. This is also known as 'delegating'. For example, a Pmw.Counter megawidget delegates the methods related to its Pmw.EntryField component, entryfield, to the component. It does not have to explicitely define methods which call the component methods. This is why we can call counter2.setentry() - since setentry() is a method of the Pmw.EntryField component, it is available to the Pmw.Counter.
Methods already defined by a class or its base classes take precedence over delegated methods. For example, Pmw.Counter inherits a cget method from Pmw.MegaArchetype. Therefore, this method is not delegated to the cget method of Pmw.EntryField.
There are several ways of extending Pmw megawidgets. Firstly, the flexibility of the options and components allows the widget's appearance and behaviour to be greatly modified. Secondly, widgets of the user's choice can be added inside some megawidgets by using the interior() method. The Pmw classes MegaToplevel, MegaWidget, Dialog and LabeledWidget are particularly designed to be extended in this way. For example, to create a dialog window containing a counter:
dialog = Pmw.Dialog( title = 'Counter dialog', buttons = ('OK', 'Cancel')) interior = dialog.interior() counter = Pmw.Counter(interior) counter.pack(padx = 20, pady = 20)
A third way to extend megawidgets is to inherit from (or subclass)
them. See How to build Pmw
megawidgets for information on how to use inheritance to extend
a megawidget by adding new options. For simpler cases, where new
methods are to be added to an existing megawidget and/or the default
values for some options are to be changed, normal subclassing can be
used. For example, to create new classes based on a Pmw.Counter,
one with a new method getminutes()
and one with a
default datatype of 'time' and a white entry background:
class MinuteCounter1(Pmw.Counter): def getminutes(self): return Pmw.timestringtoseconds(self.getvalue()) / 60 class MinuteCounter2(Pmw.Counter): def __init__(self, parent = None, **kw): kw['datatype'] = 'time' kw['entry_background'] = 'white' kw['entryfield_value'] = '00:00:00' kw['increment'] = 60 apply(Pmw.Counter.__init__, (self, parent), kw)
The following code is a small example of how to use Pmw megawidgets. It is a complete program which displays three ways for the user to enter a value - using an up-down counter, an entry field with validation and a dropdown combobox.
import Pmw root = Pmw.initialise(fontScheme = 'pmw1') counter = Pmw.Counter( label_text = 'Counter:', labelpos = 'w', entryfield_value = '00:00:00', entryfield_validate = 'time', datatype='time', increment=5*60, ) counter.pack(fill = 'x', padx = 10, pady = 10) entry = Pmw.EntryField( label_text = 'Real entry:', labelpos = 'w', value = '+2.9979e+8', validate = 'real', ) entry.pack(fill = 'x', padx = 10, pady = 10) combo = Pmw.ComboBox( label_text = 'ComboBox:', labelpos = 'w', scrolledlist_items = map(str, range(20)) ) combo.pack(fill = 'x', padx = 10, pady = 10) # Make the labels line up neatly Pmw.alignlabels((counter, entry, combo)) root.title('Pmw megawidgets example') root.mainloop()
The following also shows how to use Pmw megawidgets. It displays a RadioSelect megawidget and an exit button packed into the root window.
import Tkinter import Pmw def callback(tag): # This is called whenever the user clicks on a # button in the RadioSelect widget. print tag, 'was pressed.' # Initialise Tkinter and Pmw. root = Pmw.initialise(fontScheme = 'pmw1') root.title('Pmw RadioSelect demonstration') # Create and pack a RadioSelect widget. radio = Pmw.RadioSelect( command = callback, labelpos = 'w', label_text = 'Food group:') radio.pack(padx = 20, pady = 20) # Add some buttons to the RadioSelect. for text in ('Fruit', 'Vegetables', 'Cereals', 'Legumes'): radio.add(text) radio.invoke('Vegetables') # Create an exit button. exit = Tkinter.Button(text = 'Exit', command = root.destroy) exit.pack(pady = 20) # Let's go. root.mainloop()
There are several ways to use the Tk option database to customise a Pmw application. Firstly you can customise all the basic Tk widgets in the usual way. For example, to set the background of all Tkinter.Label widgets (whether a megawidget component or not):
root.option_add('*Label.background', 'pink')
To set the background of all Pmw.EntryField label components:
root.option_add('*EntryField.Label.background', 'green')
To set the background of all Pmw.EntryField components, including the hull component:
root.option_add('*EntryField*background', 'blue')
The above option settings affect basic Tk widgets and, since it is
built into the Tk widgets, this functionality is always available.
However, to be able to use the Tk option database to set the default
values for Pmw megawidget options, Pmw.initialise()
must be called with useTkOptionDb = 1
. If this is not
done, Pmw does not query the Tk option database for megawidget
option defaults. This is the default behaviour because there is a
slight performance penalty for using the Tk option database.
Assuming useTkOptionDb
has been set, the default
buttonbox position of all Pmw.Dialog megawidgets can be changed
with:
root.option_add('*Dialog.buttonboxpos', 'e')
To set the label position of all Pmw.EntryField megawidgets, thus giving them a label component by default:
root.option_add('*EntryField.labelpos', 'w')
Pmw 1.3 - 7 Aug 2007 - Home