Вопрос

Я работаю над формой, используя WxPython, где я хочу, чтобы список значений ListCtrl изменить на основе выбора другого listctrl. Для этого я использую методы, связанные с контрольным объектом EVT_LIST_ITEM_SELECTED а также EVT_LIST_ITEM_DESELECTED События для вызова Publisher.sendMessage. Отказ Контроль, который должен быть изменен, имеет метод, который является подписчиком для этого издателя. Это работает: когда нажал первый listctrl, второй обновляется.

Проблема в том, что данные должны быть обновлены из базы данных, и сообщение отправляется на каждый выбор и отмените. Это означает, что даже если я просто нажимаю на один элемент, база данных запрашивается дважды (один раз для отмените, затем снова для выбора). Если я Shift-Щелкните к Multi-Select 5 элементов, то 5 вызовов. Есть ли способ иметь ответ «listCtrl» на множество, а не на отдельные выборы?

Это было полезно?

Решение

Лучшее решение, кажется, нужно использовать wx.CallAfter С флагом для выполнения процедуры последующей деятельности ровно один раз:

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

Другие советы

Вы можете попробовать EVT_LIST_ITEM_RIGHT_CLICK. Это должно работать. В противном случае вы хотите использовать флаг и проверять указанный флаг каждый раз, когда события выбора стреляются, чтобы увидеть, нужно ли запрашивать базу данных или нет. Есть также UltimatelistCTRL, чистый виджет Python, который вы, вероятно, можете взломать это тоже.

Вы можете нажать на пользовательский обработчик событий

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()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top