是否有可能在一个窗口中有两个可排序的ListCtrls?

时间:2014-08-19 20:52:17

标签: python wxpython wxwidgets mixins

我有一小段代码,左边的ListCtrl一切都很好:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.lib.mixins.listctrl as listmix

class FillBD2Frame(wx.Frame):
  def __init__(self):
    wx.Frame.__init__(self, None, wx.ID_ANY, "FillBD2", size=(400, 300))
    self.Centre()
    FillBD2(self)

class MyListCtrl(wx.ListCtrl):
  def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
    wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
    self.parent=parent
    self.DataMap={}

class FillBD2(wx.Panel, listmix.ColumnSorterMixin):
  def __init__(self, parent):
    wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.WANTS_CHARS)

    self.parent=parent
    self.list_ctrl1=MyListCtrl(self, style=wx.LC_REPORT|wx.BORDER_SUNKEN|wx.LC_SORT_ASCENDING)
    self.list_ctrl2=MyListCtrl(self, style=wx.LC_REPORT|wx.BORDER_SUNKEN|wx.LC_SORT_ASCENDING)
    self.testen=  wx.Button(self, 2, "&test",  (-1, -1), wx.DefaultSize)

    gr=2
    self.list_ctrl1.InsertColumn(0, 'path',                              width=30*gr)
    self.list_ctrl1.InsertColumn(1, 'name',                              width=30*gr)
    self.list_ctrl1.InsertColumn(2, 'size(real)',  wx.LIST_FORMAT_RIGHT, width=15*gr)
    self.list_ctrl1.InsertColumn(3, 'size(dest)',  wx.LIST_FORMAT_RIGHT, width=15*gr)
    listmix.ColumnSorterMixin.__init__(self, 4)

    self.list_ctrl1.DataMap={
      0:("pth1", "nam1", 62, 70),
      1:("pth2", "nam2", 22, 30),
      2:("pth3", "nam3", 57, 60),
      4:("pth4", "nam4",  9, 10)
    }
    self.fillListCtrl(self.list_ctrl1, 1)


    self.list_ctrl2.InsertColumn(0, 'path',                              width=30*gr)
    self.list_ctrl2.InsertColumn(1, 'name',                              width=30*gr)
    self.list_ctrl2.InsertColumn(2, 'size(dest)',  wx.LIST_FORMAT_RIGHT, width=15*gr)
#    listmix.ColumnSorterMixin.__init__(self, 3)

    self.list_ctrl2.DataMap={
      0:("pth5", "nam5", 45, 50),
      1:("pth6", "nam6", 81, 90),
      2:("pth7", "nam7", 33, 40),
      4:("pth8", "nam8", 13, 20)
    }
    self.fillListCtrl(self.list_ctrl2, 2)


    self.list_ctrl1.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick1)
    self.list_ctrl2.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick2)

    vsizer=wx.BoxSizer(wx.VERTICAL)
    bsizer=wx.BoxSizer(wx.HORIZONTAL)
    hsizer=wx.BoxSizer(wx.HORIZONTAL)

    bsizer.Add(self.testen,   0, wx.ALL, 5)
    hsizer.Add(self.list_ctrl1, 1, wx.ALL|wx.EXPAND, 1)
    hsizer.Add(self.list_ctrl2, 1, wx.ALL|wx.EXPAND, 1)

    vsizer.Add(bsizer, 0, wx.ALL, 5)
    vsizer.Add(hsizer, 1, wx.ALL|wx.EXPAND, 5)

    self.SetSizer(vsizer)
    vsizer.Fit(self)
    self.list_ctrl1.SetFocus()
    self.list_ctrl1.Select(0, 1)

  def fillListCtrl(self, ctrl, ctrl_nr=1):
    ctrl.DeleteAllItems()
    ctrl.Refresh()
    index=0
    for key, data in ctrl.DataMap.items():
      ctrl.InsertStringItem(index, data[0])
      ctrl.SetStringItem(index, 1, data[1])
      ctrl.SetStringItem(index, 2, str(data[2]))
      if ctrl_nr==1:
        ctrl.SetStringItem(index, 3, str(data[3]))

      ctrl.SetItemData(index, key)
      index+=1
    ctrl.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)


  def GetListCtrl(self):
    return(self.list_ctrl1)

  def OnColClick1(self, event):
    self.itemDataMap=self.list_ctrl1.DataMap
    event.Skip()
  def OnColClick2(self, event):
    self.itemDataMap=self.list_ctrl2.DataMap
    event.Skip()


if __name__=='__main__':
  app=wx.App()
  frame=FillBD2Frame().Show()
  app.MainLoop()

但是如果我想要正确的ListCtrl也可以排序,我该怎么做?

如果我取消注释第二个listmix.ColumnSorterMixin。 init (),左侧ListCtrl的排序会混淆,而右侧的排序仍然无法排序......

GetListCtrl方法应如何决定,它应返回哪个ListCtrl ......!

1 个答案:

答案 0 :(得分:1)

您需要稍微重构代码才能使其正常工作。由于ColumnSorterMixin要求ListCtrl存在(根据源),听起来你需要将mixin子类化为wx.Panel,创建一个继承自两者的类。因此,您需要创建一个具有所有必需方法的面板,并且只需将列表控件作为其唯一的窗口小部件。然后,每次实例化此新类时,都可以将其添加到顶级面板。这是一种对我有用的方法:

import wx
import wx.lib.mixins.listctrl as listmix

class FillBD2Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "FillBD2", size=(400, 300))
        self.Centre()
        FillBD2(self)

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
        wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
        self.parent=parent
        self.DataMap={}

class FillPanel(wx.Panel, listmix.ColumnSorterMixin):

    def __init__(self, parent, DataMap, ctrl_type=1):
        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.WANTS_CHARS)
        self.parent = parent

        self.list_ctrl = MyListCtrl(self, 
                                    style=wx.LC_REPORT|wx.BORDER_SUNKEN|wx.LC_SORT_ASCENDING)

        gr=2
        self.list_ctrl.InsertColumn(0, 'path',                              width=30*gr)
        self.list_ctrl.InsertColumn(1, 'name',                              width=30*gr)

        if ctrl_type == 1:
            self.list_ctrl.InsertColumn(2, 'size(real)',  wx.LIST_FORMAT_RIGHT, width=15*gr)
            self.list_ctrl.InsertColumn(3, 'size(dest)',  wx.LIST_FORMAT_RIGHT, width=15*gr)
        elif ctrl_type == 2:
            self.list_ctrl.InsertColumn(2, 'size(dest)',  wx.LIST_FORMAT_RIGHT, width=15*gr)

        listmix.ColumnSorterMixin.__init__(self, 4)

        self.list_ctrl.DataMap = DataMap
        self.fillListCtrl(ctrl_type)
        self.list_ctrl.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list_ctrl, 1, wx.EXPAND)
        self.SetSizer(sizer)


    def fillListCtrl(self, ctrl_nr=1):
        self.list_ctrl.DeleteAllItems()
        self.list_ctrl.Refresh()
        index=0
        for key, data in self.list_ctrl.DataMap.items():
            self.list_ctrl.InsertStringItem(index, data[0])
            self.list_ctrl.SetStringItem(index, 1, data[1])
            self.list_ctrl.SetStringItem(index, 2, str(data[2]))
            if ctrl_nr==1:
                self.list_ctrl.SetStringItem(index, 3, str(data[3]))

            self.list_ctrl.SetItemData(index, key)
            index+=1
        self.list_ctrl.SetItemState(0, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)

    def GetListCtrl(self):
        return(self.list_ctrl)

    def OnColClick(self, event):
        self.itemDataMap = self.list_ctrl.DataMap
        event.Skip()


class FillBD2(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY, style=wx.WANTS_CHARS)
        self.parent=parent

        DataMap_1={
            0:("pth1", "nam1", 62, 70),
            1:("pth2", "nam2", 22, 30),
            2:("pth3", "nam3", 57, 60),
            4:("pth4", "nam4",  9, 10)
        }

        DataMap_2={
            0:("pth5", "nam5", 45, 50),
            1:("pth6", "nam6", 81, 90),
            2:("pth7", "nam7", 33, 40),
            4:("pth8", "nam8", 13, 20)
        }

        self.testen=  wx.Button(self, -1, "&test",  (-1, -1), wx.DefaultSize)

        list_panel = FillPanel(self, DataMap_1)
        list_panel_2 = FillPanel(self, DataMap_2, ctrl_type=2)

        # create sizers
        vsizer = wx.BoxSizer(wx.VERTICAL)
        hsizer = wx.BoxSizer(wx.HORIZONTAL)

        vsizer.Add(self.testen, 0, wx.ALL, 5)
        hsizer.Add(list_panel, 1, wx.ALL|wx.EXPAND, 5)
        hsizer.Add(list_panel_2, 1, wx.ALL|wx.EXPAND, 5)
        vsizer.Add(hsizer, 1, wx.EXPAND)
        self.SetSizer(vsizer)

if __name__=='__main__':
    app = wx.App()
    frame = FillBD2Frame().Show()
    app.MainLoop()

我需要指出的另一件事。你已经将按钮的id设置为2,这是一件非常糟糕的事情。你需要让wxPython管理ID,特别是那些低于100的ID,因为它们往往是wxPython内部使用的特殊ID。要使wxPython动态分配ID,请使用wx.ID_ANY或-1,就像在代码的其他部分中所做的那样。