Respond zu ListCtrl Änderung genau einmal
Frage
Ich arbeite auf einem Formular mit wxPython, wo ich will ListCtrl die Liste der Werte wollen sich auf die Auswahl eines anderen ListCtrl Basis zu ändern. Um dies zu tun, ich bin mit dem Bereich Controlling EVT_LIST_ITEM_SELECTED
und EVT_LIST_ITEM_DESELECTED
Ereignisse des Objekts zu Call Publisher.sendMessage
verknüpft Methoden. Die Steuerung geändert werden muss, eine Methode, die ein Teilnehmer an diesen Verlag ist. Dies funktioniert:., Wenn die erste ListCtrl angeklickt wird, wird die zweite aufgefrischt
Das Problem ist, dass die Daten aus der Datenbank und eine Meldung aufgefrischt werden muss, wird für jede Auswahl und Abwahl gesendet. Dies bedeutet, dass selbst wenn ich einfach auf ein Element klicken, wird die Datenbank abgefragt zweimal (einmal für die Abwahl, dann wieder für die Auswahl). Wenn ich bei gedrückter Umschalttaste auf Multi-wählt 5 Stück, dann 5 Anrufe bekommen. Gibt es eine Möglichkeit, die ListCtrl reagiert auf das Set zu haben, anstatt die einzelnen Auswahlen?
Lösung
Die beste Lösung zu sein scheint wx.CallAfter
mit einem Flag zu verwenden, um die Follow-up-Prozedur auszuführen, genau einmal:
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.list_ctrl_1 = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(self.list_ctrl_1, 1, wx.EXPAND, 0)
self.list_ctrl_1.InsertColumn(0,"1")
self.list_ctrl_1.InsertStringItem(0,"HELLO1")
self.list_ctrl_1.InsertStringItem(0,"HELLO2")
self.list_ctrl_1.InsertStringItem(0,"HELLO3")
self.list_ctrl_1.InsertStringItem(0,"HELLO4")
self.list_ctrl_1.InsertStringItem(0,"HELLO5")
self.list_ctrl_1.InsertStringItem(0,"HELLO6")
self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected, self.list_ctrl_1)
self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnItemDeselected, self.list_ctrl_1)
self.dirty = False
def Cleanup(self, StringToPrint):
print 'No Longer Dirty!'
self.dirty = False
def OnItemSelected(self,event):
print str(self.__class__) + " - OnItemSelected"
if not self.dirty:
self.dirty = True
wx.CallAfter(self.Cleanup)
event.Skip()
def OnItemDeselected(self,event):
print str(self.__class__) + " - OnItemDeselected"
if not self.dirty:
self.dirty = True
wx.CallAfter(self.Cleanup)
event.Skip()
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()
Andere Tipps
Sie können EVT_LIST_ITEM_RIGHT_CLICK versuchen. Das sollte funktionieren. Sonst würde wollen Sie eine Flagge verwenden und die Überprüfungsflag die Auswahl-Ereignis ausgelöst wird, jedes Mal sehen, ob es die Datenbank oder nicht abfragen muss. Es gibt auch die UltimateListCtrl, ein reiner Python-Widget, dass Sie wahrscheinlich dies auch tun können hacken.
Sie können in einem benutzerdefinierten Ereignishandler drücken
import wx
class MyEventHandler(wx.PyEvtHandler):
def __init__(self,target):
self.target = target
wx.PyEvtHandler.__init__(self)
def ProcessEvent(self,event):
# there must be a better way of getting the event type,
# but I couldn't find it
if event.GetEventType() == wx.EVT_LEFT_DOWN.evtType[0]:
print "Got Mouse Down event"
(item,where) = self.target.HitTest(event.GetPosition())
if item != -1:
print self.target.GetItem(item,0).GetText()
print where
else:
print "Not on list item though"
return True
else:
return False
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.list_ctrl_1 = wx.ListCtrl(self, -1, style=wx.LC_REPORT|wx.SUNKEN_BORDER)
self.myevthandler = MyEventHandler(self.list_ctrl_1)
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
sizer_1.Add(self.list_ctrl_1, 1, wx.EXPAND, 0)
self.list_ctrl_1.InsertColumn(0,"1")
self.list_ctrl_1.InsertStringItem(0,"HELLO1")
self.list_ctrl_1.PushEventHandler(self.myevthandler)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
wx.InitAllImageHandlers()
frame_1 = MyFrame(None, -1, "")
app.SetTopWindow(frame_1)
frame_1.Show()
app.MainLoop()