wxPython学习(7.高级窗口)

1.分隔窗口

分隔窗口就是将窗口分成两部分,即左右或上下两部分。
例:将整体分为左右两个窗口,右窗口又分为上下两窗口,两窗口之间的分隔线是可以拖动的,称为“窗框”

wx.SplitterWindow 中常用的方法有:
(1)SplitVertically(window1, window2, sashPosition=0)
设置左右布局的分隔窗口,window1 为左窗口,window2 为右窗口,sashPosition 是窗框的位置。
(2)SplitHorizontally(window1, window2, sashPosition=0)
设置上下布局的分隔窗口,window1 为上窗口,window2 为下窗口,sashPosition 是窗框的位置。
(3)SetMinimumPaneSize(paneSize)
设置最小窗口尺寸,如果是左右布局是指左窗口的最小尺寸,如果是上下布局是指上窗口的最小尺寸。如果没有设置则默认为 0。


分割窗是一种特殊的容器窗口部件,它管理两个子窗口。这两个子窗口可以被水平的堆放或彼此左右相邻。在两个子窗口之间的是一个窗框,它是一个可移动的边框,移动它就改变了两个子窗口的尺寸。分割窗经常被用于主窗口的侧边栏。

1.创建一个分割窗
在wxPython中,分割窗是类wx.SplitterWindow的实例。和大多数其它的wxPython窗口部件不一样,分隔窗口在被创建后,可使用前要求进一步的初始化。

构造函数:
wx.SplitterWindow(parent, id=-1, pos=wx.DefaultPosition,size=wx.DefaultSize, style=wx.SP_3D,name=”splitterWindow”)
它的这些参数都有标准的含义——parent是窗口部件的容器,pos是窗口部件在它的父容器中位置,size是它的尺寸。

2.在创建了这个分割窗后,在它可以被使用前,你必须对这个窗口调用三个方法中的一处。如果你想初始时只显示一个子窗口,那么调用Initialize(window),参数window是这个单一的子窗口(通常是一种wx.Panel)。在这种情况下,窗口将在以后响应用户的动作时再分割。

3.要显示两个子窗口,使用SplitHorizontally (window1,window2,sashPosition=0)或SplitVertically(window1, window2, sashPosition=0)。
两个方法的工作都是相似的,参数window1和window2包含两个子窗口,参数sashPosition包含分割条的初始位置。对于水平分割(水平分割条)来说,window1被放置在window2的顶部。如果sashPosition是一个正数,它代表顶部窗口的初始高度(也就是分割条距顶部的像素值)。如果sashPosition是一个负数,它定义了底部窗口的尺寸,或分割条距底部的像素值。如果sashPosition是0,那么这个分割条位于正中。对于垂直分割(垂直分割条),window1位于左边,window2位于右边。
正值的sashPosition设置window1的尺寸,也就是分割条距左边框的像素值。类似的,负值sashPosition设置右边子窗口的尺寸,0值将分割条放置在正中。如果你的子窗口复杂的话,我们建议你在布局中使用sizer,以便于当分割条被移动时很好地调整窗口的大小。

例:如图

#分隔窗口
import wx

# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='分隔窗口', size=(350, 180))
        self.Centre()  # 设置窗口居中

        #创建一个分隔窗
        splitter = wx.SplitterWindow(self, -1)
        #创建子面板
        leftpanel = wx.Panel(splitter)
        rightpanel = wx.Panel(splitter)
        #分隔窗口
        splitter.SplitVertically(leftpanel, rightpanel, 100)
        splitter.SetMinimumPaneSize(80)#设置最小窗口尺寸,这里指的是左窗口尺寸
            
        #列表,单选
        list2 = ['苹果', '橘子', '香蕉']
        lb2 = wx.ListBox(leftpanel, -1, choices=list2, style=wx.LB_SINGLE)
        self.Bind(wx.EVT_LISTBOX, self.on_listbox, lb2)#绑定事件

        #创建一个垂直方向的box布局管理器vbox1,将列表添加到vbox中,将vbox1添加到左侧控制面板中
        vbox1 = wx.BoxSizer(wx.VERTICAL)
        vbox1.Add(lb2, 1, flag=wx.ALL | wx.EXPAND, border=5)
        leftpanel.SetSizer(vbox1)

        #创建一个垂直方向的box布局管理器vbox2,创建一个静态文本并添加到vbox2中,将vbox2添加到右侧面板中
        vbox2 = wx.BoxSizer(wx.VERTICAL)
        self.content = wx.StaticText(rightpanel, label='右侧面板')
        vbox2.Add(self.content, 1, flag=wx.ALL | wx.EXPAND, border=5)
        rightpanel.SetSizer(vbox2)


    def on_listbox(self, event):
        s = '选择 {0}'.format(event.GetString())
        self.content.SetLabel(s)


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

 

2.使用树

树(tree)是一种通过层次结构展示信息的控件,在wxPython中树控件类是wx.TreeCtrl

wx.TreeCtrl 中常用的方法有:
(1)AddRoot(text, image=-1, selImage=-1, data=None)。
添加根节点,text 参数根节点显示的文本;image 参数是该节点未被选中时的图片索引,wx.TreeCtrl 中使用的图片被放到 wx.ImageList 图像列表中;selImage 参数是该节点被选中时的图片索引。data 参数是给节点传递的数据。方法返回节点,节点类型是 wx.TreeItemId。
(2)AppendItem(parent, text, image=-1, selImage=-1, data=None)。
添加子节点,parent 参数是父节点,其他参数同 AddRoot()方法。方法返回值 wx.TreeItemId。
(3)SelectItem(item, select=True)。选中 item 节点
(4)Expand(item)。展开 item 节点
(5)ExpandAll()。展开根节点下的所有子节点。
(6)ExpandAllChildren(item)。展开 item 节点下的所有子节点。
(7)AssignImageList(imageList)。保存 wx.ImageList 图像列表到树中,这样就可以在AddRoot()和 AppendItem()方法中使用图像列表索引了。


wx.TreeCtrl的构造函数是一个典型的wxPython窗口部件构造函数
wx.TreeControl(parent, id=-1, pos=wx.DefaultPosition,size=wx.DefaultSize, style=wx.TR_HAS_BUTTONS,validator=wx.DefaultValidator, name=”treeCtrl”)
该构造函数提供给你了一个没有元素的空的树。

1.当你将项目添加到树时,你首先必须要添加的项目是root(根)元素。添加根元素的方法如下所示:
AddRoot(text, image=-1, selImage=-1, data=None)
你只能添加一个根元素。如果你在已经存在一个根元素后,再添加第二根元素的话,那么wxPython将引发一个异常。其中的参数text包含用于根元素的显示字符串。参数image是图像列表中的一个索引,代表要显示在参数text旁边的图像。它的行为类似于用于列表控件的图像列表。参数data是一个与项目相关的数据对象,主要的目的是分类。

AddRoot()方法返回一个关于根项目的ID。树形控件使用它自己的类wx.TreeItemId来管理项目。在大多数时候,你不需要关心ID的具体值,你只需要知道每个项目都有一个唯一的wx.TreeItemId就够了,并且这个值可以使用等号测试。wx.TreeItemId不映射到任何简单的类型——它的值没有任何的关联性,因为你只是把它用于相等测试。

2.一旦你有了根元素,你就可以开始向树中添加元素了。用的最多的方法是
AppendItem(parent, text, image=-1, selImage=-1, data=None)。
参数parent是已有的树项目的wx.TreeItemId,它作为新项目的父亲。参数text是显示新项目的文本字符串。参数image和selImage的意义与方法AddRoot()中的相同。该方法将新的项目放置到其父项目的孩子列表的末尾。这个方法返回新创建的项目的wx.TreeItemId。如果你想给新的项目添加子项目的话,你需要拥有这个ID。

rootId = tree.AddRoot(“The Root”)
childId = tree.AppendItem(rootId, ”A Child”)
grandChildId = tree.AppendItem(childId, ”A Grandchild”)
上面的这个代码片断增加了一个root(根)项目,然后给根项目添加了一个子项目,然后给子项目添加了它的子项目。

如果要将子项目添加到孩子列表的开头的话,使用方法PrependItem(parent, text, image=-1, selImage=-1, data=None)。

如果你想将一个项目插入树的任意点上,你可以使用后面的两种方法之一。
第一个是InsertItem(parent, previous, text,image=-1, selImage=-1, data=None)。
其中参数previous其父项目中的子列表中的项目的wx.TreeItemId。插入的项目将放置在该项目的后面。
第二个方法是InsertItemBefore(parent, before, text, image=-1, selImage=-1, data=None)。
该方法将新的项目放置在before所代表的项目之前。然而参数before不是一个项目的ID。它是项目在孩子列表中的整数索引。第二个方法返回新项目的一个wx.TreeItemId。


3.要去掉树中的一个项目,可以使用Delete(item)方法,其中参数item是该项目的wx.TreeItemId。调用这个方法将导致一个EVT_TREE_Delete_ITEM类型的树的事件被触发。后面的章节我们将讨论树的事件类型。要删除一个项目的所有子项目,而留下该项目自身,可以使用方法DeleteChildren(item),其中参数item也是一个wx.TreeItemId。该方法不产生一个删除事件。要清除整个树,使用方法DeleteAllItems()。该方法为每个项目生成一个删除事件,但是,这在某些老版的Windows系统上不工作。

4.一旦你将一个项目添加到树中,你就可以使用方法GetItemText(item)来得到该项目在显示在树中的文本,其中参数item是一个wx.TreeItemId。如果你想改变一个项目的显示文本,可以使用方法SetItemText(item, text),其中参数item是一个wx.TreeItemId,参数text是一个新的显示文本。

5.你可以使用方法GetCount()来得到树中项目的总数。如果你想得到特定项目下的子项目的数量,可以使用方法GetChildrenCount(item, recursively=True)。其中参数item是一个wx.TreeItemId,参数recursively如果为False,那么该方法只返回直接的子项目的数量,如果为True,则返回所有的子项目而不关嵌套有多深。

样式:
树控件中的按钮
wx.TR_HAS_BUTTONS:有按钮。在Windows上,+用于标明项目可以被展开,-表示可以折叠。
wx.TR_NO_BUTTONS:没有按钮。

树控件中的连接线:它们决定树控件将连接线绘制在何处。
wx.TR_LINES_AT_ROOT:如果设置了这个样式,那么树控件将在多个root项目之间绘制连线。注意,如果wx.TR_HIDE_ROOT被设置了,那么你就有多个root项目。
wx.TR_NO_LINES:如果设置了这个样式,那么树控件将不在兄弟项目间绘制连接线。这个样式将代替wx.TR_LINES_AT_ROOT。
wx.TR_ROW_LINES :树控件在行之间将绘制边距

树控件的选择模式
wx.TR_EXTENDED:可以选择多个不连续的项。不是对所有的系统有效。
wx.TR_MULTIPLE:可以选择一块且仅一块连续的项。
wx.TR_SINGLE:一次只能选择一个结点。这是默认模式。

树的其它显示样式
wx.TR_FULL_ROW_HIGHLIGHT:如果设置了这个样式,那么当被选择时,被选项的整个行将高亮显示。默认情况下,只是文本区高亮。在Windows上,该样式只在也设置wx.NO_LINES时有效。
wx.TR_HAS_VARIABLE_ROW_HEIGHT:如果设置了这个样式,则行的高度将根据其中的图像和文本而不同。否则,所有的行将是同样的高度(取决于最高的行)。
wx.TR_HIDE_ROOT:如果设置了这个样式,则通过AddRoot()确定的root元素将不被显示。此时该结节的所有子项就如同它们是root一样显示。这个样式用于让一个树具有多个root元素的外观。

当树控件中发生选择变化的时候,有两个事件将被触发并可被捕获。第一个事件是wx.EVT_TREE_SEL_CHANGING,它在被选项实际改变之前发生。如果你要处理这个事件,你可以使用事件的Veto()方法来阻止选择的改变。在选择已经改变之后,事件wx.EVT_TREE_SEL_CHANGED被触发。这两个事件的类是wx.TreeEvent

树控件的另外的几个事件
wx.EVT_TREE_BEGIN_DRAG:当用户通过按下鼠标左键来拖动树中的一个项目时,触发该事件。要让拖动时能够做些事情,该事件的处理函数必须显式地调用事件的Allow()方法。
wx.EVT_TREE_BEGIN_RDRAG:当用户通过按下鼠标右键来拖动树中的一个项目时,触发该事件。要让拖动时能够做些事情,该事件的处理函数必须显式地调用事件的Allow()方法。
wx.EVT_TREE_ITEM_ACTIVATED:当一个项目通过双击被激活时,触发该事件。
wx.EVT_TREE_ITEM_GETTOOLTIP:当鼠标停留在树中的一个项目上时,触发该事件。该事件可用来为项目设置特定的提示。只需要在事件对像中简单地设置标签参数,其它的将由系统来完成。
wx.EVT_TREE_KEY_DOWN:在树控件获得焦点的情况下,当一个键被按下时触发该事件。

例:如图

#使用树
import wx

# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='树控件', size=(500, 400))
        self.Centre()  # 设置窗口居中

        splitter = wx.SplitterWindow(self)
        leftpanel = wx.Panel(splitter)
        rightpanel = wx.Panel(splitter)
        splitter.SplitVertically(leftpanel, rightpanel, 200)
        splitter.SetMinimumPaneSize(80)
            
        #创建并初始化一个树
        self.tree = self.CreateTreeCtrl(leftpanel)#传递过去父容器
        #绑定点击事件
        self.Bind(wx.EVT_TREE_SEL_CHANGING, self.on_click, self.tree)
        
        vbox1 = wx.BoxSizer(wx.VERTICAL)
        vbox1.Add(self.tree, 1, flag=wx.ALL | wx.EXPAND, border=5)
        leftpanel.SetSizer(vbox1)

        vbox2 = wx.BoxSizer(wx.VERTICAL)
        self.content = wx.StaticText(rightpanel, label='右侧面板')
        vbox2.Add(self.content, 1, flag=wx.ALL | wx.EXPAND, border=5)
        rightpanel.SetSizer(vbox2)

    def on_click(self, event):
        item = event.GetItem()
        self.content.SetLabel(self.tree.GetItemText(item))#选中的节点的文本写入右侧静态文本中

    #创建并初始化一个tree
    def CreateTreeCtrl(self, parent):
        #创建一个tree
        tree = wx.TreeCtrl(parent)

        items = []
        #创建图像列表,宽、高、掩模、初始容量
        imglist = wx.ImageList(16, 16, True, 2)
        #参数:图片、尺寸,这里用的自带的图片
        imglist.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, size=wx.Size(16, 16)))
        imglist.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, size=wx.Size(16, 16)))
        tree.AssignImageList(imglist)#将图片绑定到树上

        root = tree.AddRoot("TreeRoot", image=0)#添加根节点

        items.append(tree.AppendItem(root, "Item 1", 0))#添加子节点
        items.append(tree.AppendItem(root, "Item 2", 0))
        items.append(tree.AppendItem(root, "Item 3", 0))
        items.append(tree.AppendItem(root, "Item 4", 0))
        items.append(tree.AppendItem(root, "Item 5", 0))
        
        #遍历每个子节点,并添加子元素
        for ii in range(len(items)):
            id = items[ii]
            tree.AppendItem(id, "Subitem 1", 1)
            tree.AppendItem(id, "Subitem 2", 1)
            tree.AppendItem(id, "Subitem 3", 1)
            tree.AppendItem(id, "Subitem 4", 1)
            tree.AppendItem(id, "Subitem 5", 1)

        #初始树的状态
        tree.Expand(root)  # 展开根下子节点
        tree.Expand(items[0])  # 展开Item 1下子节点
        tree.Expand(items[3])  # 展开Item 4下子节点
        tree.SelectItem(root)  # 选中根节点

        return tree


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

 

3.使用网格

wxPython 网格类是 wx.grid.Grid。

添加单元格数据比较麻烦,而且对于网格的控制也很少,为此可以使用wx.grid.GridTableBase类,该类是一个抽象类,开发人员需要实现给类的一些方法。


网格鼠标事件的单元格事件类型
wx.grid.EVT_GRID_CELL_CHANGE:当用户通过编辑器改变单元格中的数据时触发该事件。
wx.grid.EVT_GRID_CELL_LEFT_CLICK:当用户在一个单元格中敲击鼠标左键时触发该事件。
wx.grid.EVT_GRID_CELL_LEFT_DCLICK:当用户在一个单元格中双击鼠标左键时触发该事件。
wx.grid.EVT_GRID_CELL_RIGHT_CLICK:当用户在一个单元格中敲击鼠标右键时触发该事件。
wx.grid.EVT_GRID_CELL_RIGHT_DCLICK:当用户在一个单元格中双击鼠标右键时触发该事件。
wx.grid.EVT_GRID_EDITOR_HIDDEN:当在编辑会话结束时隐藏一个单元格编辑器则触发该事件。
wx.grid.EVT_GRID_EDITOR_SHOWN:当在编辑会话结束时显示一个单元格编辑器则触发该事件。
wx.grid.EVT_GRID_LABEL_LEFT_CLICK:当用户在行或列的标签区域敲击鼠标左键时触发该事件。
wx.grid.EVT_GRID_LABEL_LEFT_DCLICK:当用户在行或列的标签区域双击鼠标左键时触发该事件。
wx.grid.EVT_GRID_LABEL_RIGHT_CLICK:当用户在行或列的标签区域敲击鼠标右键时触发该事件。
wx.grid.EVT_GRID_LABEL_RIGHT_DCLICK:当用户在行或列的标签区域双击鼠标右键时触发该事件。
wx.grid.EVT_GRID_Select_CELL:当用户将焦点移到一个新的单元格,并选择它时触发该事件。


要将网格表实例附着于你的表的实例,要调用SetTable(table,takeOwnership=False,selmode=wx.grid.Grid.SelectCells)方法。其中参数table是你的wx.grid.PyGridTableBase的实例。参数takeOwnership使得网格控件拥有这个表。如果takeOwnership为True,那么当网格被删除时,该表也被wxPython系统删除。参数selmode作用等同于在CreateGrid()中的作用。

例:如图

#使用网格
import wx
import wx.grid

#list of list
data = [['0036', '高等数学', '李放', '人民邮电出版社', '20000812', '1'],
        ['0004', 'FLASH精选', '刘扬', '中国纺织出版社', '19990312', '2'],
        ['0026', '软件工程', '牛田', '经济科学出版社', '20000328', '4'],
        ['0015', '人工智能', '周未', '机械工业出版社', '19991223', '3'],
        ['0037', '南方周末', '邓光明', '南方出版社', '20000923', '3'],
        ['0008', '新概念3', '余智', '外语出版社', '19990723', '2'],
        ['0019', '通讯与网络', '欧阳杰', '机械工业出版社', '20000517', '1'],
        ['0014', '期货分析', '孙宝', '飞鸟出版社', '19991122', '3'],
        ['0023', '经济概论', '思佳', '北京大学出版社', '20000819', '3'],
        ['0017', '计算机理论基础', '戴家', '机械工业出版社', '20000218', '4'],
        ['0002', '汇编语言', '李利光', '北京大学出版社', '19980318', '2'],
        ['0033', '模拟电路', '邓英才', '电子工业出版社', '20000527', '2'],
        ['0011', '南方旅游', '王爱国', '南方出版社', '19990930', '2'],
        ['0039', '黑幕', '李仪', '华光出版社', '20000508', '14'],
        ['0001', '软件工程', '戴国强', '机械工业出版社', '19980528', '2'],
        ['0034', '集邮爱好者', '李云', '人民邮电出版社', '20000630', '1'],
        ['0031', '软件工程', '戴志名', '电子工业出版社', '20000324', '3'],
        ['0030', '数据库及应用', '孙家萧', '清华大学出版社', '20000619', '1'],
        ['0024', '经济与科学', '毛波', '经济科学出版社', '20000923', '2'],
        ['0009', '军事要闻', '张强', '解放军出版社', '19990722', '3'],
        ['0003', '计算机基础', '王飞', '经济科学出版社', '19980218', '1'],
        ['0020', '现代操作系统', '王小国', '机械工业出版社', '20010128', '1'],
        ['0025', '计算机体系结构', '方丹', '机械工业出版社', '20000328', '4'],
        ['0010', '大众生活', '许阳', '电子出版社', '19990819', '3'],
        ['0021', '网络基础', '王大尉', '北京大学出版社', '20000617', '1'],
        ['0006', '世界杯', '柳飞', '世界出版社', '19990412', '2'],
        ['0028', '高级语言程序设计', '寇国华', '清华大学出版社', '20000117', '3'],
        ['0038', '十大旅游胜地', '潭晓明', '南方出版社', '20000403', '2'],
        ['0018', '编译原理', '郑键', '机械工业出版社', '20000415', '2'],
        ['0007', 'JAVA程序设计', '张余', '人民邮电出版社', '19990613', '1'],
        ['0013', '幽灵', '钱力华', '华光出版社', '19991008', '1'],
        ['0022', '万紫千红', '丛丽', '北京大学出版社', '20000702', '3'],
        ['0027', '世界语言大观', '候丙辉', '经济科学出版社', '20000814', '2'],
        ['0029', '操作系统概论', '聂元名', '清华大学出版社', '20001028', '1'],
        ['0016', '数据库系统概念', '吴红', '机械工业出版社', '20000328', '3'],
        ['0005', 'java基础', '王一', '电子工业出版社', '19990528', '3'],
        ['0032', 'SQL使用手册', '贺民', '电子工业出版社', '19990425', '2']]

column_names = ['书籍编号', '书籍名称', '作者', '出版社', '出版日期', '库存数量']


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='网格控件', size=(550, 500))
        self.Centre()  # 设置窗口居中
        
        #创建成员变量,一个网格对象
        self.grid = self.CreateGrid(self)
        #绑定事件,当用户在行或列的标签区域敲击鼠标左键时触发该事件
        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)

    def OnLabelLeftClick(self, event):
        print("RowIdx:{0}".format(event.GetRow()))#行索引
        print("ColIdx:{0}".format(event.GetCol()))#列索引
        print(data[event.GetRow()])
        event.Skip()#确保还可以响应其他事件处理

    #创建网格对象
    def CreateGrid(self, parent):
        grid = wx.grid.Grid(parent)
        grid.CreateGrid(len(data), len(data[0]))#行、列

        #添加数据
        for row in range(len(data)):
            for col in range(len(data[row])):
                grid.SetColLabelValue(col, column_names[col])#设置列标题
                grid.SetCellValue(row, col, data[row][col])#设置单元格内容
                
                #SetRowLabelValue(),SetColLabelValue()和SetCellValue(),它们实际上设置显示在网格中的值
                #SetCellValue()方法要求一个行索引、一个列索引和一个值。而其它两个方法要求一个索引和一个值。
                
        # 设置行和列自定调整
        grid.AutoSize()

        return grid


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环

另一种方法,使用自定义网格

import wx
import wx.grid

data = [['0036', '高等数学', '李放', '人民邮电出版社', '20000812', '1'],
        ['0004', 'FLASH精选', '刘扬', '中国纺织出版社', '19990312', '2'],
        ['0026', '软件工程', '牛田', '经济科学出版社', '20000328', '4'],
        ['0015', '人工智能', '周未', '机械工业出版社', '19991223', '3'],
        ['0037', '南方周末', '邓光明', '南方出版社', '20000923', '3'],
        ['0008', '新概念3', '余智', '外语出版社', '19990723', '2'],
        ['0019', '通讯与网络', '欧阳杰', '机械工业出版社', '20000517', '1'],
        ['0014', '期货分析', '孙宝', '飞鸟出版社', '19991122', '3'],
        ['0023', '经济概论', '思佳', '北京大学出版社', '20000819', '3'],
        ['0017', '计算机理论基础', '戴家', '机械工业出版社', '20000218', '4'],
        ['0002', '汇编语言', '李利光', '北京大学出版社', '19980318', '2'],
        ['0033', '模拟电路', '邓英才', '电子工业出版社', '20000527', '2'],
        ['0011', '南方旅游', '王爱国', '南方出版社', '19990930', '2'],
        ['0039', '黑幕', '李仪', '华光出版社', '20000508', '14'],
        ['0001', '软件工程', '戴国强', '机械工业出版社', '19980528', '2'],
        ['0034', '集邮爱好者', '李云', '人民邮电出版社', '20000630', '1'],
        ['0031', '软件工程', '戴志名', '电子工业出版社', '20000324', '3'],
        ['0030', '数据库及应用', '孙家萧', '清华大学出版社', '20000619', '1'],
        ['0024', '经济与科学', '毛波', '经济科学出版社', '20000923', '2'],
        ['0009', '军事要闻', '张强', '解放军出版社', '19990722', '3'],
        ['0003', '计算机基础', '王飞', '经济科学出版社', '19980218', '1'],
        ['0020', '现代操作系统', '王小国', '机械工业出版社', '20010128', '1'],
        ['0025', '计算机体系结构', '方丹', '机械工业出版社', '20000328', '4'],
        ['0010', '大众生活', '许阳', '电子出版社', '19990819', '3'],
        ['0021', '网络基础', '王大尉', '北京大学出版社', '20000617', '1'],
        ['0006', '世界杯', '柳飞', '世界出版社', '19990412', '2'],
        ['0028', '高级语言程序设计', '寇国华', '清华大学出版社', '20000117', '3'],
        ['0038', '十大旅游胜地', '潭晓明', '南方出版社', '20000403', '2'],
        ['0018', '编译原理', '郑键', '机械工业出版社', '20000415', '2'],
        ['0007', 'JAVA程序设计', '张余', '人民邮电出版社', '19990613', '1'],
        ['0013', '幽灵', '钱力华', '华光出版社', '19991008', '1'],
        ['0022', '万紫千红', '丛丽', '北京大学出版社', '20000702', '3'],
        ['0027', '世界语言大观', '候丙辉', '经济科学出版社', '20000814', '2'],
        ['0029', '操作系统概论', '聂元名', '清华大学出版社', '20001028', '1'],
        ['0016', '数据库系统概念', '吴红', '机械工业出版社', '20000328', '3'],
        ['0005', 'java基础', '王一', '电子工业出版社', '19990528', '3'],
        ['0032', 'SQL使用手册', '贺民', '电子工业出版社', '19990425', '2']]

column_names = ['书籍编号', '书籍名称书籍名称', '作者', '出版社', '出版日期', '库存数量']

#自定义网格
class MyGridTable(wx.grid.GridTableBase):
    #构造方法
    def __init__(self):
        super().__init__()
        self.colLabels = column_names#成员变量,列标题
    #要求类实现的方法,因为wx.grid.GridTableBase类,该类是一个抽象类
    def GetNumberRows(self):  #获取行数
        return len(data)

    def GetNumberCols(self): # 获取列数
        return len(data[0])

    def GetValue(self, row, col):  # 获取每个单元格值
        return data[row][col]

    def GetColLabelValue(self, col):  # 获取一列的标签
        return self.colLabels[col]


# 自定义窗口类MyFrame
class MyFrame(wx.Frame):
    def __init__(self):
        super().__init__(parent=None, title='网格控件', size=(550, 500))
        self.Centre()  # 设置窗口居中
        self.grid = self.CreateGrid(self)
        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.OnLabelLeftClick)

    def OnLabelLeftClick(self, event):
        print("RowIdx:{0}".format(event.GetRow()))
        print("ColIdx:{0}".format(event.GetCol()))
        print(data[event.GetRow()])
        event.Skip()

    def CreateGrid(self, parent):
        grid = wx.grid.Grid(parent)
        tablebase = MyGridTable()
        
        grid.SetTable(tablebase, True)#把自定义的MyGridTable放进去实例化
        # 设置行和列自定调整
        grid.AutoSize()

        return grid


class App(wx.App):

    def OnInit(self):
        # 创建窗口对象
        frame = MyFrame()
        frame.Show()
        return True


if __name__ == '__main__':
    app = App()
    app.MainLoop()  # 进入主事件循环


 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值