Reputation: 67
I'm trying to implement a ScrolledPanel with lazy loading, which means that only visible widgets are loaded and added to the panel. Objects are then loaded as scrolling occurs (but I'm not there yet).
What I'm having an issue with is set up the scroll bar to its real size, which is the one it would have if the objects were all in the panel.
Note that all the objects in this proof of concept have the same size. In the real use case, it will almost be the case, with some objects being a little less high (which is why I use the max_row_height
variable).
Here is my code. The height that should be applied to the vertical scrollbar is correctly computed, but I fail to apply it. I set up the panel's virtual size, which I thought was the right way, but it doesn't work.
import random
import wx
import wx.lib.scrolledpanel as scrolled
from wx.lib.buttons import GenButton
import math
########################################################################
class LazyLoadingScrolledPanel(scrolled.ScrolledPanel):
def __init__(self, parent):
scrolled.ScrolledPanel.__init__(self, parent, -1)
self.sizer = wx.WrapSizer()
wx.CallAfter(self.build, self)
# wx.CallAfter(self.build)
def build(self, evt):
text = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
margin = 5
client_size = self.GetClientSize()
panel_width = client_size.width
panel_height = client_size.height
x, y = margin, margin # Commencer avec une marge
row_height = 0
max_row_height = 0
buttons_per_row = 0
for index, letter in enumerate(text):
btn = GenButton(self, label=letter)
r, g, b = [random.randint(128, 255) for _ in range(3)]
btn.SetBackgroundColour(wx.Colour(r, g, b))
btn.Fit()
button_size = btn.GetSize()
total_button_width = button_size.width + 2 * margin
total_button_height = button_size.height + 2 * margin
if x + total_button_width > panel_width:
# Passer à la ligne suivante
x = margin
y += row_height
max_row_height = max(max_row_height, row_height)
row_height = 0
if buttons_per_row == 0:
buttons_per_row = index
if y > panel_height:
self.sizer.Detach(btn)
btn.Destroy()
break
self.sizer.Add(btn, 0, wx.ALL, margin)
x += total_button_width - margin
row_height = max(row_height, total_button_height)
total_rows = math.ceil(len(text) / buttons_per_row)
total_height = int(total_rows * max_row_height)
print(f"Total height for scrollbar: {total_height}")
self.SetVirtualSize(panel_width, total_height)
self.Layout()
self.SetSizer(self.sizer)
self.SetupScrolling()
self.SetScrollRate(0, 20)
########################################################################
class TestFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="WrapSizers in ScrolledPanel", size=(400,500))
panel = LazyLoadingScrolledPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = TestFrame()
app.MainLoop()
Upvotes: 0
Views: 40