ListCtrl with exactly one selection

876 views
Skip to first unread message

Patrick Ruoff

unread,
May 1, 2012, 11:25:11 AM5/1/12
to wxpytho...@googlegroups.com
Hi,
I would like to have a ListCtrl that allows the user to select exactly one item.
Unfortunately, the SINGLE_SEL style still lets the user deselect all items.
Is there a way to prevent that without rewriting the whole selection logic,
i.e, can one somehow distinguish between a deselect because of another item being selected
and a deselect without another item being selected?

Cody

unread,
May 1, 2012, 11:27:53 AM5/1/12
to wxpytho...@googlegroups.com
Hi,
Style flag should work. Can you please post exactly how your creating
your ListCtrl?


Cody

Patrick Ruoff

unread,
May 2, 2012, 9:16:41 AM5/2/12
to wxpytho...@googlegroups.com
Hi Cody,

I create the ListCtrl with XRC, but this is not the problem, the same problem occurs in the wxPython demo.
Perhaps I didn't express it clearly:
SINGLE_SEL restricts the listctrl selection to one selected item, this works fine,
but there can still be no selection, e.g., when the user clicks on empty space on the list.
What I want is that the user cannot deselect an item without selecting another one, so that there
is always one item selected.

Maybe it wouldn't be so bad to rewrite the selection logic.
I think I'll need it anyway some time.
Can anyone tell me all the ListCtrl events that have to be caught for this?
(mouse and keys)

Patrick

Cody

unread,
May 2, 2012, 9:32:02 AM5/2/12
to wxpytho...@googlegroups.com
Hi,

On Wed, May 2, 2012 at 8:16 AM, Patrick Ruoff
<c14.rad...@googlemail.com> wrote:
> Hi Cody,
>
> I create the ListCtrl with XRC, but this is not the problem, the same
> problem occurs in the wxPython demo.
> Perhaps I didn't express it clearly:
> SINGLE_SEL restricts the listctrl selection to one selected item, this works
> fine,
> but there can still be no selection, e.g., when the user clicks on empty
> space on the list.
> What I want is that the user cannot deselect an item without selecting
> another one, so that there
> is always one item selected.
>
> Maybe it wouldn't be so bad to rewrite the selection logic.
> I think I'll need it anyway some time.
> Can anyone tell me all the ListCtrl events that have to be caught for this?
> (mouse and keys)
>

In that case probably want to look at handling
EVT_LIST_ITEM_DESELECTED to ensure that a selection is made after that
is called. Not a 100% sure off the top of my head on the order in
which this is fired (i.e before or after the new selection event), so
may need to set a timer or issue a CallAfter to a function to check if
there is a selection after this has been handled.


Cody

Patrick Ruoff

unread,
May 2, 2012, 10:30:04 AM5/2/12
to wxpytho...@googlegroups.com
Hi,


In that case probably want to look at handling
EVT_LIST_ITEM_DESELECTED to ensure that a selection is made after that
is called. Not a 100% sure off the top of my head on the order in
which this is fired (i.e before or after the new selection event), so
may need to set a timer or issue a CallAfter to a function to check if
there is a selection after this has been handled.

yes, this works in principle:
The handler for ...DESELECTED is called first, I could select the old selection in there.
However, selecting the old selection
with ListCtrl.Select causes new select/deslect events to be generated and messing things up,
possibly even generating an infinite recursion.

Is there any way to select/deselect items without generating the corresponding events?

Cody

unread,
May 2, 2012, 10:43:25 AM5/2/12
to wxpytho...@googlegroups.com
Hi,
The attached works fine for me.

Generally control methods shouldn't generate events, unfortunatly wx
is rather inconsistent in this regards.


Cody
list_sel_test.py

Patrick Ruoff

unread,
May 2, 2012, 3:44:30 PM5/2/12
to wxpytho...@googlegroups.com
Hi,

The attached works fine for me.

Generally control methods shouldn't generate events, unfortunatly wx
is rather inconsistent in this regards.


Cody


import wx

class MyFrame(wx.Frame):
    def __init__(self):
        super(MyFrame, self).__init__(None)

        self.l = MyListCtrl(self)
        self.l.Select(0)

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent):
        super(MyListCtrl, self).__init__(parent, style=wx.LC_REPORT|wx.LC_SINGLE_SEL)

        self.InsertColumn(0, "Foo")
        self.InsertColumn(1, "Bar")
        for x in range(5):
            self.Append(("Column 0", "Column 1"))

        self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnDeSel)

    def OnDeSel(self, evt):
        wx.CallAfter(self.DoForcedSel, evt.GetIndex())

    def DoForcedSel(self, sel):
        if self.GetSelectedItemCount() == 0:
            self.Select(sel)

app = wx.App(False)
f = MyFrame()
f.Show()
app.MainLoop()


Yes, this works, thanks alot!
Guess I missed the CallAfter in my experiments... I will have a closer look at this function.
Reply all
Reply to author
Forward
0 new messages