![](/img/trans.png)
[英]Wxpython Phoenix editable listctrl unable to access the changed data
[英]How do I synchronize data between an editable ListCtrl and a data source?
我正在尝试构建一个包含链接到图形的数据表的原型应用程序,该表将在表旁边显示并随着数据的变化而更新。
对于表,我使用的是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检索的数据是旧数据。
解决这种明显异常的方法是,您可以编辑数据,但是似乎无法访问它,例如,执行数据库更新。 您需要将事件绑定到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()并获得相同的结果,也许读起来更好
有两种同步数据的方法。
1.使用虚拟ListCtrl
使用虚拟ListCtrl时,不必手动添加数据。 它从数据源中提取数据。
要使ListCtrl虚拟,请使用wx.LC_VIRTUAL
样式标志初始化ListCtrl。
为了使Virtual ListCtrl能够提取数据,您需要重写以下函数(显然,您需要首先对ListCtrl进行子类化):
OnGetItemText(self, item, column)
OnGetItemAttr(self, item)
OnGetItemImage(self, item)
其中第一个处理字符串数据。 我没有用过另外两个。 (如果不使用它们,则分别返回None
和-1
。)
您还需要调用SetItemCount(item_count)
来告诉ListCtrl要检索多少条记录。
要在用户修改单元格时更新数据源,您需要实现SetVirtualData(self, row, col, text)
。
有关更多信息,请参见Robin Dunn的演示文稿“ Advanced wxPython Nuts and Bolts” 。
2.使用常规的ListCtrl
子类ListCtrl并重写功能SetStringItem(self, row, col, text)
。 在新的实现中,更新数据源。 但是不要忘记也调用基类SetStringItem()
! 否则,ListCtrl外观将不会更改。
Virtual ListCtrl的工作量还多一些,但建议您这样做,因为您将不再获得两个数据副本。
(感谢Mike Driscoll为我指出正确的方向以找到此信息!)
我想您正在寻找的事件是wx.EVT_LIST_END_LABEL_EDIT
。
我不明白 您如何获得数据的两个副本? 一个在数据库中,一个在显示中? 情况总是如此。 当涉及到这样的事情时,我认为我看到的广告宣传的通常方法是使用Virtual ListCtrl(请参阅wxPython演示)。
您也可以看看我是如何使用MediaLocker做到的:
或在我原来的应用程序中,它是MediaLocker的基础:
http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/
我使用ObjectListView而不是ListCtrl,因为我发现它更易于使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.