我正在尝试构建一个由表组成的原型应用程序 链接到图表的数据,将与表格一起显示 并随着数据的变化而更新。
对于表我正在使用ListCtrl派生的对象,因为我想要 为了能够就地编辑数据,我也继承了 TextEditMixin类:
class EditableListCtrl(wx.ListCtrl, listmix.TextEditMixin):
def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
listmix.TextEditMixin.__init__(self)
我想将我的后端数据与其显示分开,所以我的
wx.Frame
- 派生对象具有从中读取的数据源对象
数据填充ListCtrl。
self.list = EditableListCtrl(panel, style=wx.LC_REPORT)
self.list.InsertColumn(0, 'A', width=140)
self.list.InsertColumn(1, 'B', width=130)
for i in range(0, self.db.getNumRecords()):
item = self.db.getRecord(i)
index = self.list.InsertStringItem(sys.maxint, str(item[0]))
self.list.SetStringItem(index, 1, str(item[1]))
由于我现在基本上有两份数据,我想做 确保只要ListCtrl是更新数据源 由用户编辑。
有没有一种标准方法可以做到这一点?
我已尝试绑定到EVT_LIST_ITEM_DESELECTED事件,但它 在TextEditMixin功能更改数据之前触发 ListCtrl - 回调从ListCtrl检索的数据 功能是旧数据。
答案 0 :(得分:3)
有两种方法可以同步数据。
<强> 1。使用虚拟列表控制
使用Virtual ListCtrl时,您不必手动添加数据。它 从您的数据源中提取数据。
要使ListCtrl成为虚拟,请使用以下命令初始化ListCtrl
wx.LC_VIRTUAL
样式标志。
要使Virtual ListCtrl拉取数据,您需要覆盖 以下函数(显然你需要先将ListCtrl子类化):
OnGetItemText(self, item, column)
OnGetItemAttr(self, item)
OnGetItemImage(self, item)
其中第一个处理字符串数据。我没有用过其他的
二。 (如果您不使用它们,请分别返回None
和-1
。)
您还需要调用SetItemCount(item_count)
来告诉ListCtrl
要检索的记录数。
要在用户修改单元格时更新数据源,您需要
实施SetVirtualData(self, row, col, text)
。
有关详细信息,请参阅演示文稿"Advanced wxPython Nuts and Bolts" by Robin Dunn。
<强> 2。使用常规ListCtrl
Subclass ListCtrl并覆盖函数SetStringItem(self, row,
col, text)
。在新的实施中,更新数据源。别
忘了也叫基类SetStringItem()
!除此以外,
ListCtrl外观不会改变。
Virtual ListCtrl有点多功,但推荐使用,因为你不再有两份数据副本。
(感谢Mike Driscoll指出我正确的方向找到这些信息!)
答案 1 :(得分:3)
有一种方法可以解决这种明显的异常现象,您可以在其中编辑数据但看起来您无法访问它,例如执行数据库更新。
您需要将事件绑定到listctrl然后访问event.GetLabel而不是listCtrl.GetText
例如:
self.listCtrl.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnMixUpdate)
然后:
def OnMixUpdate(self, event):
# Set the changed data via the event.GetLabel not listCtrl.GetText which remains unchanged until we change it
rowid = self.listCtrl.GetFocusedItem ()
new_data = event.GetLabel ()
colid = event.GetColumn ()
self.listCtrl.SetStringItem(rowid,colid,new_data,)
#Update a textctrl on screen
self.SetData()
#Update database
self.OnUpdate(None)
event.Skip()
以上是使用普通的listctrl() 在我提出这个解决方案之前,这个特殊问题让我疯狂了一天多。我怀疑还有其他人,但我无法找到。事实上,根据我的网络搜索,似乎没有多少人遇到过这个问题。
您可以更换线路
rowid = self.listCtrl.GetFocusedItem()
与
rowid = event.GetIndex()
得到相同的结果,也许读得更好
答案 2 :(得分:1)
我不明白。你如何拥有两份数据?一个在数据库中,一个在显示?情况总是如此。当谈到这样的事情时,我认为我看到的通常方法是使用Virtual ListCtrl(参见wxPython演示)。
您还可以查看我是如何使用MediaLocker完成的:
或者在我的原始应用中,它是MediaLocker的基础:
http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/
我正在使用ObjectListView而不是ListCtrl,因为我发现它更容易使用。
答案 3 :(得分:1)
我认为您正在寻找的事件是wx.EVT_LIST_END_LABEL_EDIT
。