wxptyhon中DataViewCtrl和PyDataViewModel的使用示例
wxptyhon的文档很简单,关于DataViewCtrl和PyDataViewModel的使用示例没找到,所以这里记录一下。
wxptyhon中DataViewCtrl和PyDataViewModel的使用示例:
import wx
from loguru import logger
import wx.dataview as dv
class MergeDataViewModel(dv.PyDataViewModel):
"""
用于管理和展示合并PDF文件的数据模型类。
继承自wx.dataview.PyDataViewModel。
"""
def __init__(self):
"""
初始化MergeDataViewModel对象。
创建一个空的数据列表。
items = dv.DataViewItemArray()
是一个专门设计用来存储和管理 DataViewItem 对象的容器,它通常用于批量操作或通知多个项目的变化。
它的主要目的是为了提高性能,因为 DataViewItem 是一个相对昂贵的对象,在每次添加或删除项目时都要创建和销毁。
通过使用 DataViewItemArray,您可以一次性创建多个 DataViewItem,然后将它们添加到 DataView 中,
这可以减少创建和销毁对象的开销。
在 DataView 中,DataViewItemArray 通常用于以下情况:
批量添加项目:当您需要一次性添加多个项目时,使用 DataViewItemArray 可以提高性能。
批量删除项目:当您需要一次性删除多个项目时,同样可以使用 DataViewItemArray 来提高性能。
DataViewItem 是 wxPython 中用于在 DataView 控件中唯一标识一个项目的对象
在 PyDataViewModel 中:
bjectToItem 方法通常将 Python 对象包装成 DataViewItem,它可能简单地将行索引(一个整数)转换为 DataViewItem。
ItemToObject 方法(在 GetRow 中使用)是 ObjectToItem 的反向操作,它将 DataViewItem 转换回 Python 对象(这里是行索引)。
"""
dv.PyDataViewModel.__init__(self)
self.data = []
def GetColumnCount(self):
"""
返回数据模型的列数。
Returns:
int: 列数,固定为5。
"""
return 5
def GetColumnType(self, col):
"""
返回指定列的数据类型。
Args:
col (int): 列索引。
Returns:
str: 列的数据类型,所有列均为"string"。
"""
return "string"
def GetValue(self, item, col):
"""
获取指定项和列的值。
Args:
item: DataViewItem对象,表示要获取值的行。
col (int): 列索引。
Returns:
str: 指定单元格的值,如果索引无效则返回空字符串。
"""
if item:
row = self.GetRow(item)
# 检查 row 和 col 是否在有效范围内
if 0 <= row < len(self.data) and 0 <= col < len(self.data[row]):
return str(self.data[row][col])
return ""
def SetValue(self, value, item, col):
"""
设置指定项和列的值。
Args:
value: 要设置的新值。
item: DataViewItem对象,表示要设置值的行。
col (int): 列索引。
Returns:
bool: 如果设置成功返回True,否则返回False。
"""
if item:
row = self.GetRow(item)
# 检查 row 和 col 是否在有效范围内
if 0 <= row < len(self.data) and 0 <= col < len(self.data[row]):
self.data[row][col] = value
return True
return False
def GetAttr(self, item, col, attr):
"""
获取指定项和列的属性。
此方法可用于设置单元格的自定义样式。
Args:
item: DataViewItem对象。
col (int): 列索引。
attr: 属性对象。
Returns:
bool: 始终返回False,表示不使用自定义属性。
"""
return False
def GetChildren(self, parent, children):
"""
获取指定父项的所有子项。
Args:
parent: 父DataViewItem对象。
children: DataViewItemArray对象,用于存储子项。
Returns:
int: 子项数量。
"""
if not parent:
for i in range(len(self.data)):
children.append(self.ObjectToItem(i))
return len(self.data)
return 0
def IsContainer(self, item):
"""
判断指定项是否为容器(即是否可以包含子项)。
Args:
item: DataViewItem对象。
Returns:
bool: 如果是根项(即item为空)返回True,否则返回False。
"""
return not item
def GetParent(self, item):
"""
获取指定项的父项。
Args:
item: DataViewItem对象。
Returns:
DataViewItem: 始终返回NullDataViewItem,因为这是一个平面结构。
"""
return dv.NullDataViewItem
def AddRow(self, row_data):
"""
添加新行到数据模型。
Args:
row_data (list): 要添加的行数据。
"""
index = len(self.data)
self.data.append(row_data)
# 通知视图有新行添加
items = dv.DataViewItemArray()
items.append(self.ObjectToItem(index))
self.ItemsAdded(dv.NullDataViewItem, items)
def DeleteRow(self, row):
"""
从数据模型中删除指定行。
Args:
row (int): 要删除的行索引。
"""
if 0 <= row < len(self.data):
del self.data[row]
# 通知视图有行被删除
items = dv.DataViewItemArray()
items.append(self.ObjectToItem(row))
self.ItemsDeleted(dv.NullDataViewItem, items)
def GetRow(self, item):
"""
根据 DataViewItem 获取对应的行索引。
Args:
item: DataViewItem对象。
Returns:
int: 对应的行索引。
"""
return self.ItemToObject(item)
# 示例用法
class MainFrame(wx.Frame):
def __init__(self, parent=None, id=wx.ID_ANY, title="DataView Example"):
wx.Frame.__init__(self, parent, id, title, size=(800, 600))
# 创建 DataViewCtrl
self.dvc = dv.DataViewCtrl(self, style=wx.BORDER_THEME | dv.DV_ROW_LINES | dv.DV_VERT_RULES)
# 创建数据模型
self.model = MergeDataViewModel()
self.dvc.AssociateModel(self.model)
# 添加列
self.dvc.AppendTextColumn("id", 0, width=100)
self.dvc.AppendTextColumn("name", 1, width=150)
self.dvc.AppendTextColumn("page_nums", 2, width=100)
self.dvc.AppendTextColumn("file_size", 3, width=100)
self.dvc.AppendTextColumn("merge_method", 4, width=150)
# 添加一些示例数据
self.model.AddRow([1, "file1.pdf", 10, "10MB", "Sequential"])
self.model.AddRow([2, "file2.pdf", 20, "20MB", "Parallel"])
# 创建按钮
self.add_button = wx.Button(self, label="Add Row")
self.delete_button = wx.Button(self, label="Delete Selected Row")
# 绑定按钮事件
self.add_button.Bind(wx.EVT_BUTTON, self.OnAddRow)
self.delete_button.Bind(wx.EVT_BUTTON, self.OnDeleteRow)
# 创建布局
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.dvc, 1, wx.EXPAND | wx.ALL, 5)
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
button_sizer.Add(self.add_button, 0, wx.ALL, 5)
button_sizer.Add(self.delete_button, 0, wx.ALL, 5)
sizer.Add(button_sizer, 0, wx.ALIGN_CENTER)
self.SetSizer(sizer)
def OnAddRow(self, event):
new_row = [len(self.model.data) + 1, "new_file.pdf", 0, "0MB", "None"]
self.model.AddRow(new_row)
def OnDeleteRow(self, event):
selected_item = self.dvc.GetSelection()
if selected_item:
row = self.model.GetRow(selected_item)
self.model.DeleteRow(row)
if __name__ == "__main__":
app = wx.App()
frame = MainFrame()
frame.Show()
app.MainLoop()