Toggle currently focused item in TreeCtrl

Hello,

I'm trying to programmatically toggle the selection of the currently focused
item in a wx.TreeCtrl with multiple selection (wx.TR_MULTIPLE) enabled.
Specifically, I'd like to make SPACE in the TreeCtrl act the same way as
CTRL+SPACE. My problem is finding which item in the tree is the currently
focused one. wx.ListCtrl has a GetFocusedItem() method, but I can't seem to find
anything analogous in wx.TreeCtrl. Any ideas?

Barring that, I was thinking I could try and create a fake CTRL+SPACE KeyDown
event, and send it to the TreeCtrl using wx.PostEvent. I've looked at directly
instantiating the KeyEvent class, but I can't figure out how to set its KeyCode
and CtrlDown attributes to mimic a CTRL+SPACE (I suspect you can't, since
KeyDown events are in C++?). I thought of looking at subclassing PyEvent, but I
don't really know how to start. Can I do multiple inheritance of (PyEvent,
KeyEvent)? And if so, what do I need to do to make it look like a CTRL+SPACE event?

(I'm running wxPython 2.8.8.1 on WinXP SP3)

Thanks,

Martin

Hello,

Hello,

I’m trying to programmatically toggle the selection of the currently focused
item in a wx.TreeCtrl with multiple selection (wx.TR_MULTIPLE) enabled.

Specifically, I’d like to make SPACE in the TreeCtrl act the same way as
CTRL+SPACE. My problem is finding which item in the tree is the currently
focused one. wx.ListCtrl has a GetFocusedItem() method, but I can’t seem to find

anything analogous in wx.TreeCtrl. Any ideas?

wx.TreeCtrl.GetSelection

wx.TreeCtrl.GetSelections ← use this with TR_MULTIPLE

Barring that, I was thinking I could try and create a fake CTRL+SPACE KeyDown
event, and send it to the TreeCtrl using wx.PostEvent. I’ve looked at directly

instantiating the KeyEvent class, but I can’t figure out how to set its KeyCode
and CtrlDown attributes to mimic a CTRL+SPACE (I suspect you can’t, since
KeyDown events are in C++?). I thought of looking at subclassing PyEvent, but I

don’t really know how to start. Can I do multiple inheritance of (PyEvent,
KeyEvent)? And if so, what do I need to do to make it look like a CTRL+SPACE event?

Bind the treectrl to EVT_KEY_DOWN / EVT_KEY_UP and check the key code for the key you want to process. Just checking on a TreeCtrl on my machine and Ctrl+Space doesn’t seem to do anything, and Space is set to Activate the tree item so if you wanted to trap the space key and change it to expand a node you would probably need to catch it in the keydown event.

Cody

···

On 8/18/08, Martin Spacek wxpython@mspacek.mm.st wrote:

Cody Precord wrote:

wx.TreeCtrl.GetSelection
wx.TreeCtrl.GetSelections <- use this with TR_MULTIPLE

Thanks, but I'm looking for the currently focused item, not the currently selected item(s). The focused item is the one with a dotted box drawn around it (at least in win32). You can change the currently focused item without changing the currently selected item(s) by holding down CTRL and moving up/down with the navigation keys. I like this functionality because it allows you to stick to the keyboard, which is more efficient than using the mouse. CTRL-SPACE does what I want, but I'd like to make SPACE on its own do the same thing, without the need to hold down CTRL.

Bind the treectrl to EVT_KEY_DOWN / EVT_KEY_UP and check the key code for the key you want to process. Just checking on a TreeCtrl on my machine and Ctrl+Space doesn't seem to do anything, and Space is set to Activate the tree item so if you wanted to trap the space key and change it to expand a node you would probably need to catch it in the keydown event.

The problem isn't binding the SPACE keydown event. What I'm proposing is a workaround hack to a lack of a TreeCtrl.GetFocusedItem() method. The problem with it is that I don't know how to artificially generate a CTRL-SPACE keydown event. The idea is that I'd catch the SPACE event, generate a fake CTRL-SPACE event, and send it off to the TreeCtrl using wx.PostEvent(). The CTRL-SPACE event itself would be left uncaught, so that it does its normal thing, namely toggling the selection of the currently focused item.

Martin

Hi Martin,

Cody Precord wrote:
> wx.TreeCtrl.GetSelection
> wx.TreeCtrl.GetSelections <- use this with TR_MULTIPLE
>

Thanks, but I'm looking for the currently focused item, not the currently
selected item(s). The focused item is the one with a dotted box drawn around
it (at least in win32). You can change the currently focused item without
changing the currently selected item(s) by holding down CTRL and moving
up/down with the navigation keys. I like this functionality because it
allows you to stick to the keyboard, which is more efficient than using the
mouse. CTRL-SPACE does what I want, but I'd like to make SPACE on its own do
the same thing, without the need to hold down CTRL.

I think Cody is right: if you look at the wxPython demo for
wx.TreeCtrl and you change the style to wx.TR_MULTIPLE, moving up/down
with the arrows and holding the CTRL key down change the focus but
also the selections (you can see that the OnSelChanged event is called
every time).
So, to get the focused item, just call:

items = tree.GetSelections()
focusedItem = items[-1]

For the fake key event, have you tried something like this:

keyEvent = wx.KeyEvent(wx.wxEVT_CHAR)
keyEvent.m_keyCode = wx.WXK_SPACE
wx.PostEvent(treeCtrl, keyEvent)

? It may need some tinkering, and I am not sure it will work, but you
never know...

Andrea.

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

···

On 8/18/08, Martin Spacek wrote:

Andrea Gavana wrote:

I think Cody is right: if you look at the wxPython demo for
wx.TreeCtrl and you change the style to wx.TR_MULTIPLE, moving up/down
with the arrows and holding the CTRL key down change the focus but
also the selections (you can see that the OnSelChanged event is called
every time).

Hm, interesting, in the demo with TR_MULTIPLE set, I see different behaviour
from what you describe. CTRL+UP/DOWN only changes the focus, not the selection,
for me in WinXP with wxPy 2.8.8.1, and so it should for consistency with the
rest of the OS. In the demo, on CTRL+UP/DOWN, the current set of selected (ie
highlighted with dark background) items remains unchanged, the focus box moves,
but unfortunately the return values from GetSelections() includes the currently
focused item, whether or not that item is actually selected (ie highlighted with
dark background).

This is probably related to bugs #626 and #2307 (6 and 3 years old respectively!):

http://trac.wxwidgets.org/ticket/626
http://trac.wxwidgets.org/ticket/2307

where a SEL_CHANGED event isn't fired when (de)selecting the currently focused
item in a tree with the wx.TR_MULTIPLE style. To work around this bug, I
disabled binding the SEL_CHANGED event, and manually called my OnSelChanged
handler on every mouse and keyboard event in the tree. Looking at the demo
though, I realized you can get the currently focused item by binding the
SEL_CHANGED event anyway and by grabbing its event.GetItem(). This is a hack,
since wx seems to treat a newly focused event as being selected, even if it's
only been focused. But it seems to work for now, so I'm happy.

So, to get the focused item, just call:
items = tree.GetSelections()
focusedItem = items[-1]

This doesn't always work, because the currently focused item isn't always the
last selected item, so you could never know for sure which of the items returned
by GetSelections() is the focused one.

For the fake key event, have you tried something like this:

keyEvent = wx.KeyEvent(wx.wxEVT_CHAR)
keyEvent.m_keyCode = wx.WXK_SPACE
wx.PostEvent(treeCtrl, keyEvent)

? It may need some tinkering, and I am not sure it will work, but you
never know...

Thanks for that. I thought for sure I'd tried tinkering with m_keyCode, but I
guess not. To this, I'd add:

keyEvent.m_controlDown = True

and now I've got myself what looks like a fake CTRL+SPACE that I can send to the
TreeCtrl. Great! Except posting the event to the treectrl doesn't actually
toggle the current selection for some reason. I guess it's not a good enough
fake after all. Just out of curiosity, what does the leading "m" in "m_" stand for?

Martin