[wxPython] Popup menu problem

After the successful (if not helpful) diagnosis of my
listbox problem once I isolated it in a full script, I'm
hoping for similar miracles with this popup menu thing -
which is now encapsulated in this script:

http://www-edc.eng.cam.ac.uk/~djd33/menu-broken.txt

The problem is that when you first right-click on an
item and select View Info, nothing happens... however,
from then on, no matter what item you click on and select
View Info, you will always get the output for the first
item you clicked on. I've stripped the output routine
down to a print statement on stdout, and you can see
the discrepancy between the printed output and the
numbers on the top of the menus themselves...

Help? :slight_smile:

Regards,
Denny

···

----------------------------------------------------------
Denny De La Haye \ www-edc.eng.cam.ac.uk/~djd33
Engineering Design Centre, \ www-edc.eng.cam.ac.uk
Department of Engineering, \ www.eng.cam.ac.uk
University of Cambridge, UK \ www.cam.ac.uk
----------------------------------------------------------
"Only two things are infinite, the universe and human stupidity,
and I'm not sure about the former." (Albert Einstein)

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

After the successful (if not helpful) diagnosis of my
listbox problem once I isolated it in a full script, I'm
hoping for similar miracles with this popup menu thing -
which is now encapsulated in this script:

http://www-edc.eng.cam.ac.uk/~djd33/menu-broken.txt

The problem is that when you first right-click on an
item and select View Info, nothing happens... however,
from then on, no matter what item you click on and select
View Info, you will always get the output for the first
item you clicked on. I've stripped the output routine
down to a print statement on stdout, and you can see
the discrepancy between the printed output and the
numbers on the top of the menus themselves...

Help? :slight_smile:

Your wish is my command!

There are two problems here. The first is that you need to bind the event
before you popup the menu. This is why nothing happens the first time. The
second issue is more subtle. It's not letting you rebind the event using the
ID 2001 repeatedly. One way around this would be to use different IDs each
time, but I've found that you end up leaking memory that way. What I would
do is replace:

     win.PopupMenuXY (node_menu, cursor_pos[0], cursor_pos[1])
     EVT_MENU (win, 2001, self.ViewStates)

with

      EVT_MENU (win, 2001, self.ViewStates)
      win.PopupMenuXY (node_menu, cursor_pos[0], cursor_pos[1])
      win.Disconnect(2001)

That seems to do the trick.

One other approach would be to generate the menus once in the constructor of
each spTangentNode, generating different ids each time. However, you'd still
need to disconnect the id when each spTangentNode was deleted, so I think
the method above is probably best.

-tim

···

----------------------------------------------------------
Denny De La Haye \ www-edc.eng.cam.ac.uk/~djd33
Engineering Design Centre, \ www-edc.eng.cam.ac.uk
Department of Engineering, \ www.eng.cam.ac.uk
University of Cambridge, UK \ www.cam.ac.uk
----------------------------------------------------------
"Only two things are infinite, the universe and human stupidity,
and I'm not sure about the former." (Albert Einstein)

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

Can I have your babies? :wink:

That worked, thankyou very very very much.
Denny

···

On Wed, 7 Mar 2001, Tim Hochberg wrote:

      EVT_MENU (win, 2001, self.ViewStates)
      win.PopupMenuXY (node_menu, cursor_pos[0], cursor_pos[1])
      win.Disconnect(2001)

----------------------------------------------------------
Denny De La Haye \ www-edc.eng.cam.ac.uk/~djd33
Engineering Design Centre, \ www-edc.eng.cam.ac.uk
Department of Engineering, \ www.eng.cam.ac.uk
University of Cambridge, UK \ www.cam.ac.uk
----------------------------------------------------------
"Only two things are infinite, the universe and human stupidity,
and I'm not sure about the former." (Albert Einstein)

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

> EVT_MENU (win, 2001, self.ViewStates)
> win.PopupMenuXY (node_menu, cursor_pos[0], cursor_pos[1])
> win.Disconnect(2001)

Can I have your babies? :wink:

Err, no, I don't think so. But you're welcome anyway.

That worked, thankyou very very very much.

Wow. That must be some program you're working on!

-tim

···

On Wed, 7 Mar 2001, Tim Hochberg wrote:

Denny

----------------------------------------------------------
Denny De La Haye \ www-edc.eng.cam.ac.uk/~djd33
Engineering Design Centre, \ www-edc.eng.cam.ac.uk
Department of Engineering, \ www.eng.cam.ac.uk
University of Cambridge, UK \ www.cam.ac.uk
----------------------------------------------------------
"Only two things are infinite, the universe and human stupidity,
and I'm not sure about the former." (Albert Einstein)

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

Hello. I hope this is useful to someone. I've found what (I feel) is a limitation with
the column-clicking/sorting feature(s) of wxListCtrl. What it boils down to is this:
You have a tuple, list, or dictionary, and you want to add values from given indices
to your wxListCtrl. Furthermore, you want to be able to sort the different columns with
OnColClick.

Here's the problem: suppose your list contains 20 items, but you only want
to add 4 of them to the ListCtrl. On top of that, you may want to a) add items beyond
the 4th index - i.e., List[3] - (remember, you only have 4 columns), or b) you want to
add them out of order - i.e., List[2], List[0], List[3]... In each of these two cases, you're
asking for weird behavior to result from column clicking/sorting.

Solution: make sure that all of the data you want to put into the ListCtrl is a) at or below the
List's index number which corresponds to the number of columns in your ListCtrl minus 1.
The code below uses a dictionary of key/value pairs- in this case we're talking
about the index of the item in the VALUES list. Key doesn't seem to matter. And lest I forget,
b) make sure you add the items to the ListCtrl in the order they are found in your original data
structure.

hope this helps, if not let me know so we can pinpoint this problem. I really like ListCtrl and would
hate to give it up.

CODE:

#!/usr/bin/env python

### this is just a test script showing a limitation in the
### column clicking feature of wxListCtrl for wxPython

from wxPython.wx import *

musicdata = {
12 : ["George", "Praying For Time", "Silly","aaaaa", "ksadjflkjasdf"],
3 : ("Bad", "The Price Of Love", "SpeakEnglishOrDie", "bbbbb","kfdkjdkjdwwwww"),
1 : ("DNA", "Tom's Diner", "Rock", "ccccc", "mmmmm"),
4 : ("Gloria", "Here We Are", "Rock", "gggggg", "wwqfkdsjf"),
}

class ListCtrlTest(wxFrame):
    def __init__(self, parent, ID, title, position, size):

        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(429, 333))
        
        tID = wxNewId()

        self.list = wxListCtrl(self, tID,
                               style=wxLC_REPORT|wxSUNKEN_BORDER)

        self.list.InsertColumn(0, "Artist")
        self.list.InsertColumn(1, "Title", wxLIST_FORMAT_RIGHT)
        self.list.InsertColumn(2, "Genre")
        self.list.InsertColumn(3, "Garbage")
        
        items = musicdata.items()
  
  for x in range(len(items)):
      key, data = items[x]

            self.list.InsertStringItem(x, data[0])
            self.list.SetStringItem(x, 1, data[1]) ## 0<1<2<3 works
            self.list.SetStringItem(x, 2, data[2])
            self.list.SetStringItem(x, 3, data[3])
            self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[3]) ## 0<3<1<2 doesn't work
# self.list.SetStringItem(x, 2, data[1]) ## items out of order
# self.list.SetStringItem(x, 3, data[2])
# self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[1]) ## 0<1<2<4 doesn't work.
# self.list.SetStringItem(x, 2, data[2]) ## items out of range
# self.list.SetStringItem(x, 3, data[4])
# self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[1])
# self.list.SetStringItem(x, 2, data[4]) ## 0<1<4<2 doesn't work.
# self.list.SetStringItem(x, 3, data[2]) ## items out of order and out of range
# self.list.SetItemData(x, key)
  
  self.list.SetColumnWidth(0, wxLIST_AUTOSIZE)
        self.list.SetColumnWidth(1, wxLIST_AUTOSIZE)
                
        self.currentItem = 0
        EVT_LIST_ITEM_SELECTED(self, tID, self.OnItemSelected)
        EVT_LIST_ITEM_ACTIVATED(self, tID, self.OnItemActivated)
        EVT_LIST_COL_CLICK(self, tID, self.OnColClick)
        
    def OnItemSelected(self, event):
        self.currentItem = event.m_itemIndex

    def OnItemActivated(self, event):
        self.currentItem = event.m_itemIndex

    def OnColClick(self, event):
        self.col = event.m_col
        self.list.SortItems(self.ColumnSorter)

    def ColumnSorter(self, key1, key2):
        item1 = musicdata[key1][self.col]
        item2 = musicdata[key2][self.col]
        if item1 == item2: return 0
        elif item1 < item2: return -1
        else: return 1

class MyApp(wxApp):
    def OnInit(self):
  frame = ListCtrlTest(NULL, -1, "ListCtrl Test", wxPoint(200,200), wxSize(429,384))
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

if __name__ == "__main__":
   app = MyApp(0)
   app.MainLoop()

···

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

Hi,

I think this is not a problem with wxListCtrl, it's a problem
with how you organize your data structures.

If you have some arbitrary data structure (e.g., the musicdata
dictionary in your example) which you want to view in a wxListCtrl,
you should define some mapping between that data structure and the
string data you will display in the columns of the wxListCtrl.

Then when the user clicks on columns (or does anything else with
the wxListCtrl), it is YOUR job to figure out which real
data to manipulate by using the mapping you defined. This is not
the job of the wxListCtrl.

E.g., in your example, you complain that you need to add the
indices in increasing order and you cannot use arbitrary
orders. But that's because your column sorting function uses
the wxListCtrl column index directly as an index into the lists
stored in musicmap. If you had a mapping between list indices
and wxListCtrl columns, you would use this mapping before
you manipulate your own data. For example, if you wanted
to display indices 0, 1, 4, 2 of the musicdata lists, you
might define a mapping from ListCtrl columns to musicdata lists:
        mapping[0] = 0
        mapping[1] = 1
        mapping[2] = 4
        mapping[3] = 2

Then add the columns normally:
        self.list.SetStringItem( x, 0, data[0] )
        self.list.SetStringItem( x, 0, data[1] )
        self.list.SetStringItem( x, 0, data[4] )
        self.list.SetStringItem( x, 0, data[2] )

And finally, in the sorting function, you would use the mapping
before using the data in musicdata:
        item1 = musicdata[key1][mapping[self.col]]
        item2 = musicdata[key2][mapping[self.col]]

Hope this helped (and I hope I'm not misunderstanding your
problem). I've had to do something similar myself in an MP3
organizer application I'm writing where I display a user-configurable
set of attributes of a list of MP3s in a wxListCtrl.

Y.

···

On Wednesday, March 07, 2001 at 11:29:18 PM, Stephen Aichele wrote:

Hello. I hope this is useful to someone. I've found what (I feel) is a limitation with
the column-clicking/sorting feature(s) of wxListCtrl. What it boils down to is this:
You have a tuple, list, or dictionary, and you want to add values from given indices
to your wxListCtrl. Furthermore, you want to be able to sort the different columns with
OnColClick.

Here's the problem: suppose your list contains 20 items, but you only want
to add 4 of them to the ListCtrl. On top of that, you may want to a) add items beyond
the 4th index - i.e., List[3] - (remember, you only have 4 columns), or b) you want to
add them out of order - i.e., List[2], List[0], List[3]... In each of these two cases, you're
asking for weird behavior to result from column clicking/sorting.

Solution: make sure that all of the data you want to put into the ListCtrl is a) at or below the
List's index number which corresponds to the number of columns in your ListCtrl minus 1.
The code below uses a dictionary of key/value pairs- in this case we're talking
about the index of the item in the VALUES list. Key doesn't seem to matter. And lest I forget,
b) make sure you add the items to the ListCtrl in the order they are found in your original data
structure.

hope this helps, if not let me know so we can pinpoint this problem. I really like ListCtrl and would
hate to give it up.

CODE:

#!/usr/bin/env python

### this is just a test script showing a limitation in the
### column clicking feature of wxListCtrl for wxPython

from wxPython.wx import *

musicdata = {
12 : ["George", "Praying For Time", "Silly","aaaaa", "ksadjflkjasdf"],
3 : ("Bad", "The Price Of Love", "SpeakEnglishOrDie", "bbbbb","kfdkjdkjdwwwww"),
1 : ("DNA", "Tom's Diner", "Rock", "ccccc", "mmmmm"),
4 : ("Gloria", "Here We Are", "Rock", "gggggg", "wwqfkdsjf"),
}

class ListCtrlTest(wxFrame):
    def __init__(self, parent, ID, title, position, size):

        wxFrame.__init__(self, parent, ID, title,
                         wxDefaultPosition, wxSize(429, 333))
        
        tID = wxNewId()

        self.list = wxListCtrl(self, tID,
                               style=wxLC_REPORT|wxSUNKEN_BORDER)

        self.list.InsertColumn(0, "Artist")
        self.list.InsertColumn(1, "Title", wxLIST_FORMAT_RIGHT)
        self.list.InsertColumn(2, "Genre")
        self.list.InsertColumn(3, "Garbage")
        
        items = musicdata.items()
        
        for x in range(len(items)):
            key, data = items

            self.list.InsertStringItem(x, data[0])
            self.list.SetStringItem(x, 1, data[1]) ## 0<1<2<3 works
            self.list.SetStringItem(x, 2, data[2])
            self.list.SetStringItem(x, 3, data[3])
            self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[3]) ## 0<3<1<2 doesn't work
# self.list.SetStringItem(x, 2, data[1]) ## items out of order
# self.list.SetStringItem(x, 3, data[2])
# self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[1]) ## 0<1<2<4 doesn't work.
# self.list.SetStringItem(x, 2, data[2]) ## items out of range
# self.list.SetStringItem(x, 3, data[4])
# self.list.SetItemData(x, key)

# self.list.InsertStringItem(x, data[0])
# self.list.SetStringItem(x, 1, data[1])
# self.list.SetStringItem(x, 2, data[4]) ## 0<1<4<2 doesn't work.
# self.list.SetStringItem(x, 3, data[2]) ## items out of order and out of range
# self.list.SetItemData(x, key)
        
        self.list.SetColumnWidth(0, wxLIST_AUTOSIZE)
        self.list.SetColumnWidth(1, wxLIST_AUTOSIZE)
                
        self.currentItem = 0
        EVT_LIST_ITEM_SELECTED(self, tID, self.OnItemSelected)
        EVT_LIST_ITEM_ACTIVATED(self, tID, self.OnItemActivated)
        EVT_LIST_COL_CLICK(self, tID, self.OnColClick)
        
    def OnItemSelected(self, event):
        self.currentItem = event.m_itemIndex

    def OnItemActivated(self, event):
        self.currentItem = event.m_itemIndex

    def OnColClick(self, event):
        self.col = event.m_col
        self.list.SortItems(self.ColumnSorter)

    def ColumnSorter(self, key1, key2):
        item1 = musicdata[key1][self.col]
        item2 = musicdata[key2][self.col]
        if item1 == item2: return 0
        elif item1 < item2: return -1
        else: return 1

class MyApp(wxApp):
    def OnInit(self):
        frame = ListCtrlTest(NULL, -1, "ListCtrl Test", wxPoint(200,200), wxSize(429,384))
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

if __name__ == "__main__":
   app = MyApp(0)
   app.MainLoop()

    Y.

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

Yumpee -

wow, thanks for that reply! That solution makes a lot of sense, indeed.
Also, thank you for including the code - makes it much easier to figure out
the solution.

-S

···

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users

> Can I have your babies? :wink:

Err, no, I don't think so. But you're welcome anyway.

*grin*

> That worked, thankyou very very very much.

Wow. That must be some program you're working on!

I just have a fundemental loathing of debugging single
problems that take over a fortnight to fix... I seem
to be missing fairly simple things in both Python and
wxPython on a regular basis, being more accustomed to
dealing with perl/cgi code, and the debug runs are
getting tedious to say the least.

The program is actually quite simple - less than 3 kloc
in my bit of it, plus some fairly major lisp code that
I only have to wrap, not modify...

Regards,
Denny

···

On Wed, 7 Mar 2001, Tim Hochberg wrote:

----------------------------------------------------------
Denny De La Haye \ www-edc.eng.cam.ac.uk/~djd33
Engineering Design Centre, \ www-edc.eng.cam.ac.uk
Department of Engineering, \ www.eng.cam.ac.uk
University of Cambridge, UK \ www.cam.ac.uk
----------------------------------------------------------
"Only two things are infinite, the universe and human stupidity,
and I'm not sure about the former." (Albert Einstein)

_______________________________________________
wxPython-users mailing list
wxPython-users@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/wxpython-users