Hi, On Mon, 21 Apr 2014 16:26:26 +0100 (BST) ALAN GAULD <alan.ga...@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 _______________________________________________ Tkinter-discuss mailing list Tkinter-discuss@python.org https://mail.python.org/mailman/listinfo/tkinter-discuss