在 ULC_VIRTUAL 模式下无法使用 UltimateListCtrl 进行项目检查

发布于 2024-12-22 12:36:04 字数 4796 浏览 0 评论 0原文

以下是系统和软件信息

平台:Windows XP 和 OSX Lion
Activestate Python 2.7.2
wxPython2.9-osx-cocoa-py2.7(适用于 OSX)
wxPython2.9-win32-py27(适用于 Windows XP)

我正在尝试使用 ULC_VIRTUAL 和 ULC_REPORT 模式创建 UltimateListCtrl。我想知道如何在每行的第一列旁边放置一个复选框,并在用户选中该框时捕获事件。我可以在没有 VIRTUAL 模式的情况下使用 UltimateListCtrl 执行相同的操作。但是,当 ULC_VIRTUAL 标志打开时,我不知道如何继续。以下是我创建的代码,但这仍然不允许我选中与第一列关联的框。请帮忙。

import wx
    import images
    import random
    import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):

        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_VIRTUAL|ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)
    self.SetItemCount(1000)
    self.table_fields=['First','Second','Third']
    field_index=0
        for field in self.table_fields:
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
        info._image = []
        info._format = wx.LIST_FORMAT_CENTER
        info._kind = 1      
        info._text = field
        info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
        self.InsertColumnInfo(field_index, info)
        self.SetColumnWidth(field_index,175)
        field_index += 1

    def getColumnText(self, index, col):
        item = self.GetItem(index, col)
        return item.GetText()

    def OnGetItemText(self, item, col):
        return "Item %d, Column %d" % (item,col)

    def OnGetItemColumnImage(self, item, col):
        return []

    def OnGetItemImage(self, item):
        return []

    def OnGetItemAttr(self, item):
        return None

    def OnGetItemTextColour(self, item, col):
        return None

    #def OnGetItemColumnCheck(self, item, col):
    #return True

    #def OnGetItemCheck(self, item):
    #return True

    def OnGetItemToolTip(self, item, col):
        return None

    def OnGetItemKind(self, item):
        return 1

    def OnGetItemColumnKind(self, item, col):
        if col==0:
            return self.OnGetItemKind(item)
        return 0

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

顺便说一句,以下是我用来在没有虚拟模式的情况下创建相同内容的代码。在这种情况下,我可以选中每行第一列数据旁边的框。但是,我将处理数以万计的项目,并且我不能依赖于加载如下所示的项目,因为它非常慢。因此,我想使用虚拟列表,但我不知道如何在其中获得相同的功能。

import wx
import images
import random
import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):

        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)

    self.table_fields=['First','Second','Third']
    field_index=0
        for field in self.table_fields:
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
        info._image = []
        info._format = wx.LIST_FORMAT_CENTER
        info._kind = 1      
        info._text = field
        info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
        self.InsertColumnInfo(field_index, info)
        self.SetColumnWidth(field_index,175)
        field_index += 1

    for record_index in range(0,1000):
        for field in self.table_fields:
        if self.table_fields.index(field)==0:
            self.InsertStringItem(record_index, 'Item %d, Column %d' % (record_index,self.table_fields.index(field)),it_kind=1)
        else:
            self.SetStringItem(record_index, self.table_fields.index(field), 'Item %d, Column %d' % (record_index,self.table_fields.index(field)))

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

Following is the system and software info

Platforms: Windows XP and OSX Lion
Activestate Python 2.7.2
wxPython2.9-osx-cocoa-py2.7 (for OSX)
wxPython2.9-win32-py27 (for Windows XP)

I am trying to create a UltimateListCtrl using ULC_VIRTUAL and ULC_REPORT mode. I would like to know how can I put a checkbox beside the first column of every row and catch the event when a user checks the box. I was able to do the same using UltimateListCtrl without VIRTUAL mode. But, with the ULC_VIRTUAL flag ON, I don't know how to proceed. Following is the code I created, but this still doesn't allow me to check the boxes associated with the first column. Please help.

import wx
    import images
    import random
    import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):

        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_VIRTUAL|ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)
    self.SetItemCount(1000)
    self.table_fields=['First','Second','Third']
    field_index=0
        for field in self.table_fields:
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
        info._image = []
        info._format = wx.LIST_FORMAT_CENTER
        info._kind = 1      
        info._text = field
        info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
        self.InsertColumnInfo(field_index, info)
        self.SetColumnWidth(field_index,175)
        field_index += 1

    def getColumnText(self, index, col):
        item = self.GetItem(index, col)
        return item.GetText()

    def OnGetItemText(self, item, col):
        return "Item %d, Column %d" % (item,col)

    def OnGetItemColumnImage(self, item, col):
        return []

    def OnGetItemImage(self, item):
        return []

    def OnGetItemAttr(self, item):
        return None

    def OnGetItemTextColour(self, item, col):
        return None

    #def OnGetItemColumnCheck(self, item, col):
    #return True

    #def OnGetItemCheck(self, item):
    #return True

    def OnGetItemToolTip(self, item, col):
        return None

    def OnGetItemKind(self, item):
        return 1

    def OnGetItemColumnKind(self, item, col):
        if col==0:
            return self.OnGetItemKind(item)
        return 0

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

Btw, following is the code I used to create the same thing without the VIRTUAL mode. And in this case, I can check the boxes beside the first column data in every row. But, I will be working with tens of thousands of items and I cannot rely on loading the items like below because it is very slow. Hence, I want to use the Virtual List, but I don't know how to get the same functionality in it.

import wx
import images
import random
import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):

        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)

    self.table_fields=['First','Second','Third']
    field_index=0
        for field in self.table_fields:
        info = ULC.UltimateListItem()
        info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
        info._image = []
        info._format = wx.LIST_FORMAT_CENTER
        info._kind = 1      
        info._text = field
        info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
        self.InsertColumnInfo(field_index, info)
        self.SetColumnWidth(field_index,175)
        field_index += 1

    for record_index in range(0,1000):
        for field in self.table_fields:
        if self.table_fields.index(field)==0:
            self.InsertStringItem(record_index, 'Item %d, Column %d' % (record_index,self.table_fields.index(field)),it_kind=1)
        else:
            self.SetStringItem(record_index, self.table_fields.index(field), 'Item %d, Column %d' % (record_index,self.table_fields.index(field)))

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

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

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

发布评论

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

评论(1

唯憾梦倾城 2024-12-29 12:36:04

这个问题已经存在一段时间了,我一直在尝试在网络上找到这个问题的解决方案(但无济于事)。我现在已经解决了我的问题,我将其发布在这里,以防万一有人可能会发现该解决方案有用,或者可能有更合适的解决方案。


简短的回答:您需要手动跟踪已检查和未检查的项目。要检测正在检查(单击)的内容,您可以绑定到 EVT_LIST_ITEM_CHECKING 事件。

长答案:首先,您需要一种方法来跟踪哪些项目已检查或未检查。然后使用它来确定 OnGetItemColumnCheck 返回什么内容。例如,您可以使用项目+列的列表,如下所示:

def __init__(...):
    ...
    self.checked = []
    ...

def OnGetItemColumnCheck(self, item, column):
    item_column = (item, column)
    if item_column in self.checked:
        return True
    else:
        return False

您现在需要一种方法来填充该列表。为此,您需要绑定到 EVT_LIST_ITEM_CHECKING 并执行适当的操作:

def __init__(...):
    ...
    self.checked = []
    self.Bind(ULC.EVT_LIST_ITEM_CHECKING, self.OnCheck)
    ...

def OnCheck(self, event):
    item_column = (event.m_itemIndex, event.m_item.GetColumn())
    try:
        idx = self.checked.index(item_column)
    except ValueError:
        idx = None

    if idx == None:
        self.checked.append(item_column)
    else:
        del(self.checked[idx])
    self.Refresh()

self.Refresh() 调用至关重要,因为有时复选框不会重新绘制。之后,您现在应该能够选中和取消选中项目(并且可以轻松访问该信息以启动!)。这是经过上述修改的完整代码:

import wx
import random
import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):
        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_VIRTUAL|ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)
        self.SetItemCount(1000)
        self.table_fields=['First','Second','Third']
        field_index=0
        for field in self.table_fields:
            info = ULC.UltimateListItem()
            info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
            info._image = []
            info._format = wx.LIST_FORMAT_CENTER
            info._kind = 1
            info._text = field
            info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
            self.InsertColumnInfo(field_index, info)
            self.SetColumnWidth(field_index,175)
            field_index += 1

        self.checked = []
        self.Bind(ULC.EVT_LIST_ITEM_CHECKING, self.OnCheck)

    def OnCheck(self, event):
        item_column = (event.m_itemIndex, event.m_item.GetColumn())
        try:
            idx = self.checked.index(item_column)
        except ValueError:
            idx = None

        if idx == None:
            self.checked.append(item_column)
        else:
            del(self.checked[idx])
        self.Refresh()

    def getColumnText(self, index, col):
        item = self.GetItem(index, col)
        return item.GetText()

    def OnGetItemText(self, item, col):
        return "Item %d, Column %d" % (item,col)

    def OnGetItemColumnImage(self, item, col):
        return []

    def OnGetItemImage(self, item):
        return []

    def OnGetItemAttr(self, item):
        return None

    def OnGetItemTextColour(self, item, col):
        return None

    def OnGetItemToolTip(self, item, col):
        return None

    def OnGetItemKind(self, item):
        return 1

    def OnGetItemColumnKind(self, item, col):
        if col==0:
            return self.OnGetItemKind(item)
        return 0

    def OnGetItemColumnCheck(self, item, column):
        item_column = (item, column)
        if item_column in self.checked:
            return True
        else:
            return False

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()

This question has been here for a while and I've been trying to find a solution to this problem around the web (to no avail). I've now solved mine and I'm posting here just in case someone might find the solution useful, or may have an more appropriate one.


Short answer: you will need to manually keep track of checked and unchecked items. To detect which are being checked (clicked), you can bind to the EVT_LIST_ITEM_CHECKING event.

Long answer: First, you will need a way to keep track of which items are checked or not. Then use that for determining what to return for OnGetItemColumnCheck. You could, for example, use a list of item+columns like so:

def __init__(...):
    ...
    self.checked = []
    ...

def OnGetItemColumnCheck(self, item, column):
    item_column = (item, column)
    if item_column in self.checked:
        return True
    else:
        return False

You will now need a way to populate that list. To do that, you will need to bind to the EVT_LIST_ITEM_CHECKING and do the appropriate actions:

def __init__(...):
    ...
    self.checked = []
    self.Bind(ULC.EVT_LIST_ITEM_CHECKING, self.OnCheck)
    ...

def OnCheck(self, event):
    item_column = (event.m_itemIndex, event.m_item.GetColumn())
    try:
        idx = self.checked.index(item_column)
    except ValueError:
        idx = None

    if idx == None:
        self.checked.append(item_column)
    else:
        del(self.checked[idx])
    self.Refresh()

The self.Refresh() call is essential as sometimes the checkbox won't get redrawn. After this, you should now be able to check and uncheck items (and that information is easily accessible to boot!). Here is your complete code with the above modifications:

import wx
import random
import os, sys
from wx.lib.agw import ultimatelistctrl as ULC

class TestUltimateListCtrl(ULC.UltimateListCtrl):
    def __init__(self, parent, log):
        ULC.UltimateListCtrl.__init__(self, parent, -1, agwStyle=ULC.ULC_VIRTUAL|ULC.ULC_REPORT|ULC.ULC_SINGLE_SEL|ULC.ULC_VRULES|ULC.ULC_HRULES)
        self.SetItemCount(1000)
        self.table_fields=['First','Second','Third']
        field_index=0
        for field in self.table_fields:
            info = ULC.UltimateListItem()
            info._mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT | ULC.ULC_MASK_CHECK
            info._image = []
            info._format = wx.LIST_FORMAT_CENTER
            info._kind = 1
            info._text = field
            info._font= wx.Font(13, wx.ROMAN, wx.NORMAL, wx.BOLD)
            self.InsertColumnInfo(field_index, info)
            self.SetColumnWidth(field_index,175)
            field_index += 1

        self.checked = []
        self.Bind(ULC.EVT_LIST_ITEM_CHECKING, self.OnCheck)

    def OnCheck(self, event):
        item_column = (event.m_itemIndex, event.m_item.GetColumn())
        try:
            idx = self.checked.index(item_column)
        except ValueError:
            idx = None

        if idx == None:
            self.checked.append(item_column)
        else:
            del(self.checked[idx])
        self.Refresh()

    def getColumnText(self, index, col):
        item = self.GetItem(index, col)
        return item.GetText()

    def OnGetItemText(self, item, col):
        return "Item %d, Column %d" % (item,col)

    def OnGetItemColumnImage(self, item, col):
        return []

    def OnGetItemImage(self, item):
        return []

    def OnGetItemAttr(self, item):
        return None

    def OnGetItemTextColour(self, item, col):
        return None

    def OnGetItemToolTip(self, item, col):
        return None

    def OnGetItemKind(self, item):
        return 1

    def OnGetItemColumnKind(self, item, col):
        if col==0:
            return self.OnGetItemKind(item)
        return 0

    def OnGetItemColumnCheck(self, item, column):
        item_column = (item, column)
        if item_column in self.checked:
            return True
        else:
            return False

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "UltimateListCtrl in wx.LC_VIRTUAL mode", size=(700, 600))
        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)
        listCtrl = TestUltimateListCtrl(panel, log)
        sizer.Add(listCtrl, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        sizer.Layout()
        self.CenterOnScreen()
        self.Show()

if __name__ == '__main__':
    import sys
    app = wx.PySimpleApp()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文