Python Forum
[WxPython] Grid. How to close the cell editor?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[WxPython] Grid. How to close the cell editor?
#1
How to implement closing your own cell editor when it loses focus? Since the built-in wx editors work.

Now my editor closes only if you select another cell in the grid.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.grid


class GridCellColourEditor(wx.grid.GridCellEditor):

    def __init__(self):
        super().__init__()

    def Create(self, parent, id, evtHandler):
        self._cp = wx.ColourPickerCtrl(parent, id)
        self.SetControl(self._cp)

        if evtHandler:
            self._cp.PushEventHandler(evtHandler)

    def BeginEdit(self, row, col, grid):
        self.startValue = grid.GetTable().GetValue(row, col)
        self._cp.SetColour(self.startValue)
        self._cp.SetFocus()

    def EndEdit(self, row, col, grid, oldval):
        val = self._cp.GetColour().GetAsString(wx.C2S_HTML_SYNTAX)
        if val != oldval:
            return val
        else:
            return None

    def ApplyEdit(self, row, col, grid):
        val = self._cp.GetColour().GetAsString(wx.C2S_HTML_SYNTAX)
        grid.GetTable().SetValue(row, col, val)

    def Reset(self):
        self._cp.SetColour(self.startValue)

    def Clone(self):
        return GridCellColourEditor()

class GridCellColourRenderer(wx.grid.GridCellRenderer):

    def __init__(self):
        super().__init__()

    def Draw(self, grid, attr, dc, rect, row, col, isSelected):
        if grid.IsEnabled():
            bgColour = grid.GetDefaultCellBackgroundColour()
        else:
            bgColour = grid.GetBackgroundColour()

        dc.SetBrush(wx.Brush(bgColour, wx.SOLID))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangle(rect)

        colour = grid.GetTable().GetValue(row, col)

        x = rect.x + 3
        y = rect.y + 3
        width = rect.width - 6
        height = rect.height - 6

        dc.SetBrush(wx.Brush(colour, wx.SOLID))
        dc.SetPen(wx.Pen(wx.BLACK))
        dc.DrawRoundedRectangle(x, y, width, height, 3)

    def GetBestSize(self, grid, attr, dc, row, col):
        return attr.GetSize()

    def Clone(self):
        return GridCellColourRenderer()

class Frame(wx.Frame):

    def __init__(self):
        super().__init__(None)

        vbox = wx.BoxSizer(wx.VERTICAL)

        self.grid = wx.grid.Grid(self, size=(100, 50))
        vbox.Add(self.grid, flag=wx.EXPAND)
        self.grid.CreateGrid(1, 2)

        self.grid.SetCellEditor(0, 0, GridCellColourEditor())
        self.grid.SetCellRenderer(0, 0, GridCellColourRenderer())

        self.grid.SetCellEditor(0, 1, wx.grid.GridCellTextEditor())
        self.grid.SetCellRenderer(0, 1, wx.grid.GridCellStringRenderer())

        btn = wx.Button(self, -1, 'For kill focus')
        vbox.Add(btn, 0, wx.ALL, 10)

        self.SetSizer(vbox)

app = wx.App()
frame = Frame()
frame.Show()
app.MainLoop()
Why, if wx.TextCtrl is used as wx.Control, then the cell editor successfully closes when focus is lost. And if I use wx.ColourPickerCtrl, the editor does not close?
Reply
#2
It solved my problem

class GridCellColourEditor(wx.grid.GridCellEditor):

    def Create(self, parent, id, evtHandler):
        self._parent = parent
        self._colourDialog = None
        self._colourButton = wx.Button(parent, id, "")
        self.SetControl(self._colourButton)
        newEventHandler = wx.EvtHandler()
        if evtHandler:
            self._colourButton.PushEventHandler(newEventHandler)
        self._colourButton.Bind(wx.EVT_BUTTON, self.OnClick)

    def OnClick(self, event):
        self._colourButton.SetFocus()
        self.ShowColourDialog()

    def SetSize(self, rect):
        self._colourButton.SetSize(rect.x, rect.y,
                                   rect.width + 2, rect.height + 2,
                                   wx.SIZE_ALLOW_MINUS_ONE)

    def Clone(self):
        return GridCellColourEditor()

    def BeginEdit(self, row, col, grid):
        self.startValue = grid.GetTable().GetValue(row, col)
        self.endValue = self.startValue
        self._colourButton.SetBackgroundColour(self.startValue)

        self._grid = grid
        self._row = row
        self._col = col
        self._parent.Bind(wx.EVT_LEFT_DOWN, self.OnParentLeftDown)
        self._parent.Bind(wx.EVT_KILL_FOCUS, self.OnParentKillFocus)

    def EndEdit(self, row, col, grid, oldval):
        self._parent.Unbind(wx.EVT_LEFT_DOWN)
        self._parent.Unbind(wx.EVT_KILL_FOCUS)

        if self.endValue != self.startValue:
            return self.endValue
        else:
            return None

    def ApplyEdit(self, row, col, grid):
        val = self.endValue.GetAsString(wx.C2S_HTML_SYNTAX)
        grid.GetTable().SetValue(row, col, val)

    def Reset(self):
        self._colourButton.SetBackgroundColour(self.startValue)

    def ShowColourDialog(self):
        colourDialog = wx.ColourDialog(self._parent)
        self._colourDialog = colourDialog
        colourDialog.GetColourData().SetColour(self.startValue)
        if colourDialog.ShowModal() == wx.ID_OK:
            data = colourDialog.GetColourData()
            colour = data.GetColour()
            self._colourButton.SetBackgroundColour(colour)
            self.endValue = colour

        self._parent.SetFocus()

        del self._colourDialog
        self._colourDialog = None

    def OnParentLeftDown(self, event: wx.MouseEvent):
        def CheckCellChange():
            row = self._grid.GetGridCursorRow()
            col = self._grid.GetGridCursorCol()
            if self._row == row and self._col == col:
                # клик в области сетки, но ячейка не изменилась
                self._grid.CloseEditControl()
        wx.CallAfter(CheckCellChange)
        event.Skip()

    def OnParentKillFocus(self, event: wx.FocusEvent):
        if self._parent.FindFocus() != self._colourButton:
            self._grid.CloseEditControl()
        event.Skip()
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [WxPython] Why does an error occur after editing a grid cell? ioprst 2 2,737 Nov-12-2019, 12:31 PM
Last Post: Larz60+
  Get value of wx grid cell ian 1 8,667 Jul-15-2017, 03:04 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020