天天看点

一个典型的GridTableBase样例

文章目录

    • 典型的 GridTableBase 样例
    • 运行图示
    • 说明
    • 程序代码

典型的 GridTableBase 样例

  • wx.grid.GridTableBase 是 wxpython 一个较为常用的控件,这里展示了它的一些用法。

运行图示

一个典型的GridTableBase样例

说明

  • 该程序覆盖了 GridTableBase 的3个基本功能,即新增、插入、删除行数据
  • 该程序还展示了 grid 样式的一些用法。

程序代码

import wx
import wx.grid
from random import randint


def MakeData(num):
    """生成数据,每一行的格式为 (id, name, date, avail)"""
    """num 表示生成的数据的长度,即总共有多少行数据"""
    chars = 'abcdefghijklmnopqrstuvwxyz'

    words = []
    for _ in range(num):
        word = ''
        for _ in range(randint(3, 10)):
            word += chars[randint(0, 25)]
        words.append(word.title())

    rows = []
    for _ in range(num):
        my_date = wx.DateTime(randint(1, 28), randint(0, 11), randint(2000, 2030))
        my_date = my_date.FormatISODate()
        row = (_ + 1, words[_], my_date, randint(0, 1))
        rows.append(row)

    return rows


class MyFrame(wx.Frame):
    def __init__(self, data):
        super().__init__(None, -1, "test grid table's editor", size=(600, 500))
        font = self.GetFont()
        font.SetPointSize(12)
        self.SetFont(font)

        panel = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        tool_bar = wx.ToolBar(panel)
        self.grid = MyGrid(panel, data)
        box.Add(tool_bar, 1, wx.EXPAND | wx.ALL, 5)
        box.Add(self.grid, 1, wx.EXPAND | wx.ALL, 5)
        panel.SetSizerAndFit(box)

        tool_bar.AddControl(wx.Button(tool_bar, wx.ID_ADD, '增加'))
        tool_bar.AddControl(wx.Button(tool_bar, wx.ID_NEW, '插入'))
        tool_bar.AddControl(wx.Button(tool_bar, wx.ID_DELETE, '删除'))
        tool_bar.Realize()

        self.Center()
        self.Show()

        self.Bind(wx.EVT_BUTTON, self.toolbar_handler)

    def toolbar_handler(self, event):
        eid = event.GetId()
        if eid == wx.ID_ADD:
            self.grid.append_row()
        elif eid == wx.ID_NEW:
            self.grid.insert_row()
        elif eid == wx.ID_DELETE:
            self.grid.ClearGrid()


class MyGrid(wx.grid.Grid):
    def __init__(self, parent, data):
        super().__init__(parent)
        self.grid_table = GridTable(data)
        self.SetTable(self.grid_table, True)
        self.avail_index = self.grid_table.col_names.index('avail')     # 获取 avail 列的索引号

        rows = self.grid_table.GetNumberRows()
        cols = self.grid_table.GetNumberCols()

        self.AutoSize()         # 自动调整列宽和行高
        for c in range(cols):
            self.SetColSize(c, self.GetColSize(c) + 20)     # 每列加宽20个像素

        self.SetColFormatNumber(0)                  # 设置为 整数 格式
        self.SetColFormatDate(2, '%Y-%m-%d')        # 设置为 日期 格式,并指定日期的格式
        self.SetColFormatBool(self.avail_index)     # 设置为 布尔 格式,即选定框样式

        for r in range(rows):                       # 设置 avail 列的居中样式
            self.SetCellAlignment(r, self.avail_index, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)

    def append_row(self):
        self.AppendRows()
        self.MakeCellVisible(self.GetNumberRows() - 1, 0)       # 在最底下新增一行,所有要使该行显示出来。

    def insert_row(self):
        row = self.GetGridCursorRow()
        self.InsertRows(row)
        self.SelectRow(row)         # 可以选定该行

    def ClearGrid(self):
        self.DeleteRows(0, self.GetNumberRows())        # 删除所有行
        self.AppendRows(10)                             # 新增了10行
        for row in range(self.GetNumberRows()):
            self.SetCellAlignment(row, self.avail_index, wx.ALIGN_CENTER, wx.ALIGN_CENTER)


class GridTable(wx.grid.GridTableBase):
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.data = [list(_) for _ in self.data]            # 所有数据转化为列表。如果是元组的话不能修改,即不能更改单元格的值。
        self.col_names = ['id', 'name', 'date', 'avail']
        self.pk_name = self.col_names[0]

    def GetCornerLabelValue(self):
        return '行号'

    def GetColLabelValue(self, col):
        return self.col_names[col]

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.col_names)

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        return self.data[row][col]

    def SetValue(self, row, col, value):
        self.data[row][col] = value

    def AppendRows(self, num=1):
        for i in range(num):        # 数据在 AppendRows 时不会自动增加,所以要在这里增加行数据。
            self.data.append([None for _ in self.col_names])

        grid_view = self.GetView()
        grid_view.BeginBatch()
        append_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED, num)
        grid_view.ProcessTableMessage(append_msg)
        grid_view.EndBatch()
        get_value_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        grid_view.ProcessTableMessage(get_value_msg)
        return True

    def InsertRows(self, pos=0, num=1):
        for i in range(num):
            self.data.insert(pos, [None for _ in self.col_names])

        grid_view = self.GetView()
        grid_view.BeginBatch()
        insert_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_INSERTED, pos, num)
        grid_view.ProcessTableMessage(insert_msg)
        grid_view.EndBatch()
        get_value_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        grid_view.ProcessTableMessage(get_value_msg)
        return True

    def DeleteRows(self, pos=0, num=1):
        if self.data is None or len(self.data) == 0:
            return False

        grid_view = self.GetView()
        grid_view.BeginBatch()
        delete_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, pos, num)
        grid_view.ProcessTableMessage(delete_msg)
        grid_view.EndBatch()
        get_value_msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES)
        grid_view.ProcessTableMessage(get_value_msg)

        for i in range(num):    # 记得在该位置删除行数据
            self.data.pop(pos)

        return True


my_data = MakeData(100)

app = wx.App()
frm = MyFrame(my_data)
app.MainLoop()