Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » Почему возникает ошибка после редактирования ячейки сетки? [RSS Feed]

#1 Ноя. 6, 2019 09:29:37

ioprst
Зарегистрирован: 2018-03-25
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Почему возникает ошибка после редактирования ячейки сетки?

Есть диалог, на котором есть панель, на которой есть сетка.

Каждому столбцу сетки назначается собственный редактор (в методе класса, производном от GridTableBase)

 class StatePanel(wx.Panel):
 
    def __init__(self, parent, states):
        super().__init__(parent)
 
        topsizer = wx.FlexGridSizer(rows=1, cols=2, vgap=10, hgap=10)
 
        self.grid = CustomGrid(self, size=(-1, 100))
        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGED, self.OnGridCellChange)
        topsizer.Add(self.grid, proportion=1, flag=wx.EXPAND)
 
        self.SetSizer(topsizer)
 
        defaultValue = _StateInfos(0, '0', 'Состояние 0', YELLOW)
 
        self.states = states
        if not self.states:
            self.states.append(defaultValue.copy())
 
        self.table = StateTable(self.states, GetStateTableColnames())
    self.RefreshStates()
 
def RefreshStates(self):
    data = []
    for num, state in enumerate(self.states):
        state.Number = num + 1
        data.append(state)
    self.table.SetData(data)
    self.table.ResetView(self.grid)
 
def OnGridCellChange(self, event):
    row, col = event.GetRow(), event.GetCol()
    colname = self.table.GetColLabelValue(col, False)
    value = self.table.GetValue(row, col)
    message = None
 
    if colname == 'Code':
        if not value:
            message = 'Значение кода не может быть пустым.'
        else:
            for r in range(self.table.GetNumberRows()):
                if r != row:
                    code = self.table.GetValueByName(r, 'Code')
                    if value == code:
                        message = f'Код {value} уже используется.'
                        break
 
    if message is not None:
        wx.CallAfter(showErrorMessage, message)
        event.Veto()
    else:
        event.Skip()

В self.table.ResetView вызывается метод StateTable.ResetView

 class StateTable(wx.grid.GridTableBase):    
    ...    
 
    def ResetView(self, grid):
        """
        (wx.grid.Grid) -> Reset the grid view.   Call this to
        update the grid if rows and columns have been added or deleted
        """
        grid.CloseEditControl()
        grid.BeginBatch()
        for current, new, delmsg, addmsg in [
            (
                self._rows,
                self.GetNumberRows(),
                wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED,
                wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED
            ),
            (
                self._cols,
                self.GetNumberCols(),
                wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED,
                wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED
            )
        ]:
            if new < current:
                msg = wx.grid.GridTableMessage(self, delmsg, new, current-new)
                grid.ProcessTableMessage(msg)
            elif new > current:
                msg = wx.grid.GridTableMessage(self, addmsg, new-current)
                grid.ProcessTableMessage(msg)
                self.UpdateValues(grid)
        grid.EndBatch()
 
        self._rows = self.GetNumberRows()
        self._cols = self.GetNumberCols()
        # update the column rendering scheme
        self._updateColAttrs(grid)
 
        # update the scrollbars and the displayed part of the grid
        grid.AdjustScrollbars()
        grid.ForceRefresh()
 
    def _updateColAttrs(self, grid):
        for row in range(self.GetNumberRows()):
            for col in range(self.GetNumberCols()):
                editor = None
                renderer = None
                colname = self.GetColLabelValue(col, False)
 
                if col != 0:
                    grid.SetReadOnly(row, col, False)
 
                    if colname == 'Code':
                        editor = wx.grid.GridCellNumberEditor()
                        renderer = wx.grid.GridCellNumberRenderer()
 
                    elif colname == 'Text':
                        editor = wx.grid.GridCellTextEditor()
                        renderer = wx.grid.GridCellStringRenderer()
 
                    elif colname == 'Text colour':
                        editor = GridCellColourEditor()
                        renderer = GridCellColourRenderer()
 
                else:
                    grid.SetReadOnly(row, col, True)
 
                grid.SetCellEditor(row, col, editor)
                grid.SetCellRenderer(row, col, renderer)

Если я редактирую любую ячейку и закрываю диалоговое окно, возникает ошибка

 wx._core.wxAssertionError: C++ assertion "GetEventHandler() == this" failed at ..\..\src\common\wincmn.cpp(478) in wxWindowBase::~wxWindowBase(): any pushed event handlers must have been removed
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "C:\Python37-32\lib\site-packages\wx\lib\agw\customtreectrl.py", line 8183, in OnInternalIdle
    if not self.HasAGWFlag(TR_MULTIPLE) and not self.GetSelection():
  File "C:\Python37-32\lib\site-packages\wx\lib\agw\customtreectrl.py", line 3534, in HasAGWFlag
    return bool(self._agwStyle & flag)
SystemError: <class 'bool'> returned a result with an error set

Я видел тему: https://github.com/wxWidgets/Phoenix/issues/627

Сделал все как предложено в решении, но это не решает проблему.

Проблема решается, только если в методе OnGridCellChange в конце вызывается self.table._updateColAttrs (self.grid). Почему?

Офлайн

#2 Ноя. 12, 2019 10:28:23

ioprst
Зарегистрирован: 2018-03-25
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Почему возникает ошибка после редактирования ячейки сетки?

Table:

 class StateTable(CustomTable):
    ...
    def _updateColAttrs(self, grid):
        for row in range(self.GetNumberRows()):
            for col in range(self.GetNumberCols()):
                editor = None
                renderer = None
                colname = self.GetColLabelValue(col, False)
                if col != 0:
                    grid.SetReadOnly(row, col, False)
                    if colname == 'Code':
                        editor = wx.grid.GridCellNumberEditor()
                        renderer = wx.grid.GridCellNumberRenderer()
                    ...
                else:
                    grid.SetReadOnly(row, col, True)
                # !!!!!! DECISION !!!!!!
                currentEditor = grid.GetCellEditor(row, col)
                currentEditor.DecRef()
                grid.SetCellEditor(row, col, editor)
                grid.SetCellRenderer(row, col, renderer)
            self.ResizeRow(grid, row)

Grid:

 class StatePanel(wx.Panel):
    def __init__(self, parent, states):
        ...
        self.grid = CustomGrid(self, size=(-1, 120))
        self.grid.Bind(wx.EVT_WINDOW_DESTROY, self.OnGridDestroy)
        ...
    def OnGridDestroy(self, event):
        self.table._updateColAttrs(self.grid)
        event.Skip()

Отредактировано ioprst (Ноя. 12, 2019 10:28:46)

Офлайн

  • Начало
  • » GUI
  • » Почему возникает ошибка после редактирования ячейки сетки?[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version