使用python的wx.grid,如何合并列?

时间:2017-09-13 13:42:23

标签: python wxpython wxwidgets

这是我到目前为止创建的表格。

enter image description here

这是我希望它看起来像是合并的列。

enter image description here

我想将昨天和今天的列合并为三列。所以昨天将高于股票,波动率和现金。然后同样为今天。我找到了一个名为wx.grid.SetColSize(self, int col, int width)的函数,但它没有任何效果。有谁知道怎么做?

这也是我的代码。

import wx
import wx.grid as gridlib

class MyForm(wx.Frame):
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="Strategies' Allocations")
        self.panel = wx.Panel(self)

        button_refresh = wx.Button(self.panel, id=wx.ID_ANY, label='Refresh')
        button_refresh.Bind(wx.EVT_BUTTON, self.refresh)

        self.myGrid1 = gridlib.Grid(self.panel)
        self.myGrid1.CreateGrid(2, 6)

        self.myGrid1.SetRowLabelSize(60)
        self.myGrid1.SetRowLabelValue(0, "")
        self.myGrid1.SetRowLabelValue(1, "ABRVXX")

        for i in range(6):
            self.myGrid1.SetColSize(i, 60)

        self.myGrid1.SetColLabelValue(0, "")
        self.myGrid1.SetColLabelValue(1, "Yesterday")
        self.myGrid1.SetColLabelValue(2, "")
        self.myGrid1.SetColLabelValue(3, "")
        self.myGrid1.SetColLabelValue(4, "Today")
        self.myGrid1.SetColLabelValue(5, "")

        self.myGrid1.SetCellValue(0, 0, "Equity")
        self.myGrid1.SetCellValue(0, 1, "Volatility")
        self.myGrid1.SetCellValue(0, 2, "Cash")
        self.myGrid1.SetCellValue(0, 3, "Equity")
        self.myGrid1.SetCellValue(0, 4, "Volatility")
        self.myGrid1.SetCellValue(0, 5, "Cash")

        self.myGrid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid1.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ******************************* #

        self.myGrid2 = gridlib.Grid(self.panel)
        self.myGrid2.CreateGrid(2, 6)

        for i in range(6):
            self.myGrid2.SetColSize(i, 60)

        self.myGrid2.SetColLabelValue(0, "")
        self.myGrid2.SetColLabelValue(1, "Yesterday")
        self.myGrid2.SetColLabelValue(2, "")
        self.myGrid2.SetColLabelValue(3, "")
        self.myGrid2.SetColLabelValue(4, "Today")
        self.myGrid2.SetColLabelValue(5, "")

        self.myGrid2.SetCellValue(0, 0, "Treasury")
        self.myGrid2.SetCellValue(0, 1, "Volatility")
        self.myGrid2.SetCellValue(0, 2, "Cash")
        self.myGrid2.SetCellValue(0, 3, "Treasury")
        self.myGrid2.SetCellValue(0, 4, "Volatility")
        self.myGrid2.SetCellValue(0, 5, "Cash")

        self.myGrid2.SetRowLabelSize(60)
        self.myGrid2.SetRowLabelValue(0, "")
        self.myGrid2.SetRowLabelValue(1, "ABRXIV")

        self.myGrid2.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid2.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ****************************** #

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.myGrid1, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(self.myGrid2, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(button_refresh, 1, wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTRE, 50)

        self.panel.SetSizer(sizer)
        self.panel.SetSize((500,400))
        self.SetSize((500,400))
        self.panel.Layout()

    def refresh(self, event):
        pass

if __name__ == "__main__":
    app = wx.App()
    frame = MyForm().Show()
    app.MainLoop()

5 个答案:

答案 0 :(得分:2)

这不会特别简单,但我认为你应该通过定义一个派生自wxGridCellAttrProvider的类并覆盖其GetColumnHeaderRenderer()方法来返回一个"什么也不做#34; wxGridColumnHeaderRenderer用于要合并的列,标准渲染器(由基类GetColumnHeaderRenderer()返回)用于其他列。然后,您只需要在表对象上使用自定义属性提供程序对象调用SetAttrProvider()

答案 1 :(得分:2)

快速而肮脏的方法是转储列标签SetColLabelSize(0)并将标题添加为单元格 然后仅针对具有SetCellSize()的细胞调整细胞跨度 下面我改变了myGrid1,但没有改变myGrid2。

import wx
import wx.grid as gridlib

class MyForm(wx.Frame):
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="Strategies' Allocations")
        self.panel = wx.Panel(self)

        button_refresh = wx.Button(self.panel, id=wx.ID_ANY, label='Refresh')
        button_refresh.Bind(wx.EVT_BUTTON, self.refresh)

        self.myGrid1 = gridlib.Grid(self.panel)
        self.myGrid1.CreateGrid(3, 6)

        self.myGrid1.SetRowLabelSize(80)
        self.myGrid1.SetRowLabelValue(0, "")
        self.myGrid1.SetRowLabelValue(1, "")
        self.myGrid1.SetRowLabelValue(2, "2")

        for i in range(6):
            self.myGrid1.SetColSize(i, 60)

#        self.myGrid1.SetColLabelValue(0, "")
#        self.myGrid1.SetColLabelValue(1, "Yesterday")
#        self.myGrid1.SetColLabelValue(2, "")
#        self.myGrid1.SetColLabelValue(3, "")
#        self.myGrid1.SetColLabelValue(4, "Today")
#        self.myGrid1.SetColLabelValue(5, "")

        self.myGrid1.SetColLabelSize(0)
        self.myGrid1.SetCellSize(0, 0, 1, 3)
        self.myGrid1.SetCellValue(0, 0, "Yesterday")
        self.myGrid1.SetCellSize(0, 3, 1, 3)
        self.myGrid1.SetCellValue(0, 3, "Today")

        self.myGrid1.SetCellValue(1, 0, "Equity")
        self.myGrid1.SetCellValue(1, 1, "Volatility")
        self.myGrid1.SetCellValue(1, 2, "Cash")
        self.myGrid1.SetCellValue(1, 3, "Equity")
        self.myGrid1.SetCellValue(1, 4, "Volatility")
        self.myGrid1.SetCellValue(1, 5, "Cash")

        self.myGrid1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid1.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ******************************* #

        self.myGrid2 = gridlib.Grid(self.panel)
        self.myGrid2.CreateGrid(2, 6)

        for i in range(6):
            self.myGrid2.SetColSize(i, 60)

        self.myGrid2.SetColLabelValue(0, "")
        self.myGrid2.SetColLabelValue(1, "Yesterday")
        self.myGrid2.SetColLabelValue(2, "")
        self.myGrid2.SetColLabelValue(3, "")
        self.myGrid2.SetColLabelValue(4, "Today")
        self.myGrid2.SetColLabelValue(5, "")

        self.myGrid2.SetCellValue(0, 0, "Treasury")
        self.myGrid2.SetCellValue(0, 1, "Volatility")
        self.myGrid2.SetCellValue(0, 2, "Cash")
        self.myGrid2.SetCellValue(0, 3, "Treasury")
        self.myGrid2.SetCellValue(0, 4, "Volatility")
        self.myGrid2.SetCellValue(0, 5, "Cash")

        self.myGrid2.SetRowLabelSize(60)
        self.myGrid2.SetRowLabelValue(0, "")
        self.myGrid2.SetRowLabelValue(1, "2")

        self.myGrid2.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        self.myGrid2.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        # ****************************** #

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.myGrid1, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(self.myGrid2, 1, wx.TOP|wx.ALIGN_CENTRE, 2)
        sizer.Add(button_refresh, 1, wx.RIGHT|wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND|wx.ALIGN_CENTRE, 50)

        self.panel.SetSizer(sizer)
        self.panel.SetSize((500,400))
        self.SetSize((500,400))
        self.panel.Layout()

    def refresh(self, event):
        pass

if __name__ == "__main__":
    app = wx.App()
    frame = MyForm().Show()
    app.MainLoop()

enter image description here

答案 2 :(得分:2)

在wxPython演示中查看GridLabelRenderer示例。它是基于wx.lib.mixins.gridlabelrenderer中的类为网格行和列绘制自定义标签的示例。使用这些类,您可以轻松地绘制标签。您只需要覆盖相应的Draw方法。

答案 3 :(得分:0)

正如@RobinDunn所建议的,这是一个使用GridLabelRenderer的版本(种类),它不像它第一眼看上去那么复杂。
然而它确实有一两个怪癖 请注意使用lr来存储rect.leftrect.right
它是以这种方式完成的,因为如果您调整rect.leftright.right也会调整,而不会让您进行调整。
我认为这是因为rect有一个大小,所以如果你调整1个元素,另一个补偿 另请注意,您必须声明空白列标题,否则它们将恢复为标准" A,B,C,D ....."序列

import wx
import wx.grid as grid
import wx.lib.mixins.gridlabelrenderer as glr
#----------------------------------------------------------------------
class MyGrid(grid.Grid, glr.GridWithLabelRenderersMixin):
    def __init__(self, *args, **kw):
        grid.Grid.__init__(self, *args, **kw)
        glr.GridWithLabelRenderersMixin.__init__(self)

class TextLabelRenderer(glr.GridLabelRenderer):
    def __init__(self, text, colspan,bgcolour=None):
        self.text = text
        self.colspan = colspan
        if bgcolour is not None:
            self.bgcolour = bgcolour
        else:
            self.bgcolour = "white"

    def Draw(self, grid, dc, rect, col):
        if self.colspan == 0:
            rect.SetSize((0,0))
        if self.colspan > 1:
            add_cols = self.colspan - 1
            l = rect.left
            r = rect.right + ((rect.Size.x -1) * add_cols)
            rect.left = l
            rect.right = r
        dc.SetBrush(wx.Brush(self.bgcolour))
        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.DrawRectangleRect(rect)
        hAlign, vAlign = grid.GetColLabelAlignment()
        text = self.text
        if self.colspan != 0:
            self.DrawBorder(grid, dc, rect)
        self.DrawText(grid, dc, rect, text, hAlign, vAlign)

class TestPanel(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, parent=None, size=(800,300))
        ROWS = 6
        COLS = 11
        g = MyGrid(self, size=(100,100))
        g.CreateGrid(ROWS, COLS)
        g.SetColLabelRenderer(0, TextLabelRenderer('Contract',1,"lightblue"))
        g.SetColLabelRenderer(1, TextLabelRenderer('Yesterday',3,"lightgreen"))
        g.SetColLabelRenderer(2, TextLabelRenderer('',0))
        g.SetColLabelRenderer(3, TextLabelRenderer('',0))
        g.SetColLabelRenderer(4, TextLabelRenderer('Today',4,"green"))
        g.SetColLabelRenderer(5, TextLabelRenderer('',0))
        g.SetColLabelRenderer(6, TextLabelRenderer('',0))
        g.SetColLabelRenderer(7, TextLabelRenderer('',0))
        g.SetColLabelRenderer(8, TextLabelRenderer('Other',1,"gold"))
       # g.SetColLabelRenderer(9, TextLabelRenderer('',0))
        g.SetRowLabelSize(0)
        g.SetCellValue(0, 1, "Equity")
        g.SetCellValue(0, 2, "Volatility")
        g.SetCellValue(0, 3, "Cash")
        g.SetCellValue(0, 4, "Equity")
        g.SetCellValue(0, 5, "Volatility")
        g.SetCellValue(0, 6, "Cash")
        g.SetCellValue(1, 0, "2")
        g.SetCellValue(1, 1, "1500")
        g.SetCellValue(1, 2, "23")
        g.SetCellValue(1, 3, "2300")
        g.SetCellValue(1, 4, "1400")
        g.SetCellValue(1, 5, "26")
        g.SetCellValue(1, 6, "2400")
        g.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        g.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )

        g1 = MyGrid(self, size=(100,100))
        g1.CreateGrid(ROWS, COLS)
        g1.SetColLabelRenderer(0, TextLabelRenderer('Contract',1,"lightblue"))
        g1.SetColLabelRenderer(1, TextLabelRenderer('Yesterday',3,"lightgreen"))
        g1.SetColLabelRenderer(2, TextLabelRenderer('',0))
        g1.SetColLabelRenderer(3, TextLabelRenderer('',0))
        g1.SetColLabelRenderer(4, TextLabelRenderer('Today',3,"green"))
        g1.SetColLabelRenderer(5, TextLabelRenderer('',0))
        g1.SetColLabelRenderer(6, TextLabelRenderer('',0))
        g1.SetColLabelRenderer(7, TextLabelRenderer('Other',2,"gold"))
        g1.SetColLabelRenderer(8, TextLabelRenderer('',0))
        g1.SetRowLabelSize(0)
        g1.SetCellValue(0, 1, "Equity")
        g1.SetCellValue(0, 2, "Volatility")
        g1.SetCellValue(0, 3, "Cash")
        g1.SetCellValue(0, 4, "Equity")
        g1.SetCellValue(0, 5, "Volatility")
        g1.SetCellValue(0, 6, "Cash")
        g1.SetCellValue(1, 0, "2")
        g1.SetCellValue(1, 1, "500")
        g1.SetCellValue(1, 2, "23")
        g1.SetCellValue(1, 3, "12300")
        g1.SetCellValue(1, 4, "11400")
        g1.SetCellValue(1, 5, "26")
        g1.SetCellValue(1, 6, "12400")
        g1.SetColLabelAlignment( wx.ALIGN_CENTRE, wx.ALIGN_CENTRE )
        g1.SetDefaultCellAlignment( wx.ALIGN_CENTRE, wx.ALIGN_TOP )
        self.Sizer = wx.BoxSizer(wx.VERTICAL)
        self.Sizer.Add(g, 1, wx.EXPAND)
        self.Sizer.Add(g1, 1, wx.EXPAND)
        self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App()
    frame = TestPanel()
    app.MainLoop()

enter image description here

答案 4 :(得分:0)

您使用wx.Grid提到了您的问题,但是对于不需要此问题的人,可以使用wx.GridBagSizer。它允许项目跨越多个列和/或行。