wxPython DataViewCtrl子文本项编辑器显示不正确

时间:2019-06-18 23:40:14

标签: python wxpython wxpython-phoenix

我一直在尝试使用wxPython创建需要树/列表编辑器的程序。但是,我很快遇到了一个问题,即文本编辑框的问题是子项出现在列表的底部,而不是放在适当的位置。在下面显示的简化示例中,我双击编辑AA旁边的单元格,但是编辑框出现在最后一行。

但是,当我编辑父单元格时,没有问题,并且可以正确显示。

我已附上以下代码。对于解决此问题的任何建议,我将不胜感激。谢谢!

import wx
import wx.dataview as dv

class Node:
    def __init__(self, name, parent):
        self.name = name
        self.parent = parent
        self.children = []
        self.value = ''

class DVC_Model(dv.PyDataViewModel):
    def __init__(self, data):
        super().__init__()
        self.data = data

        self.UseWeakRefs(True)


    def GetColumnCount(self):
        return 2

    def GetColumnType(self, col):
        return 'string'

    def GetChildren(self, item, children):
        if not item:
            for child in self.data.children:
                children.append(self.ObjectToItem(child))
            return len(self.data.children)

        obj = self.ItemToObject(item)

        for child in obj.children:
            children.append(self.ObjectToItem(child))
        return len(obj.children)

    def GetParent(self, item):
        obj = self.ItemToObject(item)

        if obj.parent is None:
            return dv.NullDataViewItem

        return self.ObjectToItem(obj.parent)

    def IsContainer(self, item):
        if not item:
            return True

        obj = self.ItemToObject(item)

        return len(obj.children) > 0

    def HasContainerColumns(self, item):
        return True

    def GetValue(self, item, col):
        if not item:
            return [root.name, root.value][col]

        obj = self.ItemToObject(item)

        return [obj.name, obj.value][col]

    def SetValue(self, variant, item, col):
        obj = self.ItemToObject(item)
        if col == 1:
            obj.value = variant

        return True

    def GetAttr(self, item, col, attr):
        obj = self.ItemToObject(item)

        if len(obj.children) > 0:
            attr.SetColour('blue')
            attr.SetBold(True)
            return True

        return False


if __name__ == '__main__':
    app = wx.App()

    window = wx.Frame(None, -1, "Test title", style=wx.DEFAULT_FRAME_STYLE)
    window.SetFocus()

    dvc = dv.DataViewCtrl(window, style=wx.BORDER_THEME | dv.DV_ROW_LINES | dv.DV_VERT_RULES | dv.DV_MULTIPLE)

    root = Node('root', None)

    A = Node('A', root)
    AA = Node('AA', A)
    AB = Node('AB', A)
    A.children = [AA, AB]

    B = Node('B', root)
    BA = Node('BA', B)
    BB = Node('BB', B)
    B.children = [BA, BB]

    root.children = [A, B]

    model = DVC_Model(root)
    dvc.AssociateModel(model)

    dvc.AppendTextColumn('Name', 0)
    dvc.AppendTextColumn('Value', 1, mode=dv.DATAVIEW_CELL_EDITABLE)


    window.Show(True)

    app.MainLoop()

更新:我在Linux上测试了该程序,但遇到了分段错误。 wxPython演示程序可以正常工作。也许可以帮助识别我的代码中的问题。

1 个答案:

答案 0 :(得分:0)

看到Linux上的错误后,我开始进行进一步的测试,并意识到我正在GetParent()中将根节点作为父节点返回给节点A和B。但是,该节点对于wxPython和I应该是不可见的需要返回wx.NullDataViewItem。我发现的解决方案是修改GetParent()或实例化没有父对象的对象,如下所示:

def GetParent(self, item):
    obj = self.ItemToObject(item)

    if obj.parent is None or obj.parent == self.data:  # if the parent is the invisible root node, return null
        return dv.NullDataViewItem

    return self.ObjectToItem(obj.parent)
root = Node('root', None)

A = Node('A', None)  # root changed to None
AA = Node('AA', A)
AB = Node('AB', A)
A.children = [AA, AB]

B = Node('B', None)  # root changed to None
BA = Node('BA', B)
BB = Node('BB', B)
B.children = [BA, BB]

root.children = [A, B]