在 MouseOver 上突出显示 wx.ListCtrl 中的 ListItem

发布于 2024-12-21 09:48:46 字数 3930 浏览 0 评论 0原文

我有一个 wxListCtrl 显示带有信息的表格(带有行和列字段)。通常,仅当您用鼠标按钮单击该行时,该行才会突出显示。但我想突出显示而不点击它。即当我将鼠标移动到不同的行时,该行将突出显示而无需单击鼠标。这可能吗?

########################################################################

导入wx

导入sys,glob

class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        self.index = 0

    self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                     style=wx.LC_REPORT
                     |wx.BORDER_SUNKEN
                     )
    self.list_ctrl.InsertColumn(0, 'Subject')
    self.list_ctrl.InsertColumn(1, 'Due')
    self.list_ctrl.InsertColumn(2, 'Location', width=125)
    self.list_ctrl.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
    self.list_ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)

    btn = wx.Button(panel, label="Add Line")
    btn.Bind(wx.EVT_BUTTON, self.add_line)

    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
    sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
    panel.SetSizer(sizer)   


    bmp = wx.Image("icon.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
    il = wx.ImageList(16,16)
    il.Add(bmp)
    self.list_ctrl.AssignImageList(il,wx.IMAGE_LIST_SMALL)      
    line = "Line %s" % self.index


    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    self.index += 1     

    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    #self.list_ctrl.SetItemBackgroundColour(self.index,wx.LIGHT_GREY)
    self.index += 1 

    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")

    self.index += 1             


#----------------------------------------------------------------------
def add_line(self, event):
    if self.index > 0:
        image = 1
    else:
        image = -1    
    line = "Line %s" % self.index
    self.list_ctrl.InsertStringItem(self.index, line,image)
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    self.index += 1

def onMouseOver(self, event):
    print "mouse over"
    for item in range(self.list_ctrl.GetItemCount()):
         self.list_ctrl.SetItemBackgroundColour(item,wx.NullColor)
    x = event.GetX()
    y = event.GetY()
    item, flags = self.list_ctrl.HitTest((x, y))
    self.list_ctrl.SetItemBackgroundColour(item,wx.RED)
    #self.list_ctrl.RefreshItems(0,2)
    event.Skip()

def onMouseLeave(self, event):
    print "mouse leave"
    for item in range(self.list_ctrl.GetItemCount()):
         self.list_ctrl.SetItemBackgroundColour(item,wx.NullColor)
    #self.list_ctrl.RefreshItems(0,2)
    event.Skip()
'''         
def onMouseOver(self, event):    #USED to display tooltip on items that cannot be selected

    x = event.GetX()
    y = event.GetY()
    item, flags = self.list_ctrl.HitTest((x, y))
    color = self.list_ctrl.GetItemBackgroundColour(item) 
    if color == wx.NullColor:

        self.list_ctrl.SetItemBackgroundColour(item,wx.RED)
    elif color == wx.RED:
        item = item - 1
        color = self.list_ctrl.GetItemBackgroundColour(item) 
        self.list_ctrl.SetItemBackgroundColour(item,wx.Nu)

'''       
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()    

I have a wxListCtrl that display a table with information (with rows and column fields). Typically the row will be highlighted only when you click it with the mouse button. But I would like to have the highlight without clicking it. i.e. When I move the mouse to different row, the row will be highlighted without clicking the mouse. Is this possible?

########################################################################

import wx

import sys, glob

class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "List Control Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        self.index = 0

    self.list_ctrl = wx.ListCtrl(panel, size=(-1,100),
                     style=wx.LC_REPORT
                     |wx.BORDER_SUNKEN
                     )
    self.list_ctrl.InsertColumn(0, 'Subject')
    self.list_ctrl.InsertColumn(1, 'Due')
    self.list_ctrl.InsertColumn(2, 'Location', width=125)
    self.list_ctrl.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
    self.list_ctrl.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)

    btn = wx.Button(panel, label="Add Line")
    btn.Bind(wx.EVT_BUTTON, self.add_line)

    sizer = wx.BoxSizer(wx.VERTICAL)
    sizer.Add(self.list_ctrl, 0, wx.ALL|wx.EXPAND, 5)
    sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
    panel.SetSizer(sizer)   


    bmp = wx.Image("icon.bmp", wx.BITMAP_TYPE_BMP).ConvertToBitmap()
    il = wx.ImageList(16,16)
    il.Add(bmp)
    self.list_ctrl.AssignImageList(il,wx.IMAGE_LIST_SMALL)      
    line = "Line %s" % self.index


    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    self.index += 1     

    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    #self.list_ctrl.SetItemBackgroundColour(self.index,wx.LIGHT_GREY)
    self.index += 1 

    self.list_ctrl.InsertStringItem(self.index, line,-1)  
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")

    self.index += 1             


#----------------------------------------------------------------------
def add_line(self, event):
    if self.index > 0:
        image = 1
    else:
        image = -1    
    line = "Line %s" % self.index
    self.list_ctrl.InsertStringItem(self.index, line,image)
    self.list_ctrl.SetStringItem(self.index, 1, "01/19/2010")
    self.list_ctrl.SetStringItem(self.index, 2, "USA")
    self.index += 1

def onMouseOver(self, event):
    print "mouse over"
    for item in range(self.list_ctrl.GetItemCount()):
         self.list_ctrl.SetItemBackgroundColour(item,wx.NullColor)
    x = event.GetX()
    y = event.GetY()
    item, flags = self.list_ctrl.HitTest((x, y))
    self.list_ctrl.SetItemBackgroundColour(item,wx.RED)
    #self.list_ctrl.RefreshItems(0,2)
    event.Skip()

def onMouseLeave(self, event):
    print "mouse leave"
    for item in range(self.list_ctrl.GetItemCount()):
         self.list_ctrl.SetItemBackgroundColour(item,wx.NullColor)
    #self.list_ctrl.RefreshItems(0,2)
    event.Skip()
'''         
def onMouseOver(self, event):    #USED to display tooltip on items that cannot be selected

    x = event.GetX()
    y = event.GetY()
    item, flags = self.list_ctrl.HitTest((x, y))
    color = self.list_ctrl.GetItemBackgroundColour(item) 
    if color == wx.NullColor:

        self.list_ctrl.SetItemBackgroundColour(item,wx.RED)
    elif color == wx.RED:
        item = item - 1
        color = self.list_ctrl.GetItemBackgroundColour(item) 
        self.list_ctrl.SetItemBackgroundColour(item,wx.Nu)

'''       
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()    

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

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

发布评论

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

评论(3

盗琴音 2024-12-28 09:48:46

当您创建 ListCtrl 并将其放入变量中时,我会尝试抓取其中一个 ListItems 的背景颜色:

self.defaultItemColor = someListItem.GetBackgroundColour()

然后使用它来将颜色改回来。调用项目的 setter 后,有时还需要调用 ListCtrl 的 SetItem(listItem) 方法。由于某些原因,将背景设置为 NullColour 不适用于 ListCtrl。当我为我的一个应用程序创建黑暗模式时,我发现了这一点。我实际上在这里写过: http:// /www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/

I would try grabbing the background color of one of the ListItems when you create the ListCtrl and putting it in a variable:

self.defaultItemColor = someListItem.GetBackgroundColour()

Then use that to change the color back. After you call the item's setter, you sometimes need to call the ListCtrl's SetItem(listItem) method as well. For some reason, setting the background to NullColour doesn't work with the ListCtrl. I discovered that back when I was creating a dark mode for one of my applications. I actually wrote about it here: http://www.blog.pythonlibrary.org/2011/11/05/wxpython-creating-a-dark-mode/

画离情绘悲伤 2024-12-28 09:48:46

我知道这是一个迟到的回复,但以下内容对我有用:
self.listCtrl.Bind(wx.EVT_MOTION, self.onMouseOver)
并将 self.previous_item 最初设置为 -1

我用它来突出显示鼠标悬停在该行上的行,并同时更改工具提示。

def onMouseOver(self, event):
    x = event.GetX()
    y = event.GetY()
    self.item, flags = self.listCtrl.HitTest((x, y))
    if self.item < 0:
        self.listCtrl.SetToolTipString("Colour codes Red - Loaded, Yellow - In Progress, Green - Finished, Blue - Invoiced, White - User defined")
        return
    if self.item != self.previous_item:
        self.old_item = self.previous_item
        self.previous_item = self.item
    else:
        return
    bg_colour = self.listCtrl.GetItemBackgroundColour(self.item) 
    if bg_colour == wx.BLACK or bg_colour == wx.NullColour:
        self.listCtrl.SetItemBackgroundColour(self.item,"#3246A8")
        self.listCtrl.SetItemBackgroundColour(self.old_item,wx.BLACK)
    elif bg_colour == "#3246A8":
        self.listCtrl.SetItemBackgroundColour(self.item,wx.BLACK)
    self.currentItem = self.item
    rowid = self.listCtrl.GetItem(self.currentItem,13)
    stat_test = rowid.GetText()
    rowid = self.listCtrl.GetItem(self.currentItem,1)
    file_test = rowid.GetText()
    rowid = self.listCtrl.GetItem(self.currentItem,4)
    running_test = rowid.GetText()

    if stat_test == "0":
        self.listCtrl.SetToolTipString("File currently playing\nRunning time "+running_test)
    elif stat_test == "1":
        self.listCtrl.SetToolTipString("In Progress\nRunning time "+running_test)
    elif stat_test == "2":
        self.listCtrl.SetToolTipString("Finished\nRunning time "+running_test)
    elif stat_test == "3":
        self.listCtrl.SetToolTipString("Invoiced\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "1":
        self.listCtrl.SetToolTipString("File currently playing & In Progress\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "2":
        self.listCtrl.SetToolTipString("File currently playing but Finished\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "3":
        self.listCtrl.SetToolTipString("File currently playing but Invoiced\nRunning time "+running_test)

我希望它能帮助别人

I know that this is a late response but the following works for me using:
self.listCtrl.Bind(wx.EVT_MOTION, self.onMouseOver)
and setting self.previous_item initially to -1

I am using it to highlight the row with the mouse over it and alter the tooltip at the same time.

def onMouseOver(self, event):
    x = event.GetX()
    y = event.GetY()
    self.item, flags = self.listCtrl.HitTest((x, y))
    if self.item < 0:
        self.listCtrl.SetToolTipString("Colour codes Red - Loaded, Yellow - In Progress, Green - Finished, Blue - Invoiced, White - User defined")
        return
    if self.item != self.previous_item:
        self.old_item = self.previous_item
        self.previous_item = self.item
    else:
        return
    bg_colour = self.listCtrl.GetItemBackgroundColour(self.item) 
    if bg_colour == wx.BLACK or bg_colour == wx.NullColour:
        self.listCtrl.SetItemBackgroundColour(self.item,"#3246A8")
        self.listCtrl.SetItemBackgroundColour(self.old_item,wx.BLACK)
    elif bg_colour == "#3246A8":
        self.listCtrl.SetItemBackgroundColour(self.item,wx.BLACK)
    self.currentItem = self.item
    rowid = self.listCtrl.GetItem(self.currentItem,13)
    stat_test = rowid.GetText()
    rowid = self.listCtrl.GetItem(self.currentItem,1)
    file_test = rowid.GetText()
    rowid = self.listCtrl.GetItem(self.currentItem,4)
    running_test = rowid.GetText()

    if stat_test == "0":
        self.listCtrl.SetToolTipString("File currently playing\nRunning time "+running_test)
    elif stat_test == "1":
        self.listCtrl.SetToolTipString("In Progress\nRunning time "+running_test)
    elif stat_test == "2":
        self.listCtrl.SetToolTipString("Finished\nRunning time "+running_test)
    elif stat_test == "3":
        self.listCtrl.SetToolTipString("Invoiced\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "1":
        self.listCtrl.SetToolTipString("File currently playing & In Progress\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "2":
        self.listCtrl.SetToolTipString("File currently playing but Finished\nRunning time "+running_test)
    if file_test == self.file_playing and stat_test == "3":
        self.listCtrl.SetToolTipString("File currently playing but Invoiced\nRunning time "+running_test)

I Hope it helps someone

油焖大侠 2024-12-28 09:48:46

这并不是“容易”开箱即用的,但您应该能够通过一些修改来完成。

您必须向 wxListCtrl 对象添加 mouseover 和 mouseout 事件侦听器,然后在每次收到 mouseover 事件时测试哪个项目被击中。您也许能够缓存列表项的坐标,但如果您采用此方法,滚动列表和窗口大小调整可能会造成问题。

一些帮助您入门的代码(未经测试,可能不起作用,您需要将 MyListCtrl 添加到合适的 wx.Frame ):

import wx

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent, id):
        wx.ListCtrl.__init__(self, parent, id)
        self.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)

    def onMouseOver(self, event):
        #Loop through all items and set bgcolor to default, then:
        item = self.HitTest(event.GetPosition())
        self.SetItemBackgroundColour(item, 'Green')
        self.RefreshItems()
        event.Skip()

    def onMouseLeave(self, event):
        #Loop through all items and set bgcolor to default, then:
        self.RefreshItems()
        event.Skip()

This is not "easily" done out of the box, but you should be able to do it with a bit of tinkering.

You'll have to add a mouseover and mouseout event listener to your wxListCtrl object, and then test which item is being hit each time you get a mouseover event. You may be able to cache the coordinates of the list items, but scrolling lists and window resizes could pose a problem if you go this route.

Some code to get you started (not tested, probably won't work and you'd need to add a MyListCtrl to a suitable wx.Frame):

import wx

class MyListCtrl(wx.ListCtrl):
    def __init__(self, parent, id):
        wx.ListCtrl.__init__(self, parent, id)
        self.Bind(wx.EVT_ENTER_WINDOW, self.onMouseOver)
        self.Bind(wx.EVT_LEAVE_WINDOW, self.onMouseLeave)

    def onMouseOver(self, event):
        #Loop through all items and set bgcolor to default, then:
        item = self.HitTest(event.GetPosition())
        self.SetItemBackgroundColour(item, 'Green')
        self.RefreshItems()
        event.Skip()

    def onMouseLeave(self, event):
        #Loop through all items and set bgcolor to default, then:
        self.RefreshItems()
        event.Skip()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文