如何将wxpython listctrl与onclick按钮事件绑定
How to bind wxpython listctrl with onclick button event
我有一个 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()
它不起作用但是。我怎样才能做到这一点?
在我看来,列表控件有点难用。基本上,您需要获取您所在的行,并对您感兴趣的列进行硬编码。像这样的东西应该可以让您开始:
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,因为它看起来更易于使用并且提供了更多开箱即用的功能。这里有几个链接:
该事件将传递来自 listctrl 的 selected 项目的索引。
使用索引获取 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 才能 select 一个项目。在这种情况下,您可能已经使用第一种方法获得了相同的结果,而无需首先定义按钮,并且使用此方法您现在必须检查是否没有 selected (ind不得为 -1)。
我有一个 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()
它不起作用但是。我怎样才能做到这一点?
在我看来,列表控件有点难用。基本上,您需要获取您所在的行,并对您感兴趣的列进行硬编码。像这样的东西应该可以让您开始:
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,因为它看起来更易于使用并且提供了更多开箱即用的功能。这里有几个链接:
该事件将传递来自 listctrl 的 selected 项目的索引。
使用索引获取 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 才能 select 一个项目。在这种情况下,您可能已经使用第一种方法获得了相同的结果,而无需首先定义按钮,并且使用此方法您现在必须检查是否没有 selected (ind不得为 -1)。