Change wxGrid CheckBox with one click

本文介绍如何在wxPython中通过自定义编辑器和渲染器使Grid中的某个单元格行为类似于wx.CheckBox,包括解决点击两次才能改变状态及无法立即检测值变化的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

wxPython includes a wx.GridCellBoolEditor/Renderer, which looks like a wx.CheckBox

Unfortunately it does not behave exactly like a wx.CheckBox, for two reasons -

1, You have to click it twice with a mouse to change it - once to create the Editor, a second time to change the value

2. There is no obvious way to detect that the value has changed until the Editor is closed

What Objects are Involved

wx.grid.Grid

wx.grid.GridCellBoolEditor

wx.grid.GridCellBoolRenderer

Process Overview

The example assumes that you want all cells in Column 1 to act like a wx.CheckBox.

The grid's init() method sets up the Editor and Renderer for Column 1 in a Column Attribute.

To solve problem 1 above, when a mouse click is detected in Column 1, wx.CallLater is used to call a method to toggle the value, with a delay of 100 (1/10 sec). This gives enough time for the Editor to be created first.

To solve problem 2 above, an EVT_GRID_EDITOR_CREATED handler is used to obtain and save a reference to the underlying wx.CheckBox, and set up an EVT_CHECKBOX handler for it.

A method called afterCheckBox() is used to respond to any changes to the wx.CheckBox. It is called both from the initial mouse click and from EVT_CHECKBOX.

Code Sample

切换行号显示
   1 import wx, wx.grid as grd
   2 
   3 class MyGrid(grd.Grid):
   4     def __init__(self, parent):
   5         grd.Grid.__init__(self, parent, -1, pos=(10,40), size=(420,95))
   6 
   7         self.CreateGrid(3,3)
   8         self.RowLabelSize = 0
   9         self.ColLabelSize = 20
  10 
  11         attr = grd.GridCellAttr()
  12         attr.SetEditor(grd.GridCellBoolEditor())
  13         attr.SetRenderer(grd.GridCellBoolRenderer())
  14         self.SetColAttr(1,attr)
  15         self.SetColSize(1,20)
  16 
  17         self.Bind(grd.EVT_GRID_CELL_LEFT_CLICK,self.onMouse)
  18         self.Bind(grd.EVT_GRID_SELECT_CELL,self.onCellSelected)
  19         self.Bind(grd.EVT_GRID_EDITOR_CREATED, self.onEditorCreated)
  20 
  21     def onMouse(self,evt):
  22         if evt.Col == 1:
  23             wx.CallLater(100,self.toggleCheckBox)
  24         evt.Skip()
  25 
  26     def toggleCheckBox(self):
  27         self.cb.Value = not self.cb.Value
  28         self.afterCheckBox(self.cb.Value)
  29 
  30     def onCellSelected(self,evt):
  31         if evt.Col == 1:
  32             wx.CallAfter(self.EnableCellEditControl)
  33         evt.Skip()
  34 
  35     def onEditorCreated(self,evt):
  36         if evt.Col == 1:
  37             self.cb = evt.Control
  38             self.cb.WindowStyle |= wx.WANTS_CHARS
  39             self.cb.Bind(wx.EVT_KEY_DOWN,self.onKeyDown)
  40             self.cb.Bind(wx.EVT_CHECKBOX,self.onCheckBox)
  41         evt.Skip()
  42 
  43     def onKeyDown(self,evt):
  44         if evt.KeyCode == wx.WXK_UP:
  45             if self.GridCursorRow > 0:
  46                 self.DisableCellEditControl()
  47                 self.MoveCursorUp(False)
  48         elif evt.KeyCode == wx.WXK_DOWN:
  49             if self.GridCursorRow < (self.NumberRows-1):
  50                 self.DisableCellEditControl()
  51                 self.MoveCursorDown(False)
  52         elif evt.KeyCode == wx.WXK_LEFT:
  53             if self.GridCursorCol > 0:
  54                 self.DisableCellEditControl()
  55                 self.MoveCursorLeft(False)
  56         elif evt.KeyCode == wx.WXK_RIGHT:
  57             if self.GridCursorCol < (self.NumberCols-1):
  58                 self.DisableCellEditControl()
  59                 self.MoveCursorRight(False)
  60         else:
  61             evt.Skip()
  62 
  63     def onCheckBox(self,evt):
  64         self.afterCheckBox(evt.IsChecked())
  65 
  66     def afterCheckBox(self,isChecked):
  67         print 'afterCheckBox',self.GridCursorRow,isChecked
  68 
  69 class TestFrame(wx.Frame):
  70     def __init__(self, parent):
  71         wx.Frame.__init__(self, parent, -1, "Custom cell editor test", size=(250,200))
  72         panel = wx.Panel(self,style=0)
  73         grid = MyGrid(panel)
  74         grid.SetFocus()
  75         self.CentreOnScreen()
  76 
  77 class MyApp(wx.App):
  78     def OnInit(self):
  79         frame = TestFrame(None)
  80         frame.Show(True)
  81         self.SetTopWindow(frame)
  82         return True
  83 
  84 MyApp(0).MainLoop()

Comments

If anything is not clear, ask questions here and I will do my best to answer them.

Frank Millman

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值