【问题标题】:Auto compute in a wxPython ListCtrl在 wxPython ListCtrl 中自动计算
【发布时间】:2014-03-04 19:42:09
【问题描述】:

我正在尝试在事件发生后自动计算总计列,而不使用按钮进行计算。我的定义函数总循环是错误的,我已经被困了几个小时,想知道要使用哪个 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()

【问题讨论】:

  • 如果你能弄清楚如何用一个按钮做到这一点,让它工作,然后以编程方式创建事件,模拟用户按下按钮

标签: python wxpython wxwidgets listctrl


【解决方案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)

希望对你有帮助,

【讨论】:

  • 感谢您的帮助。只需要对 listctrl 事件进行更多修复。
  • 当我尝试这个时,EVT_LIST_END_LABEL_EDIT 处理程序中的 GetText() 返回每列的预编辑值。
猜你喜欢
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 2011-02-09
  • 2010-12-03
  • 1970-01-01
  • 2011-10-13
相关资源
最近更新 更多