在wxPython ListCtrl中自动计算
我想在发生某个事件后自动计算总计列,而不想设置一个按钮来进行计算。我写的用于计算总计的循环有问题,我已经卡了几个小时,试图找出应该使用哪个列表控件事件。我认为在编辑标签和添加数据行时应该自动计算。请帮帮我!我还是个新手。谢谢! :)
import wx
import wx.lib.mixins.listctrl as listmix
########################################################################
class EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin):
''' TextEditMixin allows any column to be edited. '''
#----------------------------------------------------------------------
def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0):
"""Constructor"""
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.TextEditMixin.__init__(self)
self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginLabelEdit)
def OnBeginLabelEdit(self, event):
if event.m_col == 0:
event.Veto()
elif event.m_col == 4:
event.Veto()
else:
event.Skip()
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.text_ctrl = wx.TextCtrl(self)
rows = [("Ford", "123", "1996", ""),
("Nissan", "432", "2010", ""),
("Porche", "911", "2009", "")
]
self.list_ctrl = EditableListCtrl(self, style=wx.LC_REPORT)
self.list_ctrl.InsertColumn(0, "Somethin")
self.list_ctrl.InsertColumn(1, "Price")
self.list_ctrl.InsertColumn(2, "Qty")
self.list_ctrl.InsertColumn(3, "Total")
self.listitems = set()
self.index = 0
index = 0
for row in rows:
self.list_ctrl.InsertStringItem(index, row[0])
self.list_ctrl.SetStringItem(index, 1, row[1])
self.list_ctrl.SetStringItem(index, 2, row[2])
self.list_ctrl.SetStringItem(index, 3, row[3])
index += 1
btn = wx.Button(self, label="Add Line")
btn.Bind(wx.EVT_BUTTON, self.add_line)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.text_ctrl,0,wx.ALL|wx.EXPAND,5)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(sizer)
self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.total)
def add_line(self, event):
textval = self.text_ctrl.GetValue()
if textval not in self.listitems:
line = "%s" % self.index
self.list_ctrl.InsertStringItem(self.index, line)
self.list_ctrl.SetStringItem(self.index, 1, self.text_ctrl.GetValue())
self.index += 1
self.listitems.add(textval)
print "duplicate detected"
def total(self,event):
count = self.list_ctrl.GetItemCount()
for row in range(count):
itemprice = self.list_ctrl.GetItem(itemId=row, col=1)
itemqty = self.list_ctrl.GetItem(itemId=row, col=2)
itempriceval = itemprice.GetText()
itemqtyval = itemqty.GetText()
total = float(itempriceval)*float(itemqtyval)
self.list_ctrl.SetStringItem(count-1, 5, "%.2f" % total)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY, "Editable List Control")
panel = MyPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
1 个回答
1
好的,试试这个代码给你的 MyPanel
类
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.text_ctrl = wx.TextCtrl(self)
rows = [("Ford", "123", "1996", ""),
("Nissan", "432", "2010", ""),
("Porche", "911", "2009", "")
]
self.list_ctrl = EditableListCtrl(self, style=wx.LC_REPORT, size=(-1, 150))
self.list_ctrl.InsertColumn(0, "Something")
self.list_ctrl.InsertColumn(1, "Price")
self.list_ctrl.InsertColumn(2, "Qty")
self.list_ctrl.InsertColumn(3, "Total")
self.listitems = set()
self.index = 0
index = 0
for row in rows:
self.list_ctrl.InsertStringItem(index, row[0])
self.list_ctrl.SetStringItem(index, 1, row[1])
self.list_ctrl.SetStringItem(index, 2, row[2])
self.list_ctrl.SetStringItem(index, 3, row[3])
index += 1
btn = wx.Button(self, label="Add Line")
btn.Bind(wx.EVT_BUTTON, self.add_line)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.text_ctrl,0,wx.ALL|wx.EXPAND,5)
sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
self.SetSizer(sizer)
self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.total)
def add_line(self, event):
textval = self.text_ctrl.GetValue()
if textval not in self.listitems:
line = str(self.index)
self.list_ctrl.InsertStringItem(self.index, line)
self.list_ctrl.SetStringItem(self.index, 0, self.text_ctrl.GetValue())
self.index += 1
self.listitems.add(textval)
else:
print "duplicate detected"
def total(self,event):
if not event.IsEditCancelled():
count = self.list_ctrl.GetItemCount()
totals = []
try:
for row in range(count):
itemprice = self.list_ctrl.GetItem(itemId=row, col=1)
itemqty = self.list_ctrl.GetItem(itemId=row, col=2)
itempriceval = itemprice.GetText()
itemqtyval = itemqty.GetText()
total = float(itempriceval)*float(itemqtyval)
totals.append(total)
print totals
for row, total in zip(range(count),totals):
self.list_ctrl.SetStringItem(row, 3, "%.2f" % total)
except:
return
else:
print "edit was cancelled"
我做的主要改动在 total()
方法里,特别是 try...except
这部分。这段代码可以防止你在计算总数时出现错误,尤其是当不是所有的总数都能计算出来的时候。我在其他地方也做了一些修改,比如事件绑定(现在是基于编辑结束时触发的),还有一些索引也搞错了(你原本是想把总数写入索引5,实际上应该是3)
希望这对你有帮助,