【问题标题】:Wxpython Button Inside Grid网格内的 Wxpython 按钮
【发布时间】:2020-03-27 11:40:08
【问题描述】:

我正在尝试向网格单元格添加一个按钮。
我正在使用最新的演示 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()

【问题讨论】:

    标签: wxpython


    【解决方案1】:

    此脚本启动一个内部带有网格的框架。当您单击按钮时,外壳中会显示消息“活动/非活动”。 关键是类通过使用 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):
            self.rd = myRenderer(self)
            # Button coordinates
            self.rend_row = 2
            self.rend_col = 1
            # ...
            self.SetCellValue(1, 0, 'Click on the Button')
            # Set Button in cell
            self.SetCellRenderer(self.rend_row, self.rend_col, self.rd)
             # Prevent button cell selection
            self.SetReadOnly(self.rend_row, self.rend_col, True)
    
        def handleEvents(self):
            self.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onCellSelected)
    
        def onCellSelected(self, event):
            # # Button inverted switch var
            switch_inv = {False: wx.CONTROL_NONE, True: wx.CONTROL_PRESSED}
            # To avoid bug verify if it's possible to enable cell control
            # Typical bug : "wx._core.wxAssertionError: C++ assertion "CanEnableCellControl()" failed at /home/... 
            # in EnableCellEditControl(): can't enable editing for this cell!"
            if self.CanEnableCellControl():
                self.EnableCellEditControl()
            # Invert button status : CONTROL_NONE (inactive) / wx.CONTROL_PRESSED (active)
            self.rd.buttonState = switch_inv[not self.rd.boolstat['boolstat']]
            # Print button status
            print("Button status : {0}".format({0:"inactive", 4:"active"}[self.rd.buttonState]))
    
    class myRenderer(wx.grid.GridCellRenderer):
        def __init__(self, parent):
            wx.grid.GridCellRenderer.__init__(self)
    
            # Button neutral state
            self.boolstat = {'boolstat': True}
            # Button state when initializing
            self.buttonState = 0
    
        def Draw(self, grid, attr, dc, rect, row, col, isSelected):
            # Button switch var
            switch = {wx.CONTROL_NONE: False, wx.CONTROL_PRESSED: True}
            # Renderer state
            self.boolstat['boolstat'] =  switch[self.buttonState]
            # ...
            wx.RendererNative.Get().DrawPushButton(grid, dc, rect, self.buttonState)
    
    
    #---------------------------------------------------------------------------
    
    if __name__ == '__main__':
        app = wx.App()
        frame = myFrame(None)
        frame.Show()
        frame.Centre()
        app.MainLoop()
    

    【讨论】:

      【解决方案2】:

      此脚本创建一个框架和一个两行五列的网格。第五列是可以用作按钮的图像。请参阅 onCellSelected 函数以响应按钮选择。

      import wx
      import wx.grid as Grid
      
      class MyFrame(wx.Frame):
          def __init__(self, parent, title):
              super(MyFrame, self).__init__(parent, title=title, size=(400, 300))
      
              self.panel = MyPanel(self)
              self.MyGrid = New_Grid(self, numRows=2, numCols=5)
              mainSizer = wx.BoxSizer(wx.VERTICAL)
              mainSizer.Add(self.MyGrid,1,wx.ALL|wx.EXPAND,0)
              self.SetSizer(mainSizer)
      
      
      class MyPanel(wx.Panel):
          def __init__(self, parent):
              super(MyPanel, self).__init__(parent)
      
      
      class New_Grid(Grid.Grid):
          def __init__(self, parent, numRows, numCols):
              Grid.Grid.__init__(self, parent)
      
              self.CreateGrid(numRows, numCols)
              self.SetRowLabelSize(35)
              self.AutoSizeColumns(True)
              # Display content
              self.displayContent()
              # ...
              self.handleEvents()
      
          def displayContent(self):
              myList = [
                  "Col1",
                  "Col2",
                  "Col3",
                  "Col4",
                  "Set"
              ]
              x = 0
              for item in myList:
                  self.SetColLabelValue(x, item)
                  x += 1
              self.SetColLabelSize(25)
              self.AutoSizeColumns(True)
              self.update_Grid()
      
          def handleEvents(self):
              self.Bind(Grid.EVT_GRID_SELECT_CELL, self.onCellSelected)
      
          def onCellSelected(self, event):
              col = event.GetCol()
              if col == 5:
                  Selected = event.GetRow()
      
          def update_Grid(self):
              img = wx.Bitmap("SET.png", wx.BITMAP_TYPE_PNG)
              self.rd = MyImageRenderer(img)
              # Buttons coordinates
              numRows = self.GetNumberRows()
              for y in range(numRows):
                  self.rd.rend_row = y
                  self.rd.rend_col = 4
                  self.SetCellRenderer(self.rd.rend_row, self.rd.rend_col, self.rd)
                  self.SetColSize(0, img.GetWidth() + 2)
                  self.SetRowSize(0, img.GetHeight() + 3)
                  self.SetReadOnly(self.rd.rend_row, self.rd.rend_col, True)
      
      class MyImageRenderer(wx.grid.GridCellRenderer):
          def __init__(self, img):
              wx.grid.GridCellRenderer.__init__(self)
              self.img = img
      
          def Draw(self, grid, attr, dc, rect, row, col, isSelected):
              image = wx.MemoryDC()
              image.SelectObject(self.img)
              dc.SetBackgroundMode(wx.SOLID)
              if isSelected:
                  dc.SetBrush(wx.Brush(wx.BLUE, wx.SOLID))
                  dc.SetPen(wx.Pen(wx.BLUE, 1, wx.SOLID))
              else:
                  dc.SetBrush(wx.Brush(wx.WHITE, wx.SOLID))
                  dc.SetPen(wx.Pen(wx.WHITE, 1, wx.SOLID))
              dc.DrawRectangle(rect)
              width, height = self.img.GetWidth(), self.img.GetHeight()
              if width > rect.width - 2:
                  width = rect.width - 2
              if height > rect.height - 2:
                  height = rect.height - 2
              dc.Blit(rect.x + 1, rect.y + 1, width, height, image, 0, 0, wx.COPY, True)
      
          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)
      
      
      class MyApp(wx.App):
          def OnInit(self):
              self.frame = MyFrame(parent=None,title="wxPython Window")
              self.frame.Show()
              return True
      
      
      app = MyApp()
      app.MainLoop()
      

      以上脚本输出为: Table with buttons in the fifth column.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-02
        • 1970-01-01
        • 1970-01-01
        • 2015-08-17
        • 1970-01-01
        相关资源
        最近更新 更多