[Windows] In place edit for ultimatelistctrl or alternative widget

Hell there. I have a small ultimatelistctrl. It looks like this.

The user should be able to double click any cell in the list end edite it. I searched the whole web and didnt find a solution to this. I tried two ways of implementing that.

First:

class TestList(ULC.UltimateListCtrl,listmix.TextEditMixin):
def __init__ (self, *args, **kwargs):
    ULC.UltimateListCtrl.__init__(self,*args,**kwargs)
    listmix.TextEditMixin.__init__(self)

I used the listmix.TextEditMixin which works for listctrl. But i get an error when i try to use it.

File “C:\ProgramData\Anaconda3\lib\site-packages\wx\lib\mixins\listctrl.py”, line 553, in OnLeftDown

col = bisect(self.col_locs, x+self.GetScrollPos(wx.HORIZONTAL)) - 1

TypeError: GetScrollPos() takes 1 positional argument but 2 were given

Second: I tried bulding my own functionality. I wantet to just overlay a textctrl on top of the cell. But i couldnt even figure out how to get the column back where the user clicked. The row was no problem.

So why dont i just use listctrl instead of ultimatelistctrl? Because i need to add more widgets to the list later one. At least one combobox and one checkbox more. So if you maybe know another widget that would also do what i want i would also gladly switch.

Thanks for your help.

You may want to take a look at the DataViewCtrl or DataViewListCtrl classes.

1 Like

Thanks Robin. Took me a while besides normal work to test it. But it works really good. I now use this

class:

class FahrradList(DV.DataViewListCtrl):
    def __init__(self, *args, **kwargs):
        DV.DataViewListCtrl.__init__(self, *args, **kwargs)
        self.AppendToggleColumn("Senden",width=60,)
        self.AppendTextColumn("Adresse",mode=DV.DATAVIEW_CELL_EDITABLE,width=300)
        self.AppendTextColumn("Datum",mode=DV.DATAVIEW_CELL_EDITABLE,width=100)
        self.AppendTextColumn("Uhrzeit",mode=DV.DATAVIEW_CELL_EDITABLE,width=80)
        self.AppendTextColumn("Kennzeichen",mode=DV.DATAVIEW_CELL_EDITABLE,width=100)
        self.AppendTextColumn("Tatvorwurf",mode=DV.DATAVIEW_CELL_EDITABLE,width=200)
        self.AppendTextColumn("Dateiname",width=200)
        self.AppendTextColumn("Status",width=100)

I just have three question.

  1. I didnt found a way to append a column with a combobox. It seems i need to create my own class with the create method right?

https://wxpython.org/Phoenix/docs/html/wx.dataview.DataViewListCtrl.html#wx.dataview.DataViewListCtrl.Create

  1. I tried to focus a specific item. In listctrl widget i would use the

https://wxpython.org/Phoenix/docs/html/wx.ListCtrl.html#wx.ListCtrl.Focus

method.

I tried

self.list_ctrl.SelectRow(i)

https://wxpython.org/Phoenix/docs/html/wx.dataview.DataViewListCtrl.html#wx.dataview.DataViewListCtrl.SelectRow

where list_ctrl is an instance of FahrradList (i know a little confusing.) which is an instance of Dataviewlistctrl and i is an integer which should be the number of the item in the list. But it doesnt provide the same functionality. So what would be the equivalent for the focus method of listctrl?

  1. The in place edit works by focusing the item and then clicking once on it. But when i double click one an item it only focuses. The second click will not be recognized in any way. So maybe you have an idea on what to change to change it to that a double click on an unselected item will select it and start the in place edit.

Thanks for your help.

Does it need to be a wx.ComboBox or would a wx.Choice be enough? If so then you can use the DataViewChoiceRenderer. There isn’t a AppendChoiceColumn helper function for it, so you’ll need to do all the steps yourself. (Create the renderer, create the column, add the column to the dataview listctrl.)

If you need it to be a combobox then you’ll need to make your own renderer class for it.

It seems like that should work… If you’re trying to do the selection at the same time you are creating the control and populating it, then you may need to delay the selection until later so it has a chance to finish all of the internal things related to the initialization, population, etc. So try using wx.CallAfter to call the SelectRow later.

That may be just the way it’s intended to work. Typically in list-like controls a double-click is considered an “activation” event, and the slow-2-click is the “request to edit” event. Depending on the platform and how the columns are configured you may be able to do a 3rd click after a pause to get the editor widget, but it’s a platform specific behavior so there’s no guarantee.

Thanks again.

wx.Choice would also have been fine. But specs changed and now an entire different solution is neede. But good to know about this widget.

The Callafter worked great:

wx.CallAfter(self.mainparent.list_ctrl.SelectRow,i)

There can be very long calculation time in between adding new data in the list so it is nice to show the user whats happening with this trick :slight_smile:

For the last part:

The problem i have is that one left click allready activates the row. And a double click does the same.
I found the following 6 states :

Not Activated: One Click Activates the row.
Not Activated: Two Clicks activates the row.
Not Activated: Three clicks starts the in place editing. Well 2 clicks activate the row and the third click then starts the editing.

Activated: One click stars in place editing
Activated: Two clicks does nothing (Presumably activates it again)
Activated: Three clicks starts in place editing.

The change i want to do is regardles of a row beeing activated or not: A double click should always start the in place editing.