سؤال

أنا أعمل على نموذج باستخدام Wxpython حيث أريد تغيير قائمة القيم التي يجب تغييرها بناءً على اختيار ListCtrl آخر. للقيام بذلك ، أستخدم طرقًا مرتبطة بكائن التحكم EVT_LIST_ITEM_SELECTED و EVT_LIST_ITEM_DESELECTED أحداث للاتصال Publisher.sendMessage. يحتوي التحكم الذي يجب تغييره على طريقة هي مشترك في هذا الناشر. هذا يعمل: عند النقر فوق ListCtrl الأول ، يتم تحديث الثاني.

المشكلة هي أنه يجب تحديث البيانات من قاعدة البيانات ويتم إرسال رسالة لكل اختيار وإزالة. هذا يعني أنه حتى إذا قمت ببساطة بالنقر فوق عنصر واحد ، يتم الاستعلام عن قاعدة البيانات مرتين (مرة واحدة لإزالة الإزالة ، ثم مرة أخرى للاختيار). إذا انقر فوق انقر إلى 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