Domanda

Sto lavorando su un modulo utilizzando wxPython in cui desidero che l'elenco dei valori di listctrl cambi in base alla selezione di un altro listctrl.Per fare ciò, utilizzo metodi collegati agli oggetti di controllo EVT_LIST_ITEM_SELECTED E EVT_LIST_ITEM_DESELECTED eventi da chiamare Publisher.sendMessage.Il controllo da modificare ha un metodo che è un sottoscrittore di quell'editore.Funziona:quando si fa clic sul primo listctrl, il secondo viene aggiornato.

Il problema è che i dati devono essere aggiornati dal database e viene inviato un messaggio per ogni selezione e deselezione.Ciò significa che anche se faccio semplicemente clic su un elemento, il database viene interrogato due volte (una volta per la deselezione, poi di nuovo per la selezione).Se faccio clic tenendo premuto il tasto Maiusc per selezionare più 5 elementi, vengono effettuate 5 chiamate.Esiste un modo per far sì che listctrl risponda al set, piuttosto che alle singole selezioni?

È stato utile?

Soluzione

La soluzione migliore sembra essere usare wx.CallAfter con un flag per eseguire la procedura di follow-up esattamente una volta:

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

Altri suggerimenti

Puoi provare EVT_LIST_ITEM_RIGHT_CLICK.Dovrebbe funzionare.Altrimenti dovresti usare un flag e controllare detto flag ogni volta che si attiva l'evento di selezione per vedere se è necessario interrogare il database o meno.C'è anche UltimateListCtrl, un widget Python puro, che probabilmente puoi hackerare anche tu per fare questo.

Puoi inserire un gestore eventi personalizzato

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()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top