在 Python 3 中未调用覆盖的 TreeCtrl.OnCompareItems() - wxPython 4

Hum*_*lan 5 python sorting wxpython python-2.7 python-3.x

我有一个wx.TreeCtrl结构,用户可以按不同的条件(日期、名称、id、降序、升序……)对项目进行排序。这在 Python 2 中工作得很好,但 Python 3(带有 wxPython 4)拒绝排序。该方法CTreeCtrl.OnCompareItems()在 Python 2 中被调用,但在 Python 3 中从未被调用。

在functools.cmp_to_key文档(https://docs.python.org/3/library/functools.html)中我发现了一个提示:Python 3不支持比较函数。令人困惑的是:在wx.TreeCtrl(wxPython 4)的描述中,有一个比较方法OnCompareItems()https://docs.wxpython.org/wx.TreeCtrl.html#wx.TreeCtrl.OnCompareItems)。描述说,与此方法一起我必须使用 RTTI 宏DECLARE_DYNAMIC_CLASS,并且IMPLEMENT_DYNAMIC_CLASS因为基类不知道我覆盖了OnCompareItems(). 我只找到了如何在 C++ 中使用这个宏的描述,但没有找到关于 python 的描述。

我不知道如何让我的程序OnCompareItems()在 Python3/wxPython 4 中调用我的方法。

有人可以帮忙吗?

问候, 洪巴兰

下面有一个反映该问题的小示例程序。它也可以与 Python 2 和 Python 3 一起运行。显示print( 'in CTreeCtrl.OnCompareItems()' )该方法被调用(在 py2 中)或未调用(在 py3 中):

import sys
import wx

class CTreeCtrl( wx.TreeCtrl ):
    def __init__( self, parent ):
        super( CTreeCtrl, self ).__init__( parent=parent, style=wx.TR_HIDE_ROOT )

    def OnCompareItems( self, item1, item2 ):
        print( 'in CTreeCtrl.OnCompareItems()' )
        if sys.version_info.major < 3:
            d1 = self.GetItemData( item1 ).Data
            d2 = self.GetItemData( item2 ).Data
        else:
            d1 = self.GetItemData( item1 )
            d2 = self.GetItemData( item2 )

        if   d1 < d2:  return -1
        elif d1 > d2:  return 1
        else        :  return 0


class CSettingsTree( wx.Dialog  ):

    def __init__( self, parent, settings ) :

        size = wx.Size(200,150)

        wx.Dialog.__init__( self, parent, title='all settings', size=size )
        bSizer_main = wx.BoxSizer( wx.VERTICAL )

        self.m_treeCtrl = CTreeCtrl( self  )
        bSizer_main.Add( self.m_treeCtrl, 0, wx.ALL|wx.EXPAND, 5 )

        self.SetSizer( bSizer_main )
        bSizer_main.Fit( self )

        root = self.m_treeCtrl.AddRoot( 'Settings' )

        for key, name in settings :
            if sys.version_info.major < 3 :  sort_key = wx.TreeItemData( name )
            else                          :  sort_key = name

            self.m_treeCtrl.AppendItem( root, '{}: {}'.format(key, name), data=sort_key )

        self.m_treeCtrl.ExpandAll()
        self.m_treeCtrl.SortChildren( root )



#---------------------------------------------------------------------------
if __name__=="__main__":

    app = wx.App( redirect=False )

    settings = [(50,'Taylor'),(200,'Mueller'),(101,'Baker'),(102,'Smith')]

    dlg = CSettingsTree( wx.Frame( None ), settings )
    dlg.ShowModal()
Run Code Online (Sandbox Code Playgroud)

编辑 (2018-03-08, 2:52pm)

看来这是 wxPython 的 c++ 部分的一个错误(参见https://github.com/wxWidgets/Phoenix/issues/774)并且修复仍然不可用。

小智 0

当尝试根据任意字段对 customtreectrl 项目进行排序时,我遇到了同样的问题,而不是像最初实现的那样仅按字母顺序排序。我不想重复上面的评论,只是说现在存在修复程序(此处,如 @Humbalan 对他们自己的问题的编辑中给出的那样)。

可能不值得提供完整的示例,因为@Humbalan 的问题有很多细节,但在我的例子中,我使用如下内容创建树项目:

ctc_item = self.tree_ctc.AppendItem(ctc_parent, text = ctc_text, data = {'id_': ctc_id})
Run Code Online (Sandbox Code Playgroud)

在哪里self.tree_ctc = MyCustomTreeCtrl(self, style = some_style)。我的树控件和(重写的)OnCompareItems() 方法是:

class MyCustomTreeCtrl(ctc.CustomTreeCtrl):

    def __init__(self, parent, style):
        ctc.CustomTreeCtrl.__init__(self, parent, agwStyle = style)

    def OnCompareItems(self, item1, item2):
        t1 = self.GetPyData(item1)['id_']
        t2 = self.GetPyData(item2)['id_']

        if t1 < t2:  return -1
        if t1 == t2: return 0
        return 1
Run Code Online (Sandbox Code Playgroud)

我意识到这个问题已经有几年了,但这希望有用。