2

我想编写一个类似表格的 GUI。你知道一个强大的表格小部件(适用于任何 GUI),它具有现成的功能,如过滤、排序、编辑等(如 Excel 中所示)?

4

1 回答 1

6

您可以使用 wxGrid - 这是一些演示代码 - 您需要自己管理/连接底层表上的所有事件。用文字来解释有点复杂,这里有一些代码(主要基于 wx 示例代码):

import wx
from wx import EVT_MENU, EVT_CLOSE
import wx.grid as gridlib

from statusclient import JobDataTable, JobDataGrid


app = wx.App()


log = Logger(__name__)


class JobManager(wx.Frame):

    def __init__(self, parent, title):
        super(JobManager, self).__init__(parent, title=title)
        panel = wx.Panel(self, -1)

        self.client_id = job_server.register()
        log.info('Registered with server as {}'.format(self.client_id))
        self.jobs = job_server.get_all_jobs()
        grid = self.create_grid(panel, self.jobs)       
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(grid, 1, wx.ALL|wx.EXPAND)
        panel.SetSizer(sizer)

        # Bind Close Event
        EVT_CLOSE(self, self.exit)
        self.Center()
        self.Show()

    def exit(self, event):
        log.info('Unregistering {0} from server...'.format(self.client_id))
        job_server.unregister(self.client_id)
        job_server.close()
        exit()

    def create_grid(self, panel, data):
        table = JobDataTable(jobs=data)
        grid = JobDataGrid(panel)
        grid.CreateGrid(len(data), len(data[0].keys()))
        grid.SetTable(table)
        grid.AutoSize()
        grid.AutoSizeColumns(True)
        return grid

def main():
    frame = JobManager(None, 'Larskhill Job Manager')
    app.MainLoop()

if __name__ == '__main__':
        job_server = zerorpc.Client()
        job_server.connect('tcp://0.0.0.0:4242')
    main()


####
ui/client.py
####

import wx
import wx.grid as gridlib

EVEN_ROW_COLOUR = '#CCE6FF'
GRID_LINE_COLOUR = '#ccc'
COLUMNS = {0:('id', 'ID'), 1:('name', 'Name'), 2:('created_at', 'Created'), 3:('status', 'Current Status')}

log = Logger(__name__)

class JobDataTable(gridlib.PyGridTableBase):

    """
    A custom wxGrid Table that expects a user supplied data source.
    """
    def __init__(self, jobs=None):
        gridlib.PyGridTableBase.__init__(self)
        self.headerRows = 0
        self.jobs = jobs

#-------------------------------------------------------------------------------
# Required methods for the wxPyGridTableBase interface
#-------------------------------------------------------------------------------

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

    def GetNumberCols(self):
        return len(COLUMNS.keys())

    #---------------------------------------------------------------------------
    # Get/Set values in the table.  The Python version of these
    # methods can handle any data-type, (as long as the Editor and
    # Renderer understands the type too,) not just strings as in the
    # C++ version. We load thises directly from the Jobs Data.
    #---------------------------------------------------------------------------
    def GetValue(self, row, col):
        prop, label = COLUMNS.get(col)
        #log.debug('Setting cell value')
        return self.jobs[row][prop]

    def SetValue(self, row, col, value):
        pass

    #---------------------------------------------------------------------------
    # Some optional methods
    # Called when the grid needs to display labels
    #---------------------------------------------------------------------------
    def GetColLabelValue(self, col):
        prop, label = COLUMNS.get(col)
        return label

    #---------------------------------------------------------------------------
    # Called to determine the kind of editor/renderer to use by
    # default, doesn't necessarily have to be the same type used
    # natively by the editor/renderer if they know how to convert.
    #---------------------------------------------------------------------------
    def GetTypeName(self, row, col):
        return gridlib.GRID_VALUE_STRING

    #---------------------------------------------------------------------------`
    # Called to determine how the data can be fetched and stored by the
    # editor and renderer.  This allows you to enforce some type-safety
    # in the grid.
    #---------------------------------------------------------------------------
    def CanGetValueAs(self, row, col, typeName):
        pass

    def CanSetValueAs(self, row, col, typeName):
        pass

    #---------------------------------------------------------------------------
    # Style the table, stripy rows and also highlight changed rows.
    #---------------------------------------------------------------------------
    def GetAttr(self, row, col, prop):
        attr = gridlib.GridCellAttr()

        # Odd Even Rows
        if row % 2 == 1:
            bg_colour = EVEN_ROW_COLOUR
            attr.SetBackgroundColour(bg_colour)

        return attr

#-------------------------------------------------------------------------------
# Custom Job Grid
#-------------------------------------------------------------------------------
class JobDataGrid(gridlib.Grid):
    def __init__(self, parent, size=wx.Size(1000, 500), data_table=None):
        self.parent = parent
        gridlib.Grid.__init__(self, self.parent, -1) # so grid references a weak reference to the parent
        self.SetGridLineColour(GRID_LINE_COLOUR)
        self.SetRowLabelSize(0)
        self.SetColLabelSize(30)
        self.table = JobDataTable()

如果需要澄清,请大声告诉我。

于 2012-06-12T10:31:42.780 回答