Reputation: 1133
I am currently building a GUI, and im using listbox's, the user will double click an item in a list box and the selected item is passed to the code. This works fine, but the problem I am having is that I cannot seem to link the DoubleClick event to a single list box, I just get errors and the program wont run, whenever i try and add an identifier.
The code that works but with no identifer is:
serverlistbox=wx.ListBox(panel1, -1, (300,80), (180,180), serverfilelist, wx.LB_SINGLE)
serverlistbox.SetSelection(0)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick)
And the function that handles the data:
def doubleclick(self,event):
index = event.GetSelection()
downloadselect = serverfilelist[index]
wx.MessageBox('Starting download of ' +str(serverfilelist[index]))
So the EVT is the important bit, i want to link it ONLY to the serverlist box, opposed to all my list box's. Ive tried:
self.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick, self.serverlistbox)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.serverlistbox, self.doubleclick)
self.Bind(wx.EVT_LISTBOX_DCLICK, -1, self.doubleclick)
All of the above fail. Please help!!!
Upvotes: 1
Views: 5558
Reputation: 5569
The previous posts direct you to a solution but there could be some other points which could be clarified about whats could be the problem.
wx Events are processed through a hierarchy of Python objects. Therefore if an event type is bound to, but the coder is not aware of where the event terminates you might not get the event to the event handler. In your line
self.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick, self.serverlistbox)
you can not tell who the parent widget is of self.serverlistbox. One example above has the parent as "panel1". Did panel1 have a handler for EVT_LISTBOX_DCLICK? Did that handler pass up the event to its own parent? Did you use event.Skip() to do this?
There is not just the issue of referencing Python objects out of scope, which makes a helpful traceback/exception but there is also the issue of which widget gets the event and whether the event gets passed up to the object with the bounded event handler.
Here is an example which can help show the propogation/rightly bounded event handler removing Python scoping issues:
#
# http://stackoverflow.com/questions/8960808/wxpython-linking-a-double-click-event-to-specific-list-boxs-opposed-to-all
import sys
import wx
__doc__ = """Usage:
python.exe doubleclic.py
python.exe doubleclic.py panel
python.exe doubleclic.py panel frame
"""
def OnDoubleClick_ListBox_Widget_Handler(event):
textctrl.AppendText('\nListBox: ' + event.GetString() + '\n')
if 'panel' in sys.argv: event.Skip()
def OnDoubleClick_Panel_Widget_Handler(event):
game_selected = listbox.GetStringSelection()
textctrl.AppendText('Panel: ' + event.GetString() + '\n')
if 'panel' in sys.argv and 'frame' in sys.argv: event.Skip()
def OnDoubleClick_Frame_Widget_Handler(event):
game_selected = listbox.GetStringSelection()
textctrl.AppendText('Frame: ' + event.GetString() + '\n')
if __name__ == "__main__":
app = wx.App()
frame = wx.Frame(None, title="Demo wx.EVT_LISTBOX_DCLICK event binding and propogation")
panel = wx.Panel(frame)
listbox = wx.ListBox(panel, choices=['rock', 'paper', 'scissor'], name='ListBox')
textctrl = wx.TextCtrl(panel, style=wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_DONTWRAP, name='Wrong Widget')
textctrl.AppendText(__doc__)
textctrl.AppendText("command line given: \n " + ' '.join(sys.argv) + '\n\n')
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(listbox, 0, wx.EXPAND|wx.ALL)
sizer.Add(textctrl, 1, wx.EXPAND|wx.ALL)
panel.SetSizer(sizer)
listbox.Bind(wx.EVT_LISTBOX_DCLICK, OnDoubleClick_ListBox_Widget_Handler)
panel.Bind(wx.EVT_LISTBOX_DCLICK, OnDoubleClick_Panel_Widget_Handler)
frame.Bind(wx.EVT_LISTBOX_DCLICK, OnDoubleClick_Frame_Widget_Handler)
frame.Show()
app.MainLoop()
Hope this helps those coming to this issue much later after the initial post.
Upvotes: 0
Reputation: 85615
your first option should work:
self.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick, self.serverlistbox)
You have some problems that make the code fail: you are indexing serverfilelist
in the doubleclick
method. However, that list is not accessible inside the method. Probably you should do something like:
self.serverfilelist = serverfilelist
self.serverlistbox = wx.ListBox(panel1, -1, (300,80), (180,180), self.serverfilelist, wx.LB_SINGLE)
self.serverlistbox.SetSelection(0)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick, self.serverlistbox)
def doubleclick(self, event):
index = event.GetSelection()
downloadselect = self.serverfilelist[index]
wx.MessageBox('Starting download of %s' % str(downloadselect)
Also if you instantiate serverlistbox as an attribute of the class:
self.serverlistbox = wx.ListBox(panel1, ....
then you could call directly self.serverlistbox.GetSelection
in the method without using the event.
I recommend however the use of:
downloadselect = self.serverlistbox.GetStringSelection()
Then, your method is simplified to:
def doubleclick(self, event):
downloadselect = self.serverlistbox.GetStringSelection()
wx.MessageBox('Starting download of %s' % downloadselect
Upvotes: 1
Reputation: 69172
Can you bind to the listbox (instead of whatever self
is)? Something like:
self.serverlistbox.Bind(wx.EVT_LISTBOX_DCLICK, self.doubleclick)
(If this doesn't do what you want, more information would be helpful, especially posting the Traceback and the smallest piece of code possible that runs but still shows the error.)
Upvotes: 0