wxPython DataViewListCtrl排序后热键选行异常问题求助
解决DataViewListCtrl排序后热键移动选中行异常的问题
问题核心在于GetSelectedRow()和SelectRow()操作的是数据模型的原始行索引,而非排序后界面显示的视觉行顺序。当列排序后,界面行顺序与模型行顺序脱节,导致热键逻辑按原始顺序跳转,出现选中项跳变。
解决方案:基于视觉选中项的上下导航
直接使用DataViewItem的GetPrev()和GetNext()方法,这两个方法会自动遵循当前界面的排序/过滤后的显示顺序,无需手动处理索引转换。
修改后的热键逻辑代码如下:
def move_up(e): selected_item = view.GetSelection() if not selected_item.IsOk(): return prev_item = view.GetPrev(selected_item) # 循环到最后一行 if not prev_item.IsOk(): last_item = view.GetLastItem() view.Select(last_item) else: view.Select(prev_item) def move_down(e): selected_item = view.GetSelection() if not selected_item.IsOk(): return next_item = view.GetNext(selected_item) # 循环到第一行 if not next_item.IsOk(): first_item = view.GetFirstItem() view.Select(first_item) else: view.Select(next_item)
完整修改后的示例代码
import wx import wx.dataview as dv app = wx.App() window = wx.Frame(None, title="Repro", size=(300,300)) sizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(window) panel.SetSizer(sizer) # Another widget, the hotkeys should work when this has focus. text = wx.TextCtrl(panel) sizer.Add(text, proportion=1, flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=8) # The widget affected by the hotkeys. view = dv.DataViewListCtrl(panel) view.AppendTextColumn("num", 120) view.AppendTextColumn("item", 120) view.Columns[0].SetSortable(True) view.Columns[1].SetSortable(True) view.AppendItem(["1", "foo"]) view.AppendItem(["2", "bar"]) view.AppendItem(["3", "qux"]) view.AppendItem(["4", "zar"]) view.AppendItem(["5", "etc"]) view.SelectRow(0) sizer.Add(view, proportion=8, flag=wx.LEFT | wx.RIGHT | wx.EXPAND, border=8) # 修改后的热键逻辑 def move_up(e): selected_item = view.GetSelection() if not selected_item.IsOk(): return prev_item = view.GetPrev(selected_item) if not prev_item.IsOk(): last_item = view.GetLastItem() view.Select(last_item) else: view.Select(prev_item) def move_down(e): selected_item = view.GetSelection() if not selected_item.IsOk(): return next_item = view.GetNext(selected_item) if not next_item.IsOk(): first_item = view.GetFirstItem() view.Select(first_item) else: view.Select(next_item) # Set up the hotkeys. accels = [] id_up = wx.NewIdRef() window.Bind(wx.EVT_MENU, move_up, id=id_up) accels.append([wx.ACCEL_CTRL, ord("k"), id_up]) id_down = wx.NewIdRef() window.Bind(wx.EVT_MENU, move_down, id=id_down) accels.append([wx.ACCEL_CTRL, ord("j"), id_down]) atbl = wx.AcceleratorTable(accels) window.SetAcceleratorTable(atbl) window.Show(True) window.Raise() text.SetFocus() app.MainLoop()
原理说明
GetSelection()获取当前选中的DataViewItem,该对象绑定的是当前界面显示的行,不受原始数据顺序影响。GetPrev()和GetNext()会根据当前控件的排序/过滤状态,返回视觉上的上一项和下一项。- 当到达列表首尾时,通过
GetFirstItem()和GetLastItem()实现循环跳转,与原生上下箭头的行为保持一致。
内容的提问来源于stack exchange,提问作者rimkojr
相关产品推荐
相关产品推荐

