0

我是 wxPython 的新手,所以请温柔一点。

我正在尝试制作当用户按下鼠标右键时通过上下文菜单弹出来控制的虚拟列表控件。

根据我的一点点经验,虚拟列表控件似乎喜欢使用“项目”(阅读:“行”)和“列”数字进行操作。很公平。

当我收到一个右键单击事件时,我可以通过调用 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()
4

6 回答 6

1

“如果一开始你没有成功,那就再试一次。然后退出;在这件事上做一个该死的傻瓜是没有用的。” ——马克吐温

我很尴尬地承认我在这件事上浪费了一个星期。为了避免其他人落入同样的陷阱,让我简化一下:

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

如果您有一个事物列表,其中每个事物都有子元素,但您有兴趣独立操作这些子元素,那么 ListCtrl 似乎不是您想要的。

我已经开始使用 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()
于 2012-07-29T23:40:05.673 回答
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/

于 2012-07-30T14:31:10.347 回答
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 ,在“这个类发出的事件”部分

于 2013-02-15T22:32:25.767 回答
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()
于 2021-02-13T10:31:19.260 回答
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
于 2013-09-20T20:19:53.230 回答
0

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

于 2018-01-11T19:23:23.043 回答