2010-08-09 4 views
3

wxPython을 사용하는 양식에서 다른 listctrl의 선택에 따라 listctrl의 값 목록을 변경하고 싶습니다. 이렇게하려면 제어 객체의 EVT_LIST_ITEM_SELECTEDEVT_LIST_ITEM_DESELECTED 이벤트에 연결된 메서드를 사용하여 Publisher.sendMessage을 호출합니다. 변경 될 컨트롤에는 해당 게시자의 구독자 인 메서드가 있습니다. 이 작동합니다 : 첫 번째 listctrl 클릭 할 때 두 번째 새로 고칩니다.Listctrl에 정확히 한 번만 응답하십시오.

문제는 데이터베이스에서 데이터를 새로 고쳐야하며 모든 선택 및 선택 취소시 메시지가 전송되어야한다는 것입니다. 즉, 단순히 하나의 항목을 클릭하더라도 데이터베이스는 두 번 쿼리됩니다 (한 번은 선택 취소, 다시 한 번 선택). 5 번 항목을 여러 번 선택하려면 Shift 키를 누른 상태에서 클릭하면 5 회의 통화가 이루어집니다. listctrl이 개별 선택이 아닌 집합에 응답하도록하는 방법이 있습니까?

답변

4

에 밀어 수 있습니다 : 나는 것을보고

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() 
+1

이 솔루션을 이용해 주셔서 감사합니다. 매우 도움이됩니다. –

0

EVT_LIST_ITEM_RIGHT_CLICK 시도해 볼 수 있습니다. 그게 효과가있다. 그렇지 않으면 플래그를 사용하여 선택 이벤트가 발생할 때마다 플래그를 확인하여 데이터베이스를 쿼리해야하는지 여부를 확인해야합니다. 순수 파이썬 위젯 인 UltimateListCtrl도 있습니다.이 도구도 해킹 할 수 있습니다.

+0

을 이벤트를 만들었지 만 실제로 캡처하려고하는 것은 마우스 왼쪽 버튼입니다. 플래그를 설정하는 것을 고려했지만 Selected 이벤트가 마지막 이벤트인지 알 수있는 방법이 없으므로 해당 플래그를 사용할 방법이 없습니다. – Allan

0

사용자 정의 이벤트 핸들러 가장 좋은 해결책은 정확히 한 번만 후속 절차를 실행하기 위해 플래그 wx.CallAfter를 사용하는 것 같다

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()