[Tkinter-discuss] Tix Grid question, was: Re: Is this the right place for Tix questions?
Michael Lange
klappnase at web.de
Tue Apr 22 12:35:39 CEST 2014
Hi,
On Mon, 21 Apr 2014 16:26:26 +0100 (BST)
ALAN GAULD <alan.gauld at btinternet.com> wrote:
(...)
> The Tcl version works fine but the Python version gives an error
> although it does display but without any grid/border formatting. The
> error I get is:
>
> Exception in Tkinter callback
> Traceback (most recent call last):
> File "/usr/lib/python3.2/tkinter/__init__.py", line 1402, in __call__
> return self.func(*args)
> File "tixgrid-test.py", line 10, in simpleFormat
> grd.format('grid', x1,y1,x2,y2, anchor='se', fill=0,
> relief='raised', File "/usr/lib/python3.2/tkinter/tix.py", line 341, in
> __getattr__ raise AttributeError(name)
> AttributeError: format
(...)
A couple of years ago I have been playing around with this.
IIRC some of the tixGrid's method are not implemented in the Python
wrapper, probably because they are (were?) not documented in the
tixGrid man page. According to
http://tix.sourceforge.net/man/html/TixCmd/tixGrid.htm#M32
this is still the case for the format, index, selection and a number
of other commands. Back then I wrote myself a custom Tix module with the
missing Grid methods included, as far as I remember it served me well.
I'll copy'n'paste my custom Grid class below, in case you have a use for
it (but of course without warranty ;)
Regards
Michael
###############################################################
class Grid(TixWidget):
'''The Tix Grid command creates a new window and makes it into a
tixGrid widget. Additional options, may be specified on the command
line or in the option database to configure aspects such as its cursor
and relief.
A Grid widget displays its contents in a two dimensional grid of cells.
Each cell may contain one Tix display item, which may be in text,
graphics or other formats. See the DisplayStyle class for more information
about Tix display items. Individual cells, or groups of cells, can be
formatted with a wide range of attributes, such as its color, relief and
border.
Subwidgets - None
STANDARD OPTIONS
background borderwidth cursor font foreground height
highlightbackground highlightcolor highlightthickness padx pady
relief selectbackground selectborderwidth selectforeground
state takefocus width xscrollcommand yscrollcommand
WIDGET-SPECIFIC OPTIONS
editdonecmd - If non-empty, gives a Tcl command to be executed when the user
has edited a grid cell. When this command is called, it is passed
with two additional parameters: column, row, where (column, row) is the location
of the cell that has just been edited.
editnotifycmd - If non-empty, gives a Tcl command to be executed when the user
tries to edit a grid cell. When this command is called, it is
passed with two additional parameters: column, row, where (column, row) is the
location of the cell. This command should return a boolean
value: true indicates that the cell is editable and false oth-
erwise.
floatingcols - ??? Requires a boolean. The default value is 0. ???
floatingrows - ??? Requires a boolean. The default value is 0. ???
formatcmd - If non-empty, gives a Tcl command to be executed when the grid
cells need to be formatted on the screen. Normally, this command
calls the format() widget command (see below). When this command
is called, it is passed with five additional parameters: type x1
y1 x2 y2. type gives the logical type of the region in the grid.
It may be one of the following. "x-region": the horizontal margin (as defined with topmargin);
"y-region": the vertical margin (as defined with leftmargin); "s-region", the area where the
horizontal and vertical margins are joined; "main": all the cells
that do not fall into the above three types. x1 y1 x2 y2 gives
the extent of the region that needs formatting.
itemtype - ??? the default type of newly created grid cell items; may be "text" or "image";
default is "text" ???
leftmargin - In the number of cells, gives the width of vertical margin. A
zero indicates that no vertical should be drawn (default: 1).
Defines the number of columns that are fixed when the widget is horizontally
scrolled. These column(s) can be used as label(s) for the row(s).
selectmode - Specifies one of several styles for manipulating the selection.
The value of the option may be arbitrary, but the default bind-
ings expect it to be either single, browse, multiple, or
extended; the default value is single.
selectunit - Specifies the selection unit. Valid values are "cell", "column" or "row".
sizecmd - ??? A command that is called whenever a grid cell is resized ???
topmargin - In the number of cells, gives the height of horizontal margin. A
zero indicates that no horizontal should be drawn (default: 1).
Defines the number of rows that are fixed when the widget is vertically scrolled.
These row(s) can be used as label(s) for the column(s).
'''
def __init__(self, master, cnf={}, **kw):
TixWidget.__init__(self, master, 'tixGrid', ['options'], cnf, kw)
def anchor_clear(self):
'''Clears the selection anchor.'''
self.tk.call(self._w, 'anchor', 'clear')
def anchor_get(self):
'''Return a tuple of the form (column, row) describing the cell that is the current selection anchor.'''
return self._getints(self.tk.call(self._w, 'anchor', 'get'))
def anchor_set(self, column, row):
'''Set the selection anchor to the cell at (column, row).'''
self.tk.call(self._w, 'anchor', 'set', column, row)
def bdtype(self, x, y, xbdWidth=None, ybdWidth=None):
'''?????'''
# FIXME
# what is this for?
return self.tk.call(self._w, 'bdtype', x, y, xbdWidth, ybdWidth)
def delete_column(self, from_, to=None):
'''If TO is not given, deletes a single
column at the position FROM. If TO is given, deletes
the range of columns from position FROM through TO.'''
self.tk.call(self._w, 'delete', 'column', from_, to)
def delete_row(self, from_, to=None):
'''If TO is not given, deletes a single
row at the position FROM. If TO is given, deletes
the range of rows from position FROM through TO.'''
self.tk.call(self._w, 'delete', 'row', from_, to)
# FIXME: dragsite and dropsite are not documented, but they seem to do at least *something*
def dragsite_clear(self):
self.tk.call(self._w, 'dragsite', 'clear')
def dragsite_get(self):
return self._getints(self.tk.call(self._w, 'dragsite', 'get'))
def dragsite_set(self, x, y):
self.tk.call(self._w, 'dragsite', 'set', x, y)
def dropsite_clear(self):
self.tk.call(self._w, 'dropsite', 'clear')
def dropsite_get(self):
return self._getints(self.tk.call(self._w, 'dropsite', 'get'))
def dropsite_set(self, x, y):
self.tk.call(self._w, 'dropsite', 'set', x, y)
def edit_apply(self):
'''If any cell is being edited, de-highlight the cell and applies
the changes.'''
self.tk.call(self._w, 'edit', 'apply')
def edit_set(self, column, row):
'''Highlights the cell at (column, row) for editing, if the -editnotify
command returns True for this cell.'''
self.tk.call(self._w, 'edit', 'set', column, row)
def entrycget(self, column, row, option):
'''Returns the current value of the configuration option given by
OPTION of the cell at (column, row). OPTION may have any of the values
accepted by the set() widget command.'''
return self.tk.call(self._w, 'entrycget', column, row, '-'+option)
def entryconfigure(self, column, row, cnf=None, **kw):
'''Query or modify the configuration options of the cell at (x,y).
If no option is specified, returns a list describing all of the
available options for the cell (see Tk_ConfigureInfo(n) for
information on the format of this list.) If option is specified
with no value, then the command returns a list describing the
one named option (this list will be identical to the correspond-
ing sublist of the value returned if no option is specified.) If
one or more option-value pairs are specified, then the command
modifies the given widget option(s) to have the given value(s);
in this case the command returns an empty string. Option may
have any of the values accepted by the set() widget command.'''
return self._configure(('entryconfigure', column, row), cnf, kw)
entryconfig = entryconfigure
def format_border(self, col0, row0, col1, row1, **kw):
'''The format_border() method can only be called by the formatcmd callback of the widget.
Formats the border of the grid cells from (col0, row0) through (col1, row1).
Possible options are:
filled - boolean
xon - boolean
xoff - boolean
yon - boolean
yoff - boolean
relief, bg, bd, selectbackground etc. ???'''
self.tk.call(self._w, 'format', 'border', col0, row0, col1, row1, *self._options({}, kw))
def format_grid(self, col0, row0, col1, row1, **kw):
'''The format_grid() method can only be called by the formatcmd callback of the widget.
Formats the grid cells from (col0, row0) through (col1, row1).
Possible options are:
bordercolor - color
filled - boolean
xon - boolean
xoff - boolean
yon - boolean
yoff - boolean
bg, selectbackground, anchor etc ????'''
self.tk.call(self._w, 'format', 'grid', col0, row0, col1, row1, *self._options({}, kw))
# FIXME: geometryinfo is not documented, and though it seems to work I cannot
# find the use of this command
def geometryinfo(self, width=None, height=None):
'''?????'''
# has this really to be done like this?
return tuple([self._getdoubles(x) for x in self.tk.split(self.tk.call(self._w, 'geometryinfo', width, height))])
def index(self, column, row):
'''Return a tuple of the form (column, row) describing the grid cell at index (column, row).
COLUMN and ROW may be "max" (i.e. the last defined column resp. row) or "end" (i.e. max + 1). (???)'''
# FIXME
# COLUMN or ROW may be "end" or "max" instead of a numerical index; is this all of this method's use?
return self._getints(self.tk.call(self._w, 'index', column, row))
# FIXME: info is not documented, maybe because info_bbox() does not seem to have any effect
# info_exists seems to work well
def info_bbox(self, column, row):
'''???'''
return self._getints(self.tk.call(self._w, 'info', 'bbox', column, row))
def info_exists(self, column, row):
'''Returns True if the cell at COLUMN and ROW exists, else returns False.'''
return self._getboolean(self.tk.call(self._w, 'info', 'exists', column, row))
def move_column(self, from_, to, offset):
'''Moves the the range of columns
from position FROM through TO by the distance indicated by OFFSET.
For example, move_column(2, 4, 1) moves the columns 2,3,4 to columns 3,4,5.'''
self.tk.call(self._w, 'move', 'column', from_, to, offset)
def move_row(self, from_, to, offset):
'''Moves the the range of rows
from position FROM through TO by the distance indicated by OFFSET.
For example, move_row(2, 4, 1) moves the rows 2,3,4 to rows 3,4,5.'''
self.tk.call(self._w, 'move', 'row', from_, to, offset)
# FIXME: this is not documented, but seems to work
def nearest(self, x, y):
'''Returns a tuple of the form (column, row) describing the grid cell
nearest to window coordinates x and y.'''
return self._getints(self.tk.call(self._w, 'nearest', x, y))
# FIXME: selection methods are not documented in the man page
# maybe this is because only adjust, set and toggle (and partially clear) seem to work
def selection_adjust(self, col0, row0, col1=None, row1=None):
'''Removes the selection from all grid cells and adds the cell at (col0, row0) to the selection;
if col1 and row1 are given, adds the range of cells from (col0, row0) through (col1, row1) to the selection.'''
self.tk.call(self._w, 'selection', 'adjust', col0, row0, col1, row1)
select_adjust = selection_adjust
def selection_clear(self, col0=0, row0=0, col1='max', row1='max'):
# this seems to work only with selection_clear(0, 0, 'max', 'max'),
# which removes any selection
'''Removes the selection from all grid cells.'''
self.tk.call(self._w, 'select', 'clear', col0, row0, col1, row1)
select_clear = selection_clear
def selection_includes(self, column, row):
# this does not seem to have any effect
'''???Returns True if the grid cell at (column, row) is currently selected,
else returns False.??? (I guess it should).'''
return self._getboolean(self.tk.call(self._w, 'selection', 'includes', column, row))
select_includes = selection_includes
def selection_set(self, col0, row0, col1=None, row1=None):
'''Adds the cell at (col0, row0) to the selection; if col1 and row1 are given,
adds the range of cells from (col0, row0) through (col1, row1) to the selection.'''
self.tk.call(self._w, 'selection', 'set', col0, row0, col1, row1)
select_set = selection_set
def selection_toggle(self, col0, row0, col1=None, row1=None):
'''Changes the state of selection for the cell at (col0, row0); if col1 and row1 are given,
changes the state of selection for the range of cells from (col0, row0) through (col1, row1).'''
self.tk.call(self._w, 'selection', 'toggle', col0, row0, col1, row1)
select_toggle = selection_toggle
def set(self, column, row, **kw):
'''Creates a new display item at the cell at (column, row). The optional
-itemtype parameter gives the type of the display item ("text" or "image" ???). An addi-
tional list of option-value pairs specify options of the display
item. If a display item already exists at this cell, the old
item will be deleted automatically.
Possible options for text items are:
text, style, underline
Possible options for image items are:
image, style.'''
self.tk.call(self._w, 'set', column, row, *self._options({}, kw))
def size_column(self, index, **kw):
'''Queries or sets the size of the column given by
INDEX. INDEX may be any non-negative
integer that gives the position of a given column.
INDEX can also be the string "default"; in this case, this command
queries or sets the default size of all columns.
When no option-value pair is given, this command returns a tuple con-
taining the current size setting of the given column. When
option-value pairs are given, the corresponding options of the size
setting of the given column are changed. Options may be one of the foll-
wing:
pad0 pixels
Specifies the paddings to the left of a column.
pad1 pixels
Specifies the paddings to the right of a column.
size val
Specifies the width of a column .
Val may be: "auto" -- the width of the column is set the
the widest cell in the column; a valid Tk screen distance
unit (see Tk_GetPixels(n)); or a real number following by
the word chars (e.g. 3.4chars) that sets the width of the
column to the given number of characters.'''
return self.tk.split(self.tk.call(self._w, 'size', 'column', index, *self._options({}, kw)))
def size_row(self, index, **kw):
'''Queries or sets the size of the row given by
INDEX. INDEX may be any non-negative
integer that gives the position of a given row .
INDEX can also be the string "default"; in this case, this command
queries or sets the default size of all rows.
When no option-value pair is given, this command returns a list con-
taining the current size setting of the given row . When
option-value pairs are given, the corresponding options of the size
setting of the given row are changed. Options may be one of the foll-
wing:
pad0 pixels
Specifies the paddings to the top of a row.
pad1 pixels
Specifies the paddings to the the bottom of a row.
size val
Specifies the height of a row.
Val may be: "auto" -- the height of the row is set the
the highest cell in the row; a valid Tk screen distance
unit (see Tk_GetPixels(n)); or a real number following by
the word chars (e.g. 3.4chars) that sets the height of the
row to the given number of characters.'''
return self.tk.split(self.tk.call(self._w, 'size', 'row', index, *self._options({}, kw)))
# FIXME: sort is not documented, but the the widget accepts the command
# and it seems to work at least for the most part
def sort_column(self, first, last, **kw):
'''Sorts columns in the range from FIRST through LAST, according to the given options.
Possible options are:
command : a tcl command that accepts two items as arguments, compares these and returns a proper boolean value.
key : the index of the row to compare the items' values from.
order : must be "increasing" or "decreasing".
type : must be "ascii", "integer" or "real".'''
self.tk.call(self._w, 'sort', 'column', first, last, *self._options({}, kw))
def sort_row(self, first, last, **kw):
'''Sorts rows in the range from FIRST through LAST, according to the given options.
Possible options are:
command : a tcl command that accepts two items as arguments, compares these and returns a proper boolean value.
key : the index of the column to compare the items' values from.
order : must be "increasing" or "decreasing".
type : must be "ascii", "integer" or "real".'''
self.tk.call(self._w, 'sort', 'row', first, last, *self._options({}, kw))
def unset(self, column, row):
'''Clears the cell at (column, row) by removing its display item.'''
self.tk.call(self._w, 'unset', column, row)
def xview(self, *what):
"""Query and change horizontal position of the view."""
if not what:
return self._getdoubles(self.tk.call(self._w, 'xview'))
self.tk.call((self._w, 'xview') + what)
def xview_moveto(self, fraction):
"""Adjust the view in the window so that FRACTION of the
total width of the entry is off-screen to the left."""
self.tk.call(self._w, 'xview', 'moveto', fraction)
def xview_scroll(self, number, what):
"""Shift the x-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
self.tk.call(self._w, 'xview', 'scroll', number, what)
def yview(self, *what):
"""Query and change vertical position of the view."""
if not what:
return self._getdoubles(self.tk.call(self._w, 'yview'))
self.tk.call((self._w, 'yview') + what)
def yview_moveto(self, fraction):
"""Adjust the view in the window so that FRACTION of the
total width of the entry is off-screen to the top."""
self.tk.call(self._w, 'yview', 'moveto', fraction)
def yview_scroll(self, number, what):
"""Shift the y-view according to NUMBER which is measured in "units" or "pages" (WHAT)."""
self.tk.call(self._w, 'yview', 'scroll', number, what)
class _dummyGrid(Grid, TixSubWidget):
def __init__(self, master, name, destroy_physically=1):
TixSubWidget.__init__(self, master, name, destroy_physically)
class ScrolledGrid(TixWidget):
'''Scrolled Grid widgets'''
# FIXME: It should inherit -superclass tixScrolledWidget
def __init__(self, master, cnf={}, **kw):
TixWidget.__init__(self, master, 'tixScrolledGrid', ['options'], cnf, kw)
self.subwidget_list['grid'] = _dummyGrid(self, 'grid')
self.subwidget_list['vsb'] = _dummyScrollbar(self, 'vsb')
self.subwidget_list['hsb'] = _dummyScrollbar(self, 'hsb')
# we cannot use the self.grid shortcut to access the Grid subwidget here
# because it conflicts with the grid() geometry method, so add a grid_ attribute as a replacement
self.grid_ = self.subwidget('grid')
###############################################################
.-.. .. ...- . .-.. --- -. --. .- -. -.. .--. .-. --- ... .--. . .-.
Vulcans do not approve of violence.
-- Spock, "Journey to Babel", stardate 3842.4
More information about the Tkinter-discuss
mailing list