wx.gizmos.TreeListCtrl problem reading edited cells

I am using wx.gizmos.TreeListCtrl on Windows Vista. I hand-edit a cell
in one of the list columns, finishing the edit by hitting the enter
key. I have a handler bound to the wx.EVT_TREE_END_LABEL_EDIT event,
which occurs at the end of editing the cell. The handler can read the
new value of the edited cell by calling evt.GetLabel(), which is nice,
except that there is apparently no way to determine which column, i.e.
which cell was edited. OK, so there aren't that many columns, so I just
read all the cells in the row using tree.GetItemText(item,
column_number). I do this after getting item either by calling
evt.GetItem() or tree.GetCurrentItem() in the handler.

The real problem is that GetItemText() returns the value in the cell
from BEFORE the edit (clearly a bug). If I edit the cell again, then it
returns the value before the second edit, which is the value after the
first edit. So the handler can get the value of the cell from the
previous edit, but not from the latest edit.

So you can determine the new value but not the cell which was edited;
but you can't read the new contents of the edited cell either.

I tried wx.agw.HyperListCtrl, which is a reimplementation of
TreeListCtrl and got the same behavior.

Is there another way to read the newly edited cell, which works? Is
there a way to determine which cell (column) was actually edited?

A minimal sample program is attached. Assistance will be appreciated.

-gt

treelisttest_minimal.py (2.15 KB)

Hi,

2009/9/13 Glenn Thobe:

I am using wx.gizmos.TreeListCtrl on Windows Vista. I hand-edit a cell
in one of the list columns, finishing the edit by hitting the enter
key. I have a handler bound to the wx.EVT_TREE_END_LABEL_EDIT event,
which occurs at the end of editing the cell. The handler can read the
new value of the edited cell by calling evt.GetLabel(), which is nice,
except that there is apparently no way to determine which column, i.e.
which cell was edited. OK, so there aren't that many columns, so I just
read all the cells in the row using tree.GetItemText(item,
column_number). I do this after getting item either by calling
evt.GetItem() or tree.GetCurrentItem() in the handler.

The real problem is that GetItemText() returns the value in the cell
from BEFORE the edit (clearly a bug). If I edit the cell again, then it
returns the value before the second edit, which is the value after the
first edit. So the handler can get the value of the cell from the
previous edit, but not from the latest edit.

So you can determine the new value but not the cell which was edited;
but you can't read the new contents of the edited cell either.

I tried wx.agw.HyperListCtrl, which is a reimplementation of
TreeListCtrl and got the same behavior.

I can't say anything about TreeListCtrl, but if you use the SVN
version of HyperTreeList, few weeks ago I added a "column" attribute
to the TextCtrl which gets created every time you edit an item. The
issue about the new content of the cell can be worked around by using
wx.CallAfter inside the OnEndLabelEdit method. The attached script
demonstrates the solution to both problems, simply adjust the import
path for wx.lib.agw.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

treelisttest_minimal.py (2.17 KB)

Andrea Gavana wrote:


Hi,
2009/9/13 Glenn Thobe:

I am using wx.gizmos.TreeListCtrl on Windows Vista.  I hand-edit a cell
in one of the list columns, finishing the edit by hitting the enter
key.  I have a handler bound to the wx.EVT_TREE_END_LABEL_EDIT event,
which occurs at the end of editing the cell.  The handler can read the
new value of the edited cell by calling evt.GetLabel(), which is nice,
except that there is apparently no way to determine which column, i.e.
which cell was edited.  OK, so there aren't that many columns, so I just
read all the cells in the row using tree.GetItemText(item,
column_number).  I do this after getting item either by calling
evt.GetItem() or tree.GetCurrentItem() in the handler.
The real problem is that GetItemText() returns the value in the cell
from BEFORE the edit (clearly a bug).  If I edit the cell again, then it
returns the value before the second edit, which is the value after the
first edit.  So the handler can get the value of the cell from the
previous edit, but not from the latest edit.
So you can determine the new value but not the cell which was edited;
but you can't read the new contents of the edited cell either.
I tried wx.agw.HyperListCtrl, which is a reimplementation of
TreeListCtrl and got the same behavior.

I can't say anything about TreeListCtrl, but if you use the SVN
version of HyperTreeList, few weeks ago I added a "column" attribute
to the TextCtrl which gets created every time you edit an item. The
issue about the new content of the cell can be worked around by using
wx.CallAfter inside the OnEndLabelEdit method. The attached script
demonstrates the solution to both problems, simply adjust the import
path for wx.lib.agw.
Andrea.
"Imagination Is The Only Weapon In The War Against Reality."

Hi,

2009/9/13 Glenn Thobe:

I am using wx.gizmos.TreeListCtrl on Windows Vista. I
hand-edit a cell
in one of the list columns, finishing the edit by hitting the
enter
key. I have a handler bound to the
wx.EVT_TREE_END_LABEL_EDIT event,
which occurs at the end of editing the cell. The handler can
read the
new value of the edited cell by calling evt.GetLabel(), which
is nice,
except that there is apparently no way to determine which
column, i.e.
which cell was edited. OK, so there aren’t that many
columns, so I just
read all the cells in the row using tree.GetItemText(item,
column_number). I do this after getting item either by
calling
evt.GetItem() or tree.GetCurrentItem() in the handler.
The real problem is that GetItemText() returns the value in
the cell
from BEFORE the edit (clearly a bug). If I edit the cell
again, then it
returns the value before the second edit, which is the value
after the
first edit. So the handler can get the value of the cell
from the
previous edit, but not from the latest edit.
So you can determine the new value but not the cell which was
edited;
but you can’t read the new contents of the edited cell either.
I tried wx.agw.HyperListCtrl, which is a reimplementation of
TreeListCtrl and got the same behavior.
I can’t say anything about TreeListCtrl, but if you use the SVN
version of HyperTreeList, few weeks ago I added a “column”
attribute
to the TextCtrl which gets created every time you edit an item. The
issue about the new content of the cell can be worked around by
using
wx.CallAfter inside the OnEndLabelEdit method. The attached script
demonstrates the solution to both problems, simply adjust the
import
path for wx.lib.agw.
Andrea.
“Imagination Is The Only Weapon In The War Against
Reality.”
treelisttest_minimal.py
2KViewDownload
Thanks to Andrea Gavana for the most helpful information, which worked
like a charm. There are some additional features of the HyperTreeList,
which I would like to use. I figured out how to do some things, but am
having difficulty doing others. The setup is Python 2.6.2, wxPython
2.8.10.1, and HyperTreeList.py Revision 61618 of 05 Aug 2009 on Windows
Vista.
The wxPython demo for HyperTreeList shows examples of a check box being
attached to a tree item, but none involving a list item. The check box
is attached by means of the keyword argument ct_type=1 in the method
call tree.AppendItem or tree.AddRoot, which is the constructor for the
tree item in question. • Is it possible to create the tree item and attached check box in
separate steps?
• How does one programmatically set the state of the check box?
One detects a change in the state of the check box after the user
clicks on it, by binding a handler to the event
wx.lib.agw.hypertreelist.EVT_TREE_ITEM_CHECKED. The state is then
determined by state=evt.GetItem().GetCurrentCheckedImage().
Perversely, a 0 is returned if the box is checked and a 1 is returned
if it is not.
• Is this the preferred way to read the check box state?
• A bug shows up when editing a list item in the same row as the
checkbox. Selecting the cell to be edited causes a second copy of it
to appear shifted to the right of the original and with a box drawn
around it.
• Is it possible for the list columns to contain checkboxes, choice
boxes, etc. instead of merely text controls? If so, how? According to
the documentation: “Whatever non-toplevel widget can be attached next
to a list item.” Also, how does one initialize check boxes, detect
changes, and read the state for list items?
• The method wx.gizmos.TreeListCtrl.GetCurrentItem() has no
counterpart in HyperTreeList.
• Can a list item be a Choice box?
An updated sample program is attached.
Thanks for any additional help.
-gt

treelisttest_minimal_3.py (2.89 KB)

···

http://xoomer.alice.it/infinity77/http://thedoomedcity.blogspot.com/andrea.gav...@gmail.com

http://xoomer.alice.it/infinity77/http://thedoomedcity.blogspot.com/

Hi Glenn,

2009/9/17 Glenn Thobe:

Thanks to Andrea Gavana for the most helpful information, which worked like
a charm. There are some additional features of the HyperTreeList, which I
would like to use. I figured out how to do some things, but am having
difficulty doing others. The setup is Python 2.6.2, wxPython 2.8.10.1, and
HyperTreeList.py Revision 61618 of 05 Aug 2009 on Windows Vista.

The wxPython demo for HyperTreeList shows examples of a check box being
attached to a tree item, but none involving a list item. The check box is
attached by means of the keyword argument ct_type=1 in the method call
tree.AppendItem or tree.AddRoot, which is the constructor for the tree item
in question.

• Is it possible to create the tree item and attached check box in
separate steps?

Yes, it will be possible when I will be able to commit a small change
I made right now to HyperTreeList and CustomTreeCtrl. At the moment
SVN looks down (or I am unable to connect), but basically you will be
able to do this:

self.tree.SetItemType(item, ct_type)

Where ct_type is either 0 (normal item), 1 (checkbox) or 2 (radiobutton)

• How does one programmatically set the state of the check box?

Use self.tree.CheckItem2(item, check_status)

One detects a change in the state of the check box after the user clicks on
it, by binding a handler to the event
wx.lib.agw.hypertreelist.EVT_TREE_ITEM_CHECKED. The state is then
determined by state=evt.GetItem().GetCurrentCheckedImage(). Perversely, a 0
is returned if the box is checked and a 1 is returned if it is not.

• Is this the preferred way to read the check box state?

No, you should use:

state = item.IsChecked()

• A bug shows up when editing a list item in the same row as the
checkbox. Selecting the cell to be edited causes a second copy of it to
appear shifted to the right of the original and with a box drawn around it.

This looks like a bug, I'll try to hunt it down if I get some time...
please enter a bug report on wxTrac so that the bug doesn't get lost.

• Is it possible for the list columns to contain checkboxes, choice
boxes, etc. instead of merely text controls? If so, how? According to the
documentation: “Whatever non-toplevel widget can be attached next to a list
item.” Also, how does one initialize check boxes, detect changes, and read
the state for list items?

To attach whatever non-toplevel widget to an item, you simply do this:

# Create a wx.Choice, which is a child of the MAIN WINDOW
choice = wx.Choice(self.tree.GetMainWindow(), -1, choices=your_choices)
choice.Bind(wx.EVT_CHOICE, self.OnChoice)
# Assign the wx.Choice to this item on column 1
self.tree.SetItemWindow(item, choice, 1)

• The method wx.gizmos.TreeListCtrl.GetCurrentItem() has no counterpart
in HyperTreeList.

Uhm, I have never used this method myself, I don't even know what
"current" item means... what is it supposed to mean when you have
multiple selections enabled and you have selected 10 items? Which is
the "current" one? But anyway, I've added the method to return
"self._current"...

• Can a list item be a Choice box?

Yes, you simply enter an empty string for the item and attach a window
to that item, i.e.:

item = self.tree.AppendItem(parent, "B")
self.tree.SetItemText(item, "" , 1)
# Create a wx.Choice, which is a child of the MAIN WINDOW
choice = wx.Choice(self.tree.GetMainWindow(), -1, choices=your_choices)
# Assign the wx.Choice to this item on column 1
self.tree.SetItemWindow(item, choice, 1)

A modified sample is attached to this message.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

treelisttest_minimal_3.py (3.03 KB)

According to the HyperTreeList documentation,

    "* Column headers are fully customizable in terms of icons, colour, font, alignment etc..."

I couldn't find any more information on how to do that. It would be sufficient for me to make the column headers bold-face. I can make regular rows (tree items) bold by applying the SetItemBold method, to tree items; but column headers don't work like items.

Also, tool tips would be handy. I did

>>> import wx.lib.agw.hypertreelist as HTL
>>> help (HTL)

and found some tool tip-related methods inherited from the the wx._Core.Window class. I am not sure how to use them, however. It would be most useful to have tool tips associated with individual tree items, column headers, and perhaps with list items as well.

Advice on how to proceed will be appreciated.

-gt

Hi,

2009/9/23 Glenn Thobe:

According to the HyperTreeList documentation,

"* Column headers are fully customizable in terms of icons, colour,
font, alignment etc..."

I couldn't find any more information on how to do that. It would be
sufficient for me to make the column headers bold-face. I can make
regular rows (tree items) bold by applying the SetItemBold method, to
tree items; but column headers don't work like items.

Have you looked at the HyperTreeList demo? On the left hand side there
is a StaticBoxSizer labelled "HyperTreeList Columns", in which you can
change column headers text font, colour, alignment and add images.

Also, tool tips would be handy. I did

>>> import wx.lib.agw.hypertreelist as HTL
>>> help (HTL)

and found some tool tip-related methods inherited from the the
wx._Core.Window class. I am not sure how to use them, however. It
would be most useful to have tool tips associated with individual tree
items, column headers, and perhaps with list items as well.

What I usually do is to Bind() the wx.EVT_MOTION event for
HyperTreeList.GetMainWindow(), then I use HitTest() inside this event
handler to find out if the mouse is over an item (and which item) and
then I call SetToolTipString() on the main window.

Andrea.

"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/

What I usually do is to Bind() the wx.EVT_MOTION event for
HyperTreeList.GetMainWindow(), then I use HitTest() inside this event
handler to find out if the mouse is over an item (and which item) and
then I call SetToolTipString() on the main window.

Andrea.

Hello Andrea,

this tip was very helpful, but I have a problem with "long" tooltips

This is the code I use when capturing EVT_MOTION:

item, flags, column = self.HitTest(event.GetPosition())
if item and item.IsOk():
    if flags & wx.TREE_HITTEST_ONITEM or flags &
wx.TREE_HITTEST_ONITEMCOLUMN:
        item = self.GetItemPyData(item)
        tipString = self.colInfo.getToolTip(item, column) # Tip is
decided on item basis
        self.GetMainWindow().SetToolTipString(tipString)

If I use this and set a string like "Okay this is my very own long-
looking tooltip" it appears wrapped as:

Okay this is
my very
own
long-looking
tooltip

Any hint on how to prevent tip text from wrapping?

Just forget it, further search lead me to other solutions (TipWindow)

On MSW the native tooltip reuses the window used to display the tip, and for some reason MS decided to set the default width of the tooltip window to be based on the first tip shown.

IIRC we have a static method to be able to reset that width, wx.ToolTip.SetMaxWidth(width), but I'm not sure if I've ever used it nor how well it works... It's something to experiment with anyway.

···

On 10/2/09 2:37 AM, Sy Borg wrote:

Any hint on how to prevent tip text from wrapping?

--
Robin Dunn
Software Craftsman