首页 > 解决方案 > 在 wxPython 中使动态滚动面板更高效

问题描述

在我的应用程序中,我想在 scrolledPanel 中处理 sizer 的分配/解除分配。在我的第一次尝试中,我隐藏/显示了 sizer 的内容,但这导致了很多问题。隐藏的 sizer 会“呆在那里”,有效地占用空间,它不会正确更新,等等。效果更好的解决方案是一遍又一遍地破坏和创建它们。

但这也是它的问题。scrolledPanel 在我更新它时闪烁,似乎资源很重。在我的真实应用程序中,我将按钮和复选框的引用放在列表中,处理它们变得更加困难。

所以,如果有人有更好的解决方案,我会全力以赴!

我有一个隐藏/显示的解决方案!重置scrolledPanel的大小以仅容纳它当前拥有的大小的东西也会很好。

谢谢!

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()

所以,看来我终于成功了。我仍然想要关于重置滚动面板大小的建议。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()

标签: pythonwxpythonscrolledwindow

解决方案


推荐阅读