Defining and Loading Data in wx.ListCtrl

The discussion of wx.ListCtrl() in wIA focuses on images, and I'm trying
to build and populate a 2-column list control of type LC_REPORT. I've
defined two lists, one for each column (remarkSym[] and remarkTxt[]; there's
a one-to-one correspondence in the two lists). This is a lookup list from
which one row may be selected; if no row is appropriate, then the blank
first row is the default. I've also created the list widget:

self.remark = wx.ListCtrl(self, wx.ID_ANY, size=wx.Size(25, 25),
                           style=wx.TAB_TRAVERSAL|wx.LC_REPORT|wx.LC_HRULES|
         LC_SINGLE_SEL|wx.RAISED_BORDER)

   Do I now use:

self.remark.InsertColumn(1, "Symbol", format=wx.LIST_FORMAT_CENTER,
width=-1)

self.remark.InsertColumn(2, "Meaning", format=wx.LIST_FORMAT_LEFT, width=-1)

?

TIA,

Rich

Hi,

···

On Mon, Dec 12, 2011 at 3:43 PM, Rich Shepard rshepard@appl-ecosys.com wrote:

The discussion of wx.ListCtrl() in wIA focuses on images, and I’m trying

to build and populate a 2-column list control of type LC_REPORT. I’ve

defined two lists, one for each column (remarkSym and remarkTxt; there’s

a one-to-one correspondence in the two lists). This is a lookup list from

which one row may be selected; if no row is appropriate, then the blank

first row is the default. I’ve also created the list widget:

self.remark = wx.ListCtrl(self, wx.ID_ANY, size=wx.Size(25, 25),

                      style=wx.TAB_TRAVERSAL|wx.LC_REPORT|wx.LC_HRULES|

                      LC_SINGLE_SEL|wx.RAISED_BORDER)

Do I now use:

self.remark.InsertColumn(1, “Symbol”, format=wx.LIST_FORMAT_CENTER,

width=-1)

self.remark.InsertColumn(2, “Meaning”, format=wx.LIST_FORMAT_LEFT, width=-1)

?

TIA,

Rich

What you are doing is inserting the columns themselves and that looks right to me. To actually insert rows, you normally use InsertStringItem (or similar) for the first item in the row and then SetStringItem for the other columns in that row. I wrote about some of this stuff here: http://www.blog.pythonlibrary.org/2011/01/04/wxpython-wx-listctrl-tips-and-tricks/

Personally, I prefer the ObjectListView wrapper over the wx.ListCtrl, but I’ve used both.


Mike Driscoll

Blog: http://blog.pythonlibrary.org

What you are doing is inserting the columns themselves and that looks right
to me. To actually insert rows, you normally use InsertStringItem (or
similar) for the first item in the row and then SetStringItem for the other
columns in that row.

Mike,

   Gotcha'. I missed this reading the ListCtrl chapter in the book. Can I use
a dictionary holding all rows to load the list control?

I wrote about some of this stuff here:
wxPython: wx.ListCtrl Tips and Tricks - Mouse Vs Python

   This is very helpful. Thanks. I notice on your example (like on my efforts
so far) that there's an extra column on the right side. Is that column
always present or can it be eliminated with some ListCtrl foo?

Personally, I prefer the ObjectListView wrapper over the wx.ListCtrl, but
I've used both.

   I'll look at this, too. The applications I develop are few and far between
so I end up relearning each time.

Very much appreciated,

Rich

···

On Mon, 12 Dec 2011, Mike Driscoll wrote:

Hi,

What you are doing is inserting the columns themselves and that looks right

to me. To actually insert rows, you normally use InsertStringItem (or

similar) for the first item in the row and then SetStringItem for the other

columns in that row.

Mike,

Gotcha’. I missed this reading the ListCtrl chapter in the book. Can I use

a dictionary holding all rows to load the list control?

You can use any data structure you want to use if you’re careful. Look at the demo. It uses a dictionary.

I wrote about some of this stuff here:

http://www.blog.pythonlibrary.org/2011/01/04/wxpython-wx-listctrl-tips-and-tricks/

This is very helpful. Thanks. I notice on your example (like on my efforts

so far) that there’s an extra column on the right side. Is that column

always present or can it be eliminated with some ListCtrl foo?

Yeah, you can can. I don’t know why I didn’t mention it in that article, but you just need to use the ListCtrlAutoWidthMixin. There’s an example of that in the demo too.

Personally, I prefer the ObjectListView wrapper over the wx.ListCtrl, but

I’ve used both.

I’ll look at this, too. The applications I develop are few and far between

so I end up relearning each time.

Very much appreciated,

Rich

No problem.

···

On Tue, Dec 13, 2011 at 8:42 AM, Rich Shepard rshepard@appl-ecosys.com wrote:

On Mon, 12 Dec 2011, Mike Driscoll wrote:


Mike Driscoll

Blog: http://blog.pythonlibrary.org

You can use any data structure you want to use if you're careful. Look at
the demo. It uses a dictionary.

   That's what gave me the idea. Better than 28 lines of code to insert rows
one at a time.

Yeah, you can can. I don't know why I didn't mention it in that article,
but you just need to use the ListCtrlAutoWidthMixin. There's an example of
that in the demo too.

   Good. I need to learn about mixins and factories.

Thanks again, Mike,

Rich

···

On Tue, 13 Dec 2011, Mike Driscoll wrote:

so far) that there’s an extra column on the right side. Is that column

always present or can it be eliminated with some ListCtrl foo?

Yeah, you can can. I don’t know why I didn’t mention it in that article, but you just need to use the ListCtrlAutoWidthMixin. There’s an example of that in the demo too.

FWIW: I hadn’t thought about it until just now due to Rich’s question, and I use ListCtrlAutoWidthMixin myself, but it occurs to me that, really, the ListCtrl should provide this functionality by default. I hadn’t seen a regular ListCtrl and this extra column in a while (since I use the mixin), but it is, in my opinion, “not so good UI”.

Che

I tried emulating the ListCtrl demo but have obviously missed something
vital. Can I make a tarball of the two source files and post them to the
list as an attachment? I'd like someone who knows what he's doing to show me
what I've done incorrectly since the wx.ListCtrl still has the blank column
on the end and does not display the drop-down list of choices.

TIA,

Rich

···

On Tue, 13 Dec 2011, Rich Shepard wrote:

Yeah, you can can. I don't know why I didn't mention it in that article,
but you just need to use the ListCtrlAutoWidthMixin. There's an example
of that in the demo too.

Good. I need to learn about mixins and factories.

I think even just the two .py files is fine here as long as you attach, many of us do it all the time as long as the files are not huge.

Werner

···

On 12/14/2011 06:20 PM, Rich Shepard wrote:

On Tue, 13 Dec 2011, Rich Shepard wrote:

Yeah, you can can. I don't know why I didn't mention it in that article,
but you just need to use the ListCtrlAutoWidthMixin. There's an example
of that in the demo too.

Good. I need to learn about mixins and factories.

  I tried emulating the ListCtrl demo but have obviously missed something
vital. Can I make a tarball of the two source files and post them to the
list as an attachment? I'd like someone who knows what he's doing to show me
what I've done incorrectly since the wx.ListCtrl still has the blank column
on the end and does not display the drop-down list of choices.

Werner,

   5K and 16K. They're attached.

Thanks,

Rich

biolwq.py (4.78 KB)

biotaPage.py (15.7 KB)

···

On Wed, 14 Dec 2011, werner wrote:

I think even just the two .py files is fine here as long as you attach,
many of us do it all the time as long as the files are not huge.

At first glance your listctrl related code looks okay[1], but I can't run it to look deeper because of dependencies on other modules. If you can reproduce the problem in a smaller standalone sample you may be able to figure out the problem on your own. If not then send that code here and we'll be able to experiment with it to find the problem. MakingSampleApps - wxPyWiki

[1] Except for this: self.remark.Bind(wx.EVT_TEXT, self.OnDataRemark) The wx.ListCtrl does not emit the EVT_TEXT event. If you're wanting to get notified when the user edits an item in the list then you should probably use EVT_LIST_END_LABEL_EDIT.

···

On 12/14/11 10:18 AM, Rich Shepard wrote:

On Wed, 14 Dec 2011, werner wrote:

I think even just the two .py files is fine here as long as you attach,
many of us do it all the time as long as the files are not huge.

Werner,

5K and 16K. They're attached.

--
Robin Dunn
Software Craftsman

At first glance your listctrl related code looks okay[1], but I can't run
it to look deeper because of dependencies on other modules. If you can
reproduce the problem in a smaller standalone sample you may be able to
figure out the problem on your own. If not then send that code here and
we'll be able to experiment with it to find the problem. MakingSampleApps - wxPyWiki

   Thank, Robin. Many of the other imported modules are not yet needed in the
UI code; I'll comment those out and that should slim things down. Will also
look at the wiki.

[1] Except for this: self.remark.Bind(wx.EVT_TEXT, self.OnDataRemark) The
wx.ListCtrl does not emit the EVT_TEXT event. If you're wanting to get
notified when the user edits an item in the list then you should probably
use EVT_LIST_END_LABEL_EDIT.

   Ah. Users will not edit items; it's a pick list and I want to capture the
selected item.

Rich

···

On Wed, 14 Dec 2011, Robin Dunn wrote:

Smaller code attached. I'd like the remarks wx.ListCtrl to lose the blank
column on the right and gain a scroll arrow so users can select the
appropriate one. Most of the time that will be the initial blank entry. When
there is a line entered I want to capture the selected symbol for passing to
the database table row with the rest of the data.

   Please let me know if there's more I should do to make it easier to debug,
or if there are questions about usage.

Regards,

Rich

sampleapp.py (12.3 KB)

···

On Wed, 14 Dec 2011, Robin Dunn wrote:

If you can reproduce the problem in a smaller standalone sample you may be
able to figure out the problem on your own. If not then send that code
here and we'll be able to experiment with it to find the problem.

That would be EVT_LIST_ITEM_SELECTED or perhaps EVT_LIST_ITEM_ACTIVATED if you want it to behave that way. The latter is the event you get when an item is double-clicked or the user presses the Enter key.

···

On 12/14/11 1:27 PM, Rich Shepard wrote:

On Wed, 14 Dec 2011, Robin Dunn wrote:

At first glance your listctrl related code looks okay[1], but I can't run
it to look deeper because of dependencies on other modules. If you can
reproduce the problem in a smaller standalone sample you may be able to
figure out the problem on your own. If not then send that code here and
we'll be able to experiment with it to find the problem.
MakingSampleApps - wxPyWiki

Thank, Robin. Many of the other imported modules are not yet needed in the
UI code; I'll comment those out and that should slim things down. Will also
look at the wiki.

[1] Except for this: self.remark.Bind(wx.EVT_TEXT, self.OnDataRemark) The
wx.ListCtrl does not emit the EVT_TEXT event. If you're wanting to get
notified when the user edits an item in the list then you should probably
use EVT_LIST_END_LABEL_EDIT.

Ah. Users will not edit items; it's a pick list and I want to capture the
selected item.

--
Robin Dunn
Software Craftsman

A minimal sample submitted for help should include the least amount of widgets/sizers needed to demonstrate the problem. The best approach is to start from scratch because that will give you the best chance of discovering the solution yourself, but totally stripping down your existing code is acceptable too.

I've attached my copy of your sample with some changes that show how to get notified of the selections in the listctrl. The lines I changed or added are marked with "##*". Also, you had an 'return' in your populate method so it was not actually adding any items to the listctrl, which is necessary for the ListCtrlAutoWidthMixin to be able to do its job.

Finally, the wx.TAB_TRAVERSAL style is only applicable to container windows, like wx.Panel. You shouldn't be using it on textctrls or other widgets.

sampleapp.py (12.3 KB)

···

On 12/14/11 2:02 PM, Rich Shepard wrote:

On Wed, 14 Dec 2011, Robin Dunn wrote:

If you can reproduce the problem in a smaller standalone sample you
may be
able to figure out the problem on your own. If not then send that code
here and we'll be able to experiment with it to find the problem.

Smaller code attached. I'd like the remarks wx.ListCtrl to lose the blank
column on the right and gain a scroll arrow so users can select the
appropriate one. Most of the time that will be the initial blank entry.
When
there is a line entered I want to capture the selected symbol for
passing to
the database table row with the rest of the data.

Please let me know if there's more I should do to make it easier to debug,
or if there are questions about usage.

--
Robin Dunn
Software Craftsman

Thank you.

Rich

···

On Wed, 14 Dec 2011, Robin Dunn wrote:

That would be EVT_LIST_ITEM_SELECTED or perhaps EVT_LIST_ITEM_ACTIVATED if
you want it to behave that way. The latter is the event you get when an
item is double-clicked or the user presses the Enter key.

A minimal sample submitted for help should include the least amount of
widgets/sizers needed to demonstrate the problem.

Robin,

   I think the attached meets this criterion.

I've attached my copy of your sample with some changes that show how to
get notified of the selections in the listctrl. The lines I changed or
added are marked with "##*". Also, you had an 'return' in your populate
method so it was not actually adding any items to the listctrl, which is
necessary for the ListCtrlAutoWidthMixin to be able to do its job.

Finally, the wx.TAB_TRAVERSAL style is only applicable to container
windows, like wx.Panel. You shouldn't be using it on textctrls or other
widgets.

   Excellent. Thank you.

Rich

···

On Wed, 14 Dec 2011, Robin Dunn wrote:

Nuts! Here's the attachment.

Rich

sampleapp.py (4.78 KB)

···

On Wed, 14 Dec 2011, Rich Shepard wrote:

I think the attached meets this criterion.

Rich,

I think the attached meets this criterion.

  Nuts! Here's the attachment.

Attached should be a bit closer to what you like to get to.

I don't use ListCtrl that often any more, just about always ObjectListView as it is really nice to work with especially when also using SQLAlchemy for the db interaction. If you have a select of a whatever number of rows you just hand the select result to the OLV and it fills the list.

Anyhow, I had to experiment a bit, so there are maybe a few changes not needed.

- Removed the try/except in PopulateList which I think is your main problem
- change wx.App to wit.InspectableApp as I couldn't see why the list was not showing/expanding, you activate it with ctrl-alt-i, more details on the wiki
- commented the self.Fit(), otherwise the list is too small
- changed some sizer.Add proportion and expand, some are probably not needed

The PopulateList probably needs further changes if I understand how you will use it. Probably needs to clear at least all items on each call. You might also want to move the InsertColumn to another method which is only called during __init__.

Werner

sampleapp.py (4.71 KB)

···

On 12/15/2011 02:01 AM, Rich Shepard wrote:

On Wed, 14 Dec 2011, Rich Shepard wrote:

Attached should be a bit closer to what you like to get to.

Werner,

   Thanks to you and Robin. I'm reading the ObjectListView Web site and will
read all about that before proceeding further.

The PopulateList probably needs further changes if I understand how you
will use it. Probably needs to clear at least all items on each call. You might also want to move the InsertColumn to another method which is
only called during __init__.

   I see that I've not been sufficiently clear on the purpose of this
control. Just for the heck of it, I'll try again.

   Observed and measured values are stored in the database table as REALs;
i.e., floating point numbers. Analytical labs report values below detection
limits by pre-pending the less-than sign '<' and that's what clients put in
their spreadsheets. But, while we cannot store that character in a numeric
column we'd like to know that it's not an exact measurement when applying
statistical models. Other times there is no value; the stream was dry or
flowing too fast for access, someone dropped the sample bottle, it was held
too long before analysis, and so on. There's a code for each of these
situations.

   To facilitate entry of these codes I want to present a lookup table and
have the user select the appropriate entry (which might be blank because
that row has a NULL value for that column). This means the list is static
but singularly selectable.

   It may be that the most parsimonious approach for this control is to use a
single column drop-down column box with the reason descriptions (default
value is blank). When a description is selected and the filled form to be
entered in the database table, I can use the GetValue() method (or
GetText(), I need to determine which is appropriate), then do a dictionary
lookup that provides the single letter stored in the database table.

   If anyone desires to share comments or ideas with me please do so. I've
not before implemented anything like this in Python and what I did in C was
both long ago and not necessarily appropriate to a wxPython application.

Rich

···

On Thu, 15 Dec 2011, werner wrote:

Attached should be a bit closer to what you like to get to.

Werner,

  Thanks to you and Robin. I'm reading the ObjectListView Web site and will
read all about that before proceeding further.

You might want to look at the MediaLocker sample application Mike and I did put together. It uses the OLV as listctrl both to list books, persons etc and is also used with in the popup control to select e.g. a person in the book editor.

http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-–-a-wxpython-app-to-track-your-media/
https://bitbucket.org/driscollis/medialocker

The PopulateList probably needs further changes if I understand how you
will use it. Probably needs to clear at least all items on each call. You might also want to move the InsertColumn to another method which is
only called during __init__.

  I see that I've not been sufficiently clear on the purpose of this
control. Just for the heck of it, I'll try again.

  Observed and measured values are stored in the database table as REALs;
i.e., floating point numbers. Analytical labs report values below detection
limits by pre-pending the less-than sign '<' and that's what clients put in
their spreadsheets. But, while we cannot store that character in a numeric
column we'd like to know that it's not an exact measurement when applying
statistical models. Other times there is no value; the stream was dry or
flowing too fast for access, someone dropped the sample bottle, it was held
too long before analysis, and so on. There's a code for each of these
situations.

  To facilitate entry of these codes I want to present a lookup table and
have the user select the appropriate entry (which might be blank because
that row has a NULL value for that column). This means the list is static
but singularly selectable.

  It may be that the most parsimonious approach for this control is to use a
single column drop-down column box with the reason descriptions (default
value is blank). When a description is selected and the filled form to be
entered in the database table, I can use the GetValue() method (or
GetText(), I need to determine which is appropriate), then do a dictionary
lookup that provides the single letter stored in the database table.

  If anyone desires to share comments or ideas with me please do so. I've
not before implemented anything like this in Python and what I did in C was
both long ago and not necessarily appropriate to a wxPython application.

Each measure can have none or one "description/explanation" of the measure?

Couldn't you then have a table with all the possible description and you relate to this table in a similar way then we did in MediaLocker between book and person/publisher?

In other words the table with the measures has a foreign key to a measure explanation table.

Werner

···

On 12/16/2011 01:22 AM, Rich Shepard wrote:

On Thu, 15 Dec 2011, werner wrote: