网格内的 Wxpython 按钮

sch*_*hul 5 wxpython

我正在尝试向网格单元添加一个按钮。
我正在使用最新的演示 4.0.7 和 python 3.7(32 位)
我修复了在这里找到的旧示例:https://groups.google.com/forum/# !topic/wxpython-users/HhtKCxPVX_s 问题是按钮不是工作正常并按下它会导致整个网格消失。

class MyCustomRenderer2(gridlib.GridCellRenderer):
def __init__(self):
    gridlib.GridCellRenderer.__init__(self)
    self.down = False
    self.click_handled = False

def Draw(self, grid, attr, dc, rect, row, col, isSelected):
    """This is called when the widget is Refreshed"""
    print ('drawing button')
    dc.Clear()
    if self.down:
        state = wx.CONTROL_PRESSED | wx.CONTROL_SELECTED
    else:
        state = 0

    #if not self.IsEnabled():
    #    state = wx.CONTROL_DISABLED
    #pt = self.ScreenToClient(wx.GetMousePosition())
    #if self.GetClientRect().Contains(pt):
    #    state |= wx.CONTROL_CURRENT

    wx.RendererNative.Get().DrawPushButton(grid, dc, rect, state)
    #extra logic required since a button gets drawn at various times that could be while the mouse button is held down
    if self.down and not self.click_handled:
        self.click_handled = True
        self.HandleClick()

def HandleClick(self):
    print ('clicked')

def GetBestSize(self, grid, attr, dc, row, col):
    text = grid.GetCellValue(row, col)
    dc.SetFont(attr.GetFont())
    w, h = dc.GetTextExtent(text)
    return wx.Size(w, h)


def Clone(self):
    return MyCustomRenderer2()
Run Code Online (Sandbox Code Playgroud)

Lau*_* B. 2

该脚本启动一个内部有网格的框架。单击该按钮时,网格中会显示“活动/非活动”消息。要点是类通过使用 2 个开关变量(即 2 个倒排字典)进行通信。

代码里面有注释

import  wx
import  wx.grid as  gridlib

#---------------------------------------------------------------------------
class myFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, -1, size=(400, 300))

        # ...
        self.gridBox = wx.BoxSizer(wx.VERTICAL) 
        self.mainGrid = showGrid(self, numRows=5, numCols=5)
        self.gridBox.Add(self.mainGrid)        
        self.SetSizerAndFit(self.gridBox)


class showGrid(gridlib.Grid):
    def __init__(self, parent, numRows, numCols):
        """Constructeur"""
        gridlib.Grid.__init__(self, parent, size=parent.GetSize())

        self.CreateGrid(numRows, numCols)
        self.SetRowLabelSize(50)
        # Display content
        self.displayContent()
        # ...
        self.handleEvents()        

    def displayContent(self):
        # Button coordinates
        self.buttrow = 2
        self.buttcol = 1
        # Define a button renderer
        self.rd = buttonRenderer()
        # Set the attribute (attr) for the specific cell and nothing else
        attr = wx.grid.GridCellAttr()
        attr.SetRenderer(self.rd)
        self.SetAttr(self.buttrow, self.buttcol, attr)
        # Label to describe action to perform
        self.SetCellValue(1, 0, 'Click on the Button')
        # Prevent button cell selection
        self.SetReadOnly(self.buttrow, self.buttcol, True)

    def handleEvents(self):
        self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onCellSelected)

    def onCellSelected(self, event):
        if self.buttrow==event.GetRow() and self.buttcol==event.GetCol():
            # # Button inverted switch var
            switch_inv = {False: wx.CONTROL_FLAT, True: wx.CONTROL_PRESSED}
            # Invert button status : CONTROL_NONE (inactive) / wx.CONTROL_PRESSED (active)
            self.rd.buttonState = switch_inv[not self.rd.boolstat['boolstat']]
            # Print button status
            self.SetCellValue(2, 2, "{0}".format({8:"inactive", 4:"active"}[self.rd.buttonState]))
            # Refresh the grid
            self.Refresh(eraseBackground=True)
        else:
            pass


class buttonRenderer(wx.grid.PyGridCellRenderer):
    def __init__(self):
        wx.grid.GridCellRenderer.__init__(self)

        # Button neutral state
        self.boolstat = {'boolstat': True}
        # Button state inactive when initializing
        self.buttonState = 8

    def Draw(self, grid, attr, dc, rect, row, col, isSelected):

        # Define Push Button dimensions
        rect.SetSize(wx.Size(50,15))
        # For centering the button
        posX = 95
        posY = 55
        rect.SetPosition(wx.Point(posX,posY))
        # Draw the Push Button
        wx.RendererNative.Get().DrawPushButton(grid, dc, rect, self.buttonState)        
        # Switch button state indicator
        self.boolstat['boolstat'] =  \
        {wx.CONTROL_FLAT: False, wx.CONTROL_PRESSED: True}[self.buttonState]

#---------------------------------------------------------------------------

if __name__ == '__main__':
    app = wx.App()
    frame = myFrame(None)
    frame.Show()
    frame.Centre()
    app.MainLoop()
Run Code Online (Sandbox Code Playgroud)

活动网格按钮

在此输入图像描述

非活动网格按钮

在此输入图像描述