Hello Everyone, I’m developing the desktop application for mac and I’m using the ultimatlistctrl to show the data on that app. I want to change the color of the hrules. I have attached the mock up image below:
@Robin need your help here
Hello Everyone, I’m developing the desktop application for mac and I’m using the ultimatlistctrl to show the data on that app. I want to change the color of the hrules. I have attached the mock up image below:
@Robin need your help here
One possible solution would be to create a derived class from UltimateListMainWindow
and override its GetRuleColour()
method to return your required colour.
Then create a derived class from UltimateListCtrl
and override its __init__()
method to use the custom version of UltimateListMainWindow
.
Example:
import sys
import wx
import wx.lib.agw.ultimatelistctrl as ULC
class CustomUltimateListMainWindow(ULC.UltimateListMainWindow):
# get the colour to be used for drawing the rules
def GetRuleColour(self):
""" Returns the colour to be used for drawing the horizontal and vertical rules. """
return wx.Colour(255, 0, 0)
class CustomUltimateListCtrl(ULC.UltimateListCtrl):
"""
UltimateListCtrl is a class that mimics the behaviour of :class:`ListCtrl`, with almost
the same base functionalities plus some more enhancements. This class does
not rely on the native control, as it is a full owner-drawn list control.
"""
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
style=0, agwStyle=0, validator=wx.DefaultValidator, name="UltimateListCtrl"):
"""
Default class constructor.
:param `parent`: parent window. Must not be ``None``;
:param `id`: window identifier. A value of -1 indicates a default value;
:param `pos`: the control position. A value of (-1, -1) indicates a default position,
chosen by either the windowing system or wxPython, depending on platform;
:param `size`: the control size. A value of (-1, -1) indicates a default size,
chosen by either the windowing system or wxPython, depending on platform;
:param `style`: the underlying :class:`wx.Control` window style;
:param `agwStyle`: the AGW-specific window style; can be almost any combination of the following
bits:
=============================== =========== ====================================================================================================
Window Styles Hex Value Description
=============================== =========== ====================================================================================================
``ULC_VRULES`` 0x1 Draws light vertical rules between rows in report mode.
``ULC_HRULES`` 0x2 Draws light horizontal rules between rows in report mode.
``ULC_ICON`` 0x4 Large icon view, with optional labels.
``ULC_SMALL_ICON`` 0x8 Small icon view, with optional labels.
``ULC_LIST`` 0x10 Multicolumn list view, with optional small icons. Columns are computed automatically, i.e. you don't set columns as in ``ULC_REPORT``. In other words, the list wraps, unlike a :class:`ListBox`.
``ULC_REPORT`` 0x20 Single or multicolumn report view, with optional header.
``ULC_ALIGN_TOP`` 0x40 Icons align to the top. Win32 default, Win32 only.
``ULC_ALIGN_LEFT`` 0x80 Icons align to the left.
``ULC_AUTOARRANGE`` 0x100 Icons arrange themselves. Win32 only.
``ULC_VIRTUAL`` 0x200 The application provides items text on demand. May only be used with ``ULC_REPORT``.
``ULC_EDIT_LABELS`` 0x400 Labels are editable: the application will be notified when editing starts.
``ULC_NO_HEADER`` 0x800 No header in report mode.
``ULC_NO_SORT_HEADER`` 0x1000 No Docs.
``ULC_SINGLE_SEL`` 0x2000 Single selection (default is multiple).
``ULC_SORT_ASCENDING`` 0x4000 Sort in ascending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
``ULC_SORT_DESCENDING`` 0x8000 Sort in descending order. (You must still supply a comparison callback in :meth:`ListCtrl.SortItems`.)
``ULC_TILE`` 0x10000 Each item appears as a full-sized icon with a label of one or more lines beside it (partially implemented).
``ULC_NO_HIGHLIGHT`` 0x20000 No highlight when an item is selected.
``ULC_STICKY_HIGHLIGHT`` 0x40000 Items are selected by simply hovering on them, with no need to click on them.
``ULC_STICKY_NOSELEVENT`` 0x80000 Don't send a selection event when using ``ULC_STICKY_HIGHLIGHT`` style.
``ULC_SEND_LEFTCLICK`` 0x100000 Send a left click event when an item is selected.
``ULC_HAS_VARIABLE_ROW_HEIGHT`` 0x200000 The list has variable row heights.
``ULC_AUTO_CHECK_CHILD`` 0x400000 When a column header has a checkbox associated, auto-check all the subitems in that column.
``ULC_AUTO_TOGGLE_CHILD`` 0x800000 When a column header has a checkbox associated, toggle all the subitems in that column.
``ULC_AUTO_CHECK_PARENT`` 0x1000000 Only meaningful foe checkbox-type items: when an item is checked/unchecked its column header item is checked/unchecked as well.
``ULC_SHOW_TOOLTIPS`` 0x2000000 Show tooltips for ellipsized items/subitems (text too long to be shown in the available space) containing the full item/subitem text.
``ULC_HOT_TRACKING`` 0x4000000 Enable hot tracking of items on mouse motion.
``ULC_BORDER_SELECT`` 0x8000000 Changes border colour when an item is selected, instead of highlighting the item.
``ULC_TRACK_SELECT`` 0x10000000 Enables hot-track selection in a list control. Hot track selection means that an item is automatically selected when the cursor remains over the item for a certain period of time. The delay is retrieved on Windows using the `win32api` call `win32gui.SystemParametersInfo(win32con.SPI_GETMOUSEHOVERTIME)`, and is defaulted to 400ms on other platforms. This style applies to all views of `UltimateListCtrl`.
``ULC_HEADER_IN_ALL_VIEWS`` 0x20000000 Show column headers in all view modes.
``ULC_NO_FULL_ROW_SELECT`` 0x40000000 When an item is selected, the only the item in the first column is highlighted.
``ULC_FOOTER`` 0x80000000 Show a footer too (only when header is present).
``ULC_USER_ROW_HEIGHT`` 0x100000000 Allows to set a custom row height (one value for all the items, only in report mode).
=============================== =========== ====================================================================================================
:param `validator`: the window validator;
:param `name`: the window name.
"""
self._imageListNormal = None
self._imageListSmall = None
self._imageListState = None
if not agwStyle & ULC.ULC_MASK_TYPE:
raise Exception("UltimateListCtrl style should have exactly one mode bit set")
if not (agwStyle & ULC.ULC_REPORT) and agwStyle & ULC.ULC_HAS_VARIABLE_ROW_HEIGHT:
raise Exception("Style ULC_HAS_VARIABLE_ROW_HEIGHT can only be used in report, non-virtual mode")
if agwStyle & ULC.ULC_STICKY_HIGHLIGHT and agwStyle & ULC.ULC_TRACK_SELECT:
raise Exception("Styles ULC_STICKY_HIGHLIGHT and ULC_TRACK_SELECT can not be combined")
if agwStyle & ULC.ULC_NO_HEADER and agwStyle & ULC.ULC_HEADER_IN_ALL_VIEWS:
raise Exception("Styles ULC_NO_HEADER and ULC_HEADER_IN_ALL_VIEWS can not be combined")
if agwStyle & ULC.ULC_USER_ROW_HEIGHT and (agwStyle & ULC.ULC_REPORT) == 0:
raise Exception("Style ULC_USER_ROW_HEIGHT can be used only with ULC_REPORT")
wx.Control.__init__(self, parent, id, pos, size, style | wx.CLIP_CHILDREN, validator, name)
self._mainWin = None
self._headerWin = None
self._footerWin = None
self._headerHeight = wx.RendererNative.Get().GetHeaderButtonHeight(self)
self._footerHeight = self._headerHeight
if wx.Platform == "__WXGTK__":
style &= ~wx.BORDER_MASK
style |= wx.BORDER_THEME
else:
if style & wx.BORDER_THEME:
style -= wx.BORDER_THEME
self._agwStyle = agwStyle
if style & wx.SUNKEN_BORDER:
style -= wx.SUNKEN_BORDER
self._mainWin = CustomUltimateListMainWindow(self, wx.ID_ANY, wx.Point(0, 0), wx.DefaultSize, style, agwStyle)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self._mainWin, 1, wx.GROW)
self.SetSizer(sizer)
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.CreateOrDestroyHeaderWindowAsNeeded()
self.CreateOrDestroyFooterWindowAsNeeded()
self.SetInitialSize(size)
wx.CallAfter(self.Layout)
# --- DEMO APP ---
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "CustomUltimateListCtrl Demo")
agw_style = ULC.ULC_REPORT | ULC.ULC_VRULES | ULC.ULC_HRULES | ULC.ULC_SINGLE_SEL | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT
u_list = CustomUltimateListCtrl(self, wx.ID_ANY, agwStyle=agw_style)
u_list.InsertColumn(0, "Column 1", format=ULC.ULC_FORMAT_CENTER)
u_list.InsertColumn(1, "Column 2")
u_list.InsertColumn(2, "Column 3", format=ULC.ULC_FORMAT_RIGHT)
index = u_list.InsertStringItem(sys.maxsize, "Item 1")
u_list.SetStringItem(index, 1, "bb")
u_list.SetStringItem(index, 2, "56")
index = u_list.InsertStringItem(sys.maxsize, "Item 2")
u_list.SetStringItem(index, 1, "hh")
u_list.SetStringItem(index, 2, "34")
choice = wx.Choice(u_list, -1, choices=["one", "two"])
index = u_list.InsertStringItem(sys.maxsize, "A widget")
u_list.SetItemWindow(index, 1, choice, expand=True)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(u_list, 1, wx.EXPAND)
self.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
Tested using Python 3.10.12 + wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.2.1 on Linux Mint 21.2
Here is a simpler alternative (if you don’t mind monkey-patching a protected member of a class):
import sys
import types
import wx
import wx.lib.agw.ultimatelistctrl as ULC
# Replacement for UltimateListMainWindow.GetRuleColour()
def getRuleColour(self):
return wx.Colour(255, 0, 0)
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "CustomUltimateListCtrl Demo")
agw_style = ULC.ULC_REPORT | ULC.ULC_VRULES | ULC.ULC_HRULES | ULC.ULC_SINGLE_SEL | ULC.ULC_HAS_VARIABLE_ROW_HEIGHT
u_list = ULC.UltimateListCtrl(self, wx.ID_ANY, agwStyle=agw_style)
# Replace UltimateListMainWindow.GetRuleColour method
u_list._mainWin.GetRuleColour = types.MethodType(getRuleColour, u_list._mainWin)
u_list.InsertColumn(0, "Column 1", format=ULC.ULC_FORMAT_CENTER)
u_list.InsertColumn(1, "Column 2")
u_list.InsertColumn(2, "Column 3", format=ULC.ULC_FORMAT_RIGHT)
index = u_list.InsertStringItem(sys.maxsize, "Item 1")
u_list.SetStringItem(index, 1, "bb")
u_list.SetStringItem(index, 2, "56")
index = u_list.InsertStringItem(sys.maxsize, "Item 2")
u_list.SetStringItem(index, 1, "hh")
u_list.SetStringItem(index, 2, "34")
choice = wx.Choice(u_list, -1, choices=["one", "two"])
index = u_list.InsertStringItem(sys.maxsize, "A widget")
u_list.SetItemWindow(index, 1, choice, expand=True)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(u_list, 1, wx.EXPAND)
self.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
Based on one of the answers to a question on stack overflow.