Форум сайта python.su
Есть диалог, на котором есть панель, на которой есть сетка.
Каждому столбцу сетки назначается собственный редактор (в методе класса, производном от 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()
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
Офлайн
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)
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)
Офлайн