In my app, I want to handle allocation / deallocation of sizers inside a scrolledPanel. In my first try, I was hiding / showing the contents of the sizers, but this was causing a lot of problems. The hidden sizers would "stay there", effectively ocuppying space, it would not update propely, etc. The solution that worked better was to destroy and create them over and over again.
But this that its problems too. The scrolledPanel blinks while I'm updating it and seems to be resource heavy. In my real app, I put the references of the buttons and checkboxes in lists and it becames more dificult to handle them.
So, if anyone has a better solution, I'm all ears!
I'm up to a hiding / showing solution! Something to reset the size of the scrolledPanel to accomodate only the sizer it currently has it would be nice too.
Thanks!
import wx
import wx.lib.scrolledpanel as scrolled
class WaterDataBase(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for word in self.words:
self.addSizerToPanel(word)
def createSizer(self, word):
# Creates a sizer with a CheckBox and a StaticText to display.
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, word)
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
return sizer
def addSizerToPanel(self, word):
sizer = self.createSizer(word)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = []
# If query's empty, print all words
if not query or query.isspace():
for word in self.words:
result.append(word)
else:
for word in self.words:
if word.lower().find(query) != -1:
result.append(word)
# Destroy all panel sizers and put exactly the ones we want.
self.scrolled_panel.DestroyChildren()
for word in result:
self.addSizerToPanel(word)
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = WaterDataBase(None).Show()
app.MainLoop()
So, it seems I've made it, finally. I still wants the advice about reseting the size of the scrolledPanel. xD
import wx
import wx.lib.scrolledpanel as scrolled
class Frame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.sizerRefs = []
self.words = []
self.setupSizers()
self.setupData()
def setupSizers(self):
masterSizer = wx.BoxSizer(wx.HORIZONTAL)
itemsSizer = wx.BoxSizer(wx.VERTICAL)
itemsSizer.Add(self.addSearchControl(), flag=wx.ALL, border=7)
self.scrolledPanelSizer = wx.BoxSizer(wx.VERTICAL)
self.scrolled_panel = scrolled.ScrolledPanel(self, wx.ID_ANY, size=(200, 200))
self.scrolled_panel.SetSizer(self.scrolledPanelSizer)
itemsSizer.Add(self.scrolled_panel, flag=wx.ALL, border=7)
masterSizer.Add(itemsSizer)
self.scrolled_panel.SetupScrolling()
self.SetSizer(masterSizer)
def addSearchControl(self):
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.searchField = wx.TextCtrl(self, -1)
self.searchField.Bind(wx.EVT_TEXT, self.OnSearched)
sizer.Add(self.searchField)
return sizer
def setupData(self):
self.words = "I'm trying to make this work, please. Let's keep it on! The day is beautiful today. Together we are stronger!".split()
for i in range(0, len(self.words)):
self.addSizerToPanel(i)
def createSizer(self, index):
sizer = wx.BoxSizer(wx.HORIZONTAL)
checkBox = wx.CheckBox(self.scrolled_panel, -1)
text = wx.StaticText(self.scrolled_panel, -1, self.words[index])
sizer.Add(checkBox, flag=wx.ALL, border=5)
sizer.Add(text, flag=wx.LEFT, border=5)
self.sizerRefs.append(sizer)
return sizer
def addSizerToPanel(self, index):
sizer = self.createSizer(index)
self.scrolledPanelSizer.Add(sizer, flag=wx.ALL, border=5)
def hideAllSizers(self):
for sizer in self.sizerRefs:
sizer.ShowItems(False)
def unhideSizer(self, index):
self.sizerRefs[index].ShowItems(True)
def OnSearched(self, event):
query = self.searchField.GetValue().lower()
result = [] # Storing the indexes of the words found
# If query's empty, print all words
if not query or query.isspace():
for i in range(0, len(self.words)):
result.append(i)
else:
for i in range(0, len(self.words)):
if self.words[i].lower().find(query) != -1:
result.append(i)
# Hides all panel sizers and unhide exactly the ones we want.
self.hideAllSizers()
for i in range(0, len(result)):
self.unhideSizer(result[i])
self.scrolled_panel.Layout()
self.scrolled_panel.Scroll(0, 0) # Using this to cause the scrollPanel get back to the top.
app = wx.App()
frame = Frame(None).Show()
app.MainLoop()