I have a DesktopListbox inside a DesktopContainer, with an instance of the container on a PagePanel. I can resize the PagePanel, and even though the listbox is not resized by this action, every cell is repainted many times as the resizing takes place, leading to a poor user experience due to jerkiness.
Is anyone aware of any tricks to mitigate this sort of behaviour? At the moment I’ve taken the listbox off the pagepanel and just let it be another control in the window, and while that avoids the repainting hassle, it introduces the need for a lot of extra code to manage what the pagepanel was doing.
Any OS, really, although it’s best on macOS; using 2023r4 just now. Symptoms are that the splitter bar tends to move much more smoothly if I take the listbox off the pagepanel. Yesterday I tried having the paint event just return (i.e. do nothing) 90% of the time. But it seems that, internally, the cell is cleared before the Paint event is called, so that ended up looking very bad, although it did show that the Paint event gets called continuously.
I need to look and check if your fifth question may hold a clue.
On Windows there is a setting for whether a window is repainted during a resize event. (‘Live’)
I wonder if that is affecting a pagepanel - treating it like a full on window?
The windows listbox is a terrible flicker merchant.
Over the years, Ive tried
replacing the listbox with a picture ‘taken’ of the listbox while such things are happening,
keeping pictures of what the cell looked like last time it was actively drawn, and just painting the static picture
turning off the scrollbars
More recently, I combined some cells that had custom drawing - where I might have had 3 columns each with a drawing thing, now I have 1 cell that shows all 3 things.
It made quite a difference to speed, since it reduced the paint calls by 2 * rowcount during every refresh.
I’m using that one, too, all over my software. But I have never seen it run other than smooth. And I have really complicated windows with lots of containers.
I’m not at my desk just now so can’t check things until I get home, later.
I need to check that I’ve not inadvertently got anything that might refresh a listbox, buried in there. I’m also restructuring the pagepanel so that each panel has just the one DesktopContainer on it, and nothing else.
Moving the bottom splitter was causing the panel to be resized. The listbox is on the panel, and is being repainted even though its visible size does not, in fact, change. On macOS that is slightly jerky but not too bad. It’s in Win/Lin (each in a VM) that I have issues with smoothness. I’m running Sonoma 14.4.1 in a 2018 Mini.
The problem is the fundamental design of the Xojo Listbox, which was great for the 1990s, but things have advanced since then.
Each cell is drawn directly to the List’s view buffer, so when the view is resized or a refresh on the view is called, every single visible cell must be redrawn.
In other development tools, their list views actually contain sub views for the cells and are typically fixed type views “text”, “Image” etc. These allow for view caching per cell element, which reduces the draw time of the list control and improves smoothness. This also allows for lazy view rendering and element recycling.
One way I worked around this back in the day was to use an array of labels atop a canvas inside a NSScrollView.
Sam’s approach definitely works, and can actually simplify things greatly. The Listbox offers lots of functionality, but sometimes you only need a subset of that for your applications.
We used Sam’s approach for a Xojo Web 1 application, where we needed a “pseudo” Listbox that contained a label and a checkbox on each Row. This was primarily needed to facilitate touch interfaces. Rather than using a Listbox, we constructed some simple nested container controls and populated a canvas. Then we added a very limited number of Event Definitions to the Containers.
While we were developing a Web Application, a similar approach should work on the Desktop as well.
Be mindful that this approach is geared around dynamically instantiating containers and assigning Event Handlers on the fly. There is a bit of a learning curve for that, but it is well worth it.
Can you post what you changed in IMsplitter so it works with Desktop Containers and controls? I’m currently converting a project to API2 that has three imSplitters.
Looks like I changed AddControl/NoResize, RemoveControl, and all the AdjustControl methods. I’ve copied the class into an empty project, saved as xojo_project, zipped it, and put it here:
I forgot to mention that, during my transition from API1 to API2 controls, I had the code from both the original IMSplitter, and my mods, in all those methods I mentioned. That meant that everything continued to work during the transition. I took out the original API1 code at the end.
I found I could not make a good (small) example for this. But it has caused me to re-examine what I am doing in the PaintCellText event handler. I suspect I could move some code out of there.