在虚拟模式下从wxPython ListCtrl / UltimateListCtrl获取列号

时间:2012-07-28 08:00:21

标签: python wxpython

我是wxPython的新手,所以请保持温和。

我正在尝试进行虚拟列表控制,当用户按下鼠标右键时,该控件将通过上下文菜单弹出控制。

从我的一点经验来看,似乎虚拟列表控件喜欢使用“item”(读取:“row”)和“column”数字进行操作。很公平。

当我收到右键单击事件时,我可以通过调用event.GetIndex()来轻松获得行(项)编号。但是如何获取被点击的对象的列号?

import wx
import wx.lib.agw.ultimatelistctrl as ULC

class MyFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Right-click example")
        self.list = MyListCtrl(parent=self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.list, 1, wx.EXPAND)
        self.SetSizer(sizer)

class MyListCtrl(ULC.UltimateListCtrl):
     def __init__(self, parent, *args, **kwargs):
         ULC.UltimateListCtrl.__init__(self, parent, 1, agwStyle=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)

        self.InsertColumn(0, "Column0")
        self.InsertColumn(1, "Column1")
        self.SetItemCount(5)
        # Bindings
        self.Bind(ULC.EVT_LIST_ITEM_RIGHT_CLICK, self.OnRightClick)

    def OnGetItemText(self, item, column):
        return "%d, %d" % (item, column)

    def OnGetItemToolTip(self, item, column):
        pass

    def OnGetItemTextColour(self, item, column):
        pass

    def OnRightClick(self, event):
        # Get the index (i.e. which row was clicked)
        print("OnColRightClick: GetIndex = %r\n" %(event.GetIndex()))
        # How can I get which column was clicked?

if __name__ == "__main__":
    # Start the GUI
    app = wx.App()
    frame = MyFrame()
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()

6 个答案:

答案 0 :(得分:1)

“如果一开始你没有成功,请再试一次。 然后退出;对此毫无用处。“ - 马克吐温

我很尴尬地承认我浪费了一周的时间。为了避免其他人陷入同样的​​陷阱,让我简化一下:

如果你有一个事物列表,其中每个东西都有你想要一起显示但又乐于作为一组操作的子元素,那么ListCtrl可能适合你。

如果你有一个事物列表,其中每个东西都有子元素,但你有兴趣独立操作这些子元素,ListCtrl似乎是你想要的。< / p>

我已经开始使用Grid小部件,到目前为止它似乎正在为我的目的而工作。这可能会在稍后再次让我感到困惑,但现在似乎有效。以下是来自Wx Huge Grid演示的一些略微修改的代码,用于说明网格小部件上的点击将如何返回行和列“地址”。

如果有人有关于如何从ListCtrl获取列号的建议,我当然都是耳朵。

import  wx
import  wx.grid as  gridlib

#---------------------------------------------------------------------------
class HugeTable(gridlib.PyGridTableBase):
    def __init__(self, log):
        gridlib.PyGridTableBase.__init__(self)
        self.log = log

        self.odd=gridlib.GridCellAttr()
        self.odd.SetBackgroundColour("sky blue")
        self.even=gridlib.GridCellAttr()
        self.even.SetBackgroundColour("sea green")

    def GetAttr(self, row, col, kind):
        attr = [self.even, self.odd][row % 2]
        attr.IncRef()
        return attr

    # This is all it takes to make a custom data table to plug into a
    # wxGrid.  There are many more methods that can be overridden, but
    # the ones shown below are the required ones.  This table simply
    # provides strings containing the row and column values.

    def GetNumberRows(self):
        return 10000

    def GetNumberCols(self):
        return 10000

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        return str( (row, col) )

    def SetValue(self, row, col, value):
        self.log.write('SetValue(%d, %d, "%s") ignored.\n' % (row, col, value))

#---------------------------------------------------------------------------
 class HugeTableGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        table = HugeTable(log)

        # The second parameter means that the grid is to take ownership of the
        # table and will destroy it when done.  Otherwise you would need to keep
        # a reference to it and call it's Destroy method later.
        self.SetTable(table, True)

        self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnCellRightClick)

    def OnCellRightClick(self, event):
        print "OnCellRightClick: (%d,%d)\n" % (event.GetRow(), event.GetCol())

#---------------------------------------------------------------------------
 class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "Huge (virtual) Table Demo", size=(640,480))
        grid = HugeTableGrid(self, log)

        grid.SetReadOnly(5,5, True)

#---------------------------------------------------------------------------
if __name__ == '__main__':
    import sys
    app = wx.App()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

答案 1 :(得分:1)

遗憾的是,没有一种获取列信息的好方法。我确实在这个问题上找到了这个讨论:http://wxpython-users.1045709.n5.nabble.com/Getting-row-col-of-selected-cell-in-ListCtrl-td2360831.html

听起来你必须自己计算一下。根据Robin的说法,wx.lib.mixins.listctrl.TextEditMixin中有一些代码可能有所帮助。我还发现ObjectListView(ListCtrl的包装器)的配方也可能有所帮助:http://code.activestate.com/recipes/577543-objectlistview-getcolumnclickedevent-handler/

答案 2 :(得分:1)

我不知道在点击一行时是否可以在listctrl中获取列号(因为它选择整行,而不是单个单元格)...但是,如果您想要单击列时的列号在列上(就像我做的那样,在很多搜索结束之后)你可以将一个事件(wx.EVT_LIST_COL_CLICK / wx.EVT_LIST_COL_RIGHT_CLICK)绑定到listctrl,并在事件方法中使用event.m_col ...它存储列号码

    self.Bind(wx.EVT_LIST_COL_CLICK, self.onColumnClick, self.myListCtrl)
...
def onColumnClick(self, evt):
    column_clicked = evt.m_col

从这里获得灵感:http://wxpython.org/Phoenix/docs/html/ListCtrl.html,在“此课程发布的活动”部分

答案 3 :(得分:1)

这在 listctrl 中对我有用。它并不完美,但它有效。 唯一的限制是我们要选择的左侧的所有列都必须可见。

self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
self.col=-1
....

def OnDoubleClick(self, event):
    posx=event.GetX()
    self.col=-1
    while posx>0:
        self.col+=1
        posx=posx-self.GetColumnWidth(self.col)        
    event.Skip()

答案 4 :(得分:0)

这适用于网格,可能很容易适应ListCtrl:

def onclick(self,event):
    rows = cumsum(self.GetRowSize(i) for i in range(self.GetNumberRows()))
    cols = cumsum(self.GetColSize(i) for i in range(self.GetNumberCols()))
    irow = self.GetNumberRows() - sum(event.m_y < y for y in rows)
    icol = self.GetNumberCols() - sum(event.m_x < x for x in cols)
    print irow,icol

答案 5 :(得分:0)

您可以使用EVT_LIST_COL_CLICK或EVT_LIST_COL_RIGHT_CLICK事件处理程序中的event.GetColumn()。这将返回m_col值。