【问题标题】:How to bind wxpython listctrl with onclick button event如何将 wxpython listctrl 与 onclick 按钮事件绑定
【发布时间】:2017-11-26 21:24:16
【问题描述】:

我有一个 wxpython listctrl ,它包含 4 列 [A, B, C, D]。用户从 listctrl 中选择任何一行。现在我的 gui 中有一个按钮,所以当我单击该按钮时,我想从该选定行打印列 D 的值。 例如让用户选择了这一行:
[Python, JAVA, MATLAB, RUBY]
现在,如果用户单击按钮,它应该给出输出:RUBY
我正在以这种方式绑定 THE BUTTON

self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnPlot, self.list) 

self.list.Append((j[0],j[1],j[2],j[3]))     #values are inserted in the listctrl 

我定义的 OnPlot 事件为: def OnPlot(self, event): click = event.GetText()

它不起作用,但是。我怎样才能做到这一点?

【问题讨论】:

    标签: onclick wxpython buttonclick listctrl event-binding


    【解决方案1】:

    该事件将从 listctrl 传递所选项目的索引。
    使用索引获取 listctrl 中的项目和列,在本例中为 3.
    获取列的文本。
    即:

    def on_plot(self, event):
        ind = event.GetIndex()
        item = self.list_ctrl.GetItem(ind,3)
        print item.GetText()
    

    这假设您已经像这样绑定 listctrl:

    self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_plot, self.list_ctrl)
    

    编辑:
    关于您的评论和对问题标题的编辑。 您不能将任意事件绑定到某物。一个按钮有一组定义的事件,就像一个 listctrl 一样,并且永远不会相遇。解决问题的方法是将按钮绑定到按钮事件。

    plot_button.Bind(wx.EVT_BUTTON, self.on_plot)
    

    然后像这样定义on_plot

    def on_plot(self, event):
        ind = self.list_ctrl.GetFirstSelected()
        if ind >=0:
            item = self.list_ctrl.GetItem(ind,3)
            print item.GetText()
    

    正如您将看到的,它实现了相同的最终结果,但是它很大,但是您已经不得不单击 listctrl 来选择一个项目。在这种情况下,您可能已经使用第一种方法获得了相同的结果,而不必首先定义按钮,并且使用此方法您现在必须检查是否没有选择任何内容(ind 不得为 -1 )。

    【讨论】:

    • 我想在用户单击按钮时打印 D 列。所以我必须以这种方式绑定按钮: self.plot_btn.Bind(wx.EVT_BUTTON, self.OnPlot, self.plot_btn) 现在如果我按照你所说的方式定义 onplot ,它会给我错误 CommandEvent has no attribute 'GetIndex '
    • 因为你说你的绑定语句是self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnPlot, self.list) 我假设点击发生在ListCtrl self.list 因为按钮没有eventListCtrl 有.您将不得不发布您的代码,而不仅仅是那个 sn-p。我想您必须让按钮事件触发listCtrl 事件,这是一种奇怪的安排方式,但并非不可能。
    • 我以这种方式绑定了列表:'self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.get_selected_item, self.list)' 并将 get_selected_item 定义为 'def get_selected_item(self, event): self.plot_list .append(event.GetText())'
    • 没关系,但请阅读wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind 了解它的工作原理以及可能会产生不可预见的后果
    【解决方案2】:

    在我看来,列表控件很难使用。基本上,您将需要获取您所在的行并对您感兴趣的列进行硬编码。这样的事情应该让您开始:

    import wx
    
    
    class MyForm(wx.Frame):
    
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")
    
            # Add a panel so it looks the correct on all platforms
            panel = wx.Panel(self, wx.ID_ANY)
            self.index = 0
            self.current_selection = None
    
            self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                                         style=wx.LC_REPORT
                             |wx.BORDER_SUNKEN
                             )
            self.list_ctrl.InsertColumn(0, 'Subject')
            self.list_ctrl.InsertColumn(1, 'Due')
            self.list_ctrl.InsertColumn(2, 'Location', width=125)
            self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected)
    
            btn = wx.Button(panel, label="Add Line")
            btn.Bind(wx.EVT_BUTTON, self.add_line)
    
            data_getter_btn = wx.Button(panel, label='Get all data')
            data_getter_btn.Bind(wx.EVT_BUTTON, self.on_get_data)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
            sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
            sizer.Add(data_getter_btn, 0, wx.ALL|wx.CENTER, 5)
            panel.SetSizer(sizer)
    
        def add_line(self, event):
            line = "Line %s" % self.index
            self.list_ctrl.InsertStringItem(self.index, line)
            self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
            self.list_ctrl.SetStringItem(self.index, 2, "USA")
            self.index += 1
    
        def on_item_selected(self, event):
            self.current_selection = event.m_itemIndex
    
        def on_get_data(self, event):
            if self.current_selection:
                print self.current_selection
                item = self.list_ctrl.GetItem(itemId=self.current_selection, col=2)
                print item.GetText()
    
    #----------------------------------------------------------------------
    # Run the program
    if __name__ == "__main__":
        app = wx.App(False)
        frame = MyForm()
        frame.Show()
        app.MainLoop()
    

    上面的代码将打印出当前选择(行号)和第 3 列的文本。如果你想打印出所有行和列的文本,那么你可以这样做:

    import wx
    
    ########################################################################
    class MyForm(wx.Frame):
    
        #----------------------------------------------------------------------
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")
    
            # Add a panel so it looks the correct on all platforms
            panel = wx.Panel(self, wx.ID_ANY)
            self.index = 0
    
            self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                             style=wx.LC_REPORT
                             |wx.BORDER_SUNKEN
                             )
            self.list_ctrl.InsertColumn(0, 'Subject')
            self.list_ctrl.InsertColumn(1, 'Due')
            self.list_ctrl.InsertColumn(2, 'Location', width=125)
    
            btn = wx.Button(panel, label="Add Line")
            btn2 = wx.Button(panel, label="Get Data")
            btn.Bind(wx.EVT_BUTTON, self.add_line)
            btn2.Bind(wx.EVT_BUTTON, self.get_data)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
            sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
            sizer.Add(btn2, 0, wx.ALL|wx.CENTER, 5)
            panel.SetSizer(sizer)
    
        #----------------------------------------------------------------------
        def add_line(self, event):
            line = "Line %s" % self.index
            self.list_ctrl.InsertStringItem(self.index, line)
            self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
            self.list_ctrl.SetStringItem(self.index, 2, "USA")
            self.index += 1
    
        #----------------------------------------------------------------------
        def get_data(self, event):
            """"""
            count = self.list_ctrl.GetItemCount()
            cols = self.list_ctrl.GetColumnCount()
            for row in range(count):
                for col in range(cols):
                    item = self.list_ctrl.GetItem(itemId=row, col=col)
                    print item.GetText()
    
    #----------------------------------------------------------------------
    # Run the program
    if __name__ == "__main__":
        app = wx.App(False)
        frame = MyForm()
        frame.Show()
        app.MainLoop()
    

    完成这类事情的一种更简单的方法是将对象与每一行相关联。这是一个例子:

    import wx
    
    ########################################################################
    class Car(object):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, make, model, year, color="Blue"):
            """Constructor"""
            self.make = make
            self.model = model
            self.year = year
            self.color = color
    
    
    ########################################################################
    class MyPanel(wx.Panel):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, parent):
            """Constructor"""
            wx.Panel.__init__(self, parent)
    
            rows = [Car("Ford", "Taurus", "1996"),
                    Car("Nissan", "370Z", "2010"),
                    Car("Porche", "911", "2009", "Red")
                    ]
    
            self.list_ctrl = wx.ListCtrl(self, size=(-1,100),
                                    style=wx.LC_REPORT
                                    |wx.BORDER_SUNKEN
                                    )
            self.list_ctrl.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onItemSelected)
            self.list_ctrl.InsertColumn(0, "Make")
            self.list_ctrl.InsertColumn(1, "Model")
            self.list_ctrl.InsertColumn(2, "Year")
            self.list_ctrl.InsertColumn(3, "Color")
    
            index = 0
            self.myRowDict = {}
            for row in rows:
                self.list_ctrl.InsertStringItem(index, row.make)
                self.list_ctrl.SetStringItem(index, 1, row.model)
                self.list_ctrl.SetStringItem(index, 2, row.year)
                self.list_ctrl.SetStringItem(index, 3, row.color)
                self.myRowDict[index] = row
                index += 1
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
            self.SetSizer(sizer)
    
        #----------------------------------------------------------------------
        def onItemSelected(self, event):
            """"""
            currentItem = event.m_itemIndex
            car = self.myRowDict[currentItem]
            print car.make
            print car.model
            print car.color
            print car.year
    
    ########################################################################
    class MyFrame(wx.Frame):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self):
            """Constructor"""
            wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")
            panel = MyPanel(self)
            self.Show()
    
    #----------------------------------------------------------------------
    if __name__ == "__main__":
        app = wx.App(False)
        frame = MyFrame()
        app.MainLoop()
    

    坦率地说,我真的不再使用 ListCtrl 了。我更喜欢使用 ObjectListView,因为它看起来更容易使用并且提供了更多开箱即用的功能。这里有几个链接:

    【讨论】:

      猜你喜欢
      • 2011-10-13
      • 2017-11-25
      • 2014-06-29
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多