天天看点

wxpython grid 表格快速定位及排序wxpython grid 表格快速定位及排序程序代码

wxpython grid 表格快速定位及排序

简介

当表格中数据较多时,通常需要对数据进行快速定位及排序,以下程序演示了如何实现这两个功能。

为方便中在其他程序中调用,这两个功能都做成了类中的函数。

功能介绍

  • 快速定位
      1. 到顶部
      1. 回退到上一页
      1. 快进到下一页
      1. 到底部
  • 按列排序
    • 左键双击列名进行排序;
    • 默认为升序,如果重复双击列名,则在升序、降序中反转。

图例

wxpython grid 表格快速定位及排序wxpython grid 表格快速定位及排序程序代码

程序代码

import wx.grid
import string
import random


class MyPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent)
        font = self.GetFont()
        font.SetPointSize(12)
        self.SetFont(font)

        self.order_col = [0, False]     # 待排序的列索引, 是否逆序
        self.grid = wx.grid.Grid(self)

        self.data = make_data(100)
        self.n_rows = len(self.data)
        self.col_names = ['编号', '姓名', '生日', '有效性']
        self.n_cols = len(self.col_names)

        self.on_init()

        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_DCLICK, self.label_left_dclick)   # 双击列名,进行排序

    def on_init(self):
        box = wx.BoxSizer(wx.VERTICAL)

        panel_fast = wx.Panel(self)
        GridTools(self.grid).fast_move_bar(panel_fast)      # 加入表格数据快进按钮
        box.Add(panel_fast, 0, wx.ALL, 5)

        box.Add(self.grid, 1, wx.EXPAND | wx.ALL, 5)
        self.SetSizerAndFit(box)

        self.grid.CreateGrid(self.n_rows, self.n_cols)
        for col in range(self.n_cols):
            self.grid.SetColLabelValue(col, self.col_names[col])

        for row in range(self.n_rows):
            for col in range(self.n_cols):
                self.grid.SetCellValue(row, col, str(self.data[row][col]))
                if col == self.col_names.index('有效性'):
                    self.grid.SetCellAlignment(row, col, wx.ALIGN_CENTER, wx.ALIGN_CENTER)

        self.grid_style()

    def grid_style(self):
        self.grid.SetColFormatNumber(0)
        self.grid.SetColFormatDate(2, "%Y-%m-%d")
        self.grid.SetColFormatBool(3)

        self.grid.AutoSizeColumns()
        for col in range(self.n_cols):
            self.grid.SetColSize(col, self.grid.GetColSize(col) + 10)

    def label_left_dclick(self, _):
        self.order_col = GridTools(self.grid).order_grid(self.order_col)


class GridTools:
    def __init__(self, grid: wx.grid.Grid):
        self.grid = grid

    def get_grid_data(self):
        grid_data = []
        for row in range(self.grid.GetNumberRows()):
            row_data = []
            for col in range(self.grid.GetNumberCols()):
                row_data.append(self.grid.GetCellValue(row, col))
            grid_data.append(row_data)
        return grid_data

    def show_grid(self, data):
        """在表格中显示 data"""
        for row in range(self.grid.GetNumberRows()):
            for col in range(self.grid.GetNumberCols()):
                self.grid.SetCellValue(row, col, str(data[row][col]))

    def fast_move_bar(self, parent_panel):
        """快速移动表格定位,快进、快退以表格页面为单位。"""
        panel = wx.Panel(parent_panel)
        fast_btn = [wx.Button(panel, wx.ID_TOP, '|<'), wx.Button(panel, wx.ID_BACKWARD, '<<'),
                    wx.Button(panel, wx.ID_FORWARD, '>>'), wx.Button(panel, wx.ID_BOTTOM, '>|')]
        box = wx.BoxSizer()
        box.AddMany(fast_btn)
        panel.SetSizerAndFit(box)

        def btn_handler(event):
            eid = event.GetId()
            if eid == wx.ID_TOP:
                self.grid.GoToCell(0, 0)
            elif eid == wx.ID_BACKWARD:
                self.grid.MovePageUp()
            elif eid == wx.ID_FORWARD:
                self.grid.MovePageDown()
            elif eid == wx.ID_BOTTOM:
                self.grid.GoToCell(self.grid.GetNumberRows()-1, 0)

        panel.Bind(wx.EVT_BUTTON, btn_handler)

    def order_grid(self, last_col: list):
        """双击列名以排序, last_col: 上次排序的列的索引号、是否逆序,如 [0, False]"""
        clicked_col = self.grid.GetGridCursorCol()
        if clicked_col == last_col[0]:
            last_col[1] = not last_col[1]       # 如果列索引相同,则顺序反转
        grid_data = self.get_grid_data()
        grid_data.sort(key=lambda x: x[clicked_col], reverse=last_col[1])
        self.show_grid(grid_data)
        return [clicked_col, last_col[1]]


def make_data(n=10):
    """产生随机数据"""
    data = []
    for i in range(n):
        my_id = i + 1

        name = ''
        for _ in range(random.randint(3, 10)):
            name += string.ascii_lowercase[random.randint(0, 25)]
        name = name.title()

        date = wx.DateTime.FromDMY(1, 0, 1990) + wx.DateSpan(days=random.randint(0, 365*20))
        birthday = wx.DateTime.FormatISODate(date)

        avail = '1' if random.randint(0, 1) else ''

        data.append((my_id, name, birthday, avail))
    return data


if __name__ == '__main__':
    app = wx.App()
    frm = wx.Frame(None, -1, 'grid 快进及排序', size=(600, 500))
    MyPanel(frm)
    frm.Center()
    frm.Show()
    app.MainLoop()