首页 > 解决方案 > wxWidgets/wxPython - 滚动一个使用 GridSizer 调整大小的文本的窗口后,应用程序冻结

问题描述

所以基本上我做了一个非常简单的 wxPython 应用程序,它结合了 ScrolledWindow 和 Gridsizers。它有你的平均框架、一个面板和一个 ScrolledWindow。在这个 ScrollWindow 中,我设法在 GridSizers 的帮助下添加了很多表格。布局很好,调整大小也很好,虽然有点慢,但这是意料之中的。当我滚动得很慢时,一切仍然有效。但是当我快速滚动时,它确实会对滚动做出反应,甚至是连续滚动并很好地加载所有元素。但是,当我滚动到很多并将鼠标移出滚动窗口并且我想调整面板大小或移动面板时,应用程序本身和所有其他应用程序都会冻结!

所以我进一步压缩了代码,不为我的主应用程序构建我想要的表,而只是用 1000 个静态文本字符串填充网格。问题仍然存在。即使我用 C++ 编写相同的代码片段并使用 Visual Studio 构建它,问题变得更糟,尽管它被编译了!加载程序花费了 1 分 30 秒,同时也冻结了所有其他程序。我确实设法加载了任务管理器,并注意到它只使用了 7 MB RAM 和微不足道的处理能力,尽管它冻结了。我觉得这与事件有关:滚动的次数越多,将越多的“东西”放入某个队列中,当我将鼠标移出窗口时,该队列就会执行。

这是代码。首先它会创建你的 wx.Frame,然后是面板。滚动的窗口以面板为父级,垂直滚动率设置为 20。虚拟大小未指定,但当它适合大小调整器时将重新计算。然后制作一个 10x100 的 gridsizer,并用包含“test”的静态文本填充。然后将该网格设置为 ScrolledWindows 的面板,因此文本在滚动窗口中很好地显示。最后,将滚动窗口添加到主大小调整器以适应整个应用程序。

import wx

class MyForm(wx.Frame):

    def __init__(self):

        wx.Frame.__init__(self, None, wx.ID_ANY, title='Test.py')

        panel = wx.Panel(self, wx.ID_ANY)

        cols = 10
        rows = 100

        scrollWin = wx.ScrolledWindow(panel, wx.ID_ANY, size=(400, 400))
        scrollWin.SetScrollbars(0, 20, 0, 0)

        grid = wx.GridSizer(rows, cols, (5,5))

        texts = [wx.StaticText(scrollWin, wx.ID_STATIC, 'Test') for i in range(rows*cols)]
        for text in texts:
            grid.Add(text, 1, wx.ALL|wx.EXPAND, 5)

        scrollWin.SetSizer(grid)
        grid.Fit(scrollWin)

        topSizer = wx.BoxSizer(wx.VERTICAL)
        topSizer.Add(scrollWin, 1, wx.ALL|wx.EXPAND, 5)

        panel.SetSizer(topSizer)
        topSizer.Fit(self)
        topSizer.SetSizeHints(self)

        self.Show()

app = wx.App()
frame = MyForm()
app.MainLoop()

我希望瓶颈的最后一件事是滚动程序的窗口,但更多的是调整应用程序的大小。

同样,我仍然可以滚动一点,即使是疯狂的,但是当我将鼠标移出窗口时,它会冻结。我相信这与调整网格的大小没有太大关系,而是与一些需要赶上的未知背景事件处理有关。感谢您的宝贵时间,任何帮助将不胜感激。

标签: wxpythonscrollbarwxwidgets

解决方案


我不知道在您的情况下减速的确切原因是什么,这不起作用似乎很奇怪。但是,无论如何,您不应该首先尝试这样做。在 MSW 下,每个进程限制为 10000 个窗口,每个系统限制为 32700 个窗口。消耗其中的 1000 个并不是一个好主意。

您应该改用wxGrid它,它不会为每个单元格创建一个窗口——这太昂贵了。


推荐阅读