Редактор дочерних текстовых элементов wxPython DataViewCtrl отображается неправильно - PullRequest
0 голосов
/ 19 июня 2019

Я пытался использовать 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 голосов
/ 19 июня 2019

Увидев ошибку в Linux, я начал проводить дальнейшее тестирование и понял, что возвращаю корневой узел как родительский в GetParent() для узлов A и B. Однако этот узел должен быть невидим для wxPython, и мне нужно быловозвращать 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]
...