如何在可编辑 ListCtrl 和数据源之间同步数据?

发布于 2025-01-02 05:13:37 字数 1111 浏览 1 评论 0 原文

我正在尝试构建一个由表格组成的原型应用程序 链接到图表的数据,该图表将显示在表格旁边 并随着数据的变化而更新。

对于表,我使用的是 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 检索的数据 函数是旧数据。

I'm trying to build a prototype application that consists of a table
of data linked to a graph, which will be displayed alongside the table
and updated as the data changes.

For the table I'm using a ListCtrl-derived object and, because I want
to be able to edit the data in-place, I'm also inheriting the
TextEditMixin class:

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)

I want to keep my back-end data separate from its display, so my
wx.Frame-derived object has a data source object from which it reads
data to populate the 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]))

Since I now essentially have two copies of the data, I'd like to make
sure that the data source is updated whenever the ListCtrl is
edited by the user.

Is there a standard way to do this?

I have tried binding to the EVT_LIST_ITEM_DESELECTED event, but it
triggers before the TextEditMixin functionality changes the data in
the ListCtrl - the data retrieved from the ListCtrl by the callback
function is the old data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最美不过初阳 2025-01-09 05:13:37

有两种方法可以同步数据。

1.使用虚拟ListCtrl

使用虚拟ListCtrl 时,您不必手动添加数据。它
从您的数据源中提取数据。

要使 ListCtrl 虚拟,请使用以下命令初始化 ListCtrl
wx.LC_VIRTUAL 样式标志。

为了让 Virtual ListCtrl 拉取数据,您需要覆盖
以下函数(显然您需要首先子类化 ListCtrl):

OnGetItemText(self, item, column)
OnGetItemAttr(self, item)
OnGetItemImage(self, item)

第一个函数处理字符串数据。其他的我没用过
二。 (如果您不使用它们,只需分别返回 None-1。)

您还需要调用 SetItemCount(item_count) 来告知列表控件
要检索多少条记录。

要在用户修改单元格时更新数据源,您需要
实现 SetVirtualData(self, row, col, text)。

有关更多信息,请参阅 Robin Dunn 的演示文稿 “高级 wxPython 的具体细节”

2.使用常规 ListCtrl

子类 ListCtrl 并覆盖函数 SetStringItem(self, row,
列,文本)
。在新的实施中,更新您的数据源。不
但忘了调用基类 SetStringItem()!否则,
ListCtrl 的外观不会改变。

虚拟 ListCtrl 的工作量更大,但推荐使用,因为您最终不再拥有数据的两个副本。

(感谢 Mike Driscoll 为我指明了查找此信息的正确方向!)

There are two ways to synchronise the data.

1. Use a Virtual ListCtrl

When using a Virtual ListCtrl, you don't have to add data manually. It
pulls data from your data source.

To make a ListCtrl virtual, initialise the ListCtrl with the
wx.LC_VIRTUAL style flag.

For the Virtual ListCtrl to pull the data, you need to override the
following functions (obviously you need to subclass ListCtrl first):

OnGetItemText(self, item, column)
OnGetItemAttr(self, item)
OnGetItemImage(self, item)

The first of these handles string data. I haven't used the other
two. (If you're not using them, just return None and -1 respectively.)

You also need to call SetItemCount(item_count) to tell the ListCtrl
how many records to retrieve.

To update the data source when the user modifies a cell, you need to
implement SetVirtualData(self, row, col, text).

See the presentation "Advanced wxPython Nuts and Bolts" by Robin Dunn for more information.

2. Use a regular ListCtrl

Subclass ListCtrl and override the function SetStringItem(self, row,
col, text)
. In your new implementation, update your data source. Don't
forget to also call the base class SetStringItem() though! Otherwise,
the ListCtrl appearance won't change.

Virtual ListCtrl is a bit more work, but recommended because you no longer end up with two copies of the data.

(Thanks to Mike Driscoll for pointing me in the right direction to find this information!)

羅雙樹 2025-01-09 05:13:37

有一种方法可以解决这种明显的异常情况,即您编辑数据,但似乎无法访问它,例如执行数据库更新。
您需要将事件绑定到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()
并得到相同的结果,也许读起来更好

There is a way around this apparent anomaly, where you edit the data and yet it appears that you cannot access it, to perform a database update for example.
You need to bind the event to the listctrl and then access event.GetLabel not listCtrl.GetText
for example:

self.listCtrl.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnMixUpdate)

and then:

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()

The above is using a normal listctrl()
This particular problem drove me nuts for more than day before I came up with this solution. I suspect that there are others but I couldn't find one. In fact based my web searches it doesn't appear that more than a handful of people have come across this problem.

You can replace the line
rowid = self.listCtrl.GetFocusedItem ()
with
rowid = event.GetIndex()
and get the same result which perhaps reads better

逐鹿 2025-01-09 05:13:37

我不明白。你如何拥有数据的两份副本?一份在数据库中,一份在显示中?情况总是如此。当谈到这样的事情时,我认为我看到的广告中常用的方法是使用 Virtual ListCtrl(请参阅 wxPython 演示)。

您还可以看看我如何使用 MediaLocker 做到这一点:

http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%E2%80%93-a-wxpython-app-to-track-your-media/< /a>

或者在我原来的应用程序中,它是 MediaLocker 的基础:

http:// www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/

我正在使用ObjectListView 而不是 ListCtrl,因为我发现它更容易使用。

I don't get it. How do you have two copies of the data? One in the database and one on display? That's always going to be the case. When it comes to something like this, I think the usual method I've seen advertised is to use a Virtual ListCtrl (see the wxPython demo).

You can also look at how I did it with MediaLocker:

http://www.blog.pythonlibrary.org/2011/12/09/ann-medialocker-%E2%80%93-a-wxpython-app-to-track-your-media/

Or in my original app that was the basis for MediaLocker:

http://www.blog.pythonlibrary.org/2011/11/10/wxpython-and-sqlalchemy-an-intro-to-mvc-and-crud/

I'm using ObjectListView instead of the ListCtrl as I find it easier to use.

傲性难收 2025-01-09 05:13:37

我认为您要查找的事件是 wx.EVT_LIST_END_LABEL_EDIT

The event you're looking for is wx.EVT_LIST_END_LABEL_EDIT, I think.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文