wxPython Panel in existing window: slow and small

怎甘沉沦 提交于 2020-01-25 12:32:10

问题


I'm experiencing very different behavior when creating a wx.Panel depending on whether the main window's already called Show().

With the below code, the application opens quickly with MainPanel created & populated before MainFrame.Show(). Using "New" to re-create it has multi-second lag while it re-makes the 200 texts. Also the MainPanel doesn't expand to take up the whole size of the window until the window is resized.

This is definitely an issue with panel creation rather than panel destruction; if I remove the MainPanel creation in MainFrame's init, then the New action has the same speed & size issues.

Two questions:

Is there anything I can do to speed up panel creation after MainFrame.Show()?

What needs to be done when creating MainPanel after MainFrame.Show()ed to have the MainPanel expand to the size of its parent?

#!/usr/bin/python
# -*- coding: utf-8 -*-

import wx
import wx.lib.scrolledpanel

class MainPanel(wx.lib.scrolledpanel.ScrolledPanel):
    def __init__(self,parent):
        wx.lib.scrolledpanel.ScrolledPanel.__init__(self, parent=parent)
        self.SetupScrolling()
        sizer = wx.BoxSizer(wx.VERTICAL)
        for i in range(1,200):
            sizer.Add(wx.StaticText(self, wx.ID_ANY, "I'm static text"))
        self.SetSizer(sizer)
        self.SetAutoLayout(True)

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="FrameTest", size=(600,800))
        self.InitMenu()
        self.panel = None
        self.panel = MainPanel(self)

    def InitMenu(self):
        self.menuBar = wx.MenuBar()
        menuFile = wx.Menu()
        menuFile.Append(wx.ID_NEW, "&New")
        self.Bind(wx.EVT_MENU, self.OnNew, id=wx.ID_NEW)
        self.menuBar.Append(menuFile, "&File")
        self.SetMenuBar(self.menuBar)

    def OnNew(self, evt):
        if self.panel:
            self.panel.Destroy()
        self.panel = MainPanel(self)

if __name__ == "__main__":
    app = wx.App(0)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

UPDATE: joaquin's SendSizeEvent() definitely solves the first problem. For the second, I've found that hiding containers works out well. I'm guessing that after the window's been shown, it's trying to unnecessarily re-(display/layout/something) after every new widget and that's slowing it down. If I add Hide & Show to the panel's init, then there's no more lag and it works in both situations.

class MainPanel(wx.lib.scrolledpanel.ScrolledPanel):
    def __init__(self,parent):
        wx.lib.scrolledpanel.ScrolledPanel.__init__(self, parent=parent)
        self.SetupScrolling()
        self.Hide()
        sizer = wx.BoxSizer(wx.VERTICAL)
        for i in range(1,200):
            sizer.Add(wx.StaticText(self, wx.ID_ANY, "I'm static text"))
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        self.Show()

回答1:


The panel will get the correct size if the Frame feels a SizeEvent. So this works for your second question:

def OnNew(self, evt):
    if self.panel:
        self.panel.Destroy()
    self.panel = MainPanel(self)
    self.SendSizeEvent()

Control of windows and widgets becomes easier by using sizers. With sizers in your main frame you can use the sizer Layout method to fit widgets in place.

Could not find a way of speeding up panel rewrite. But you can diminish the bizarre visual effect by not deleting the panel but clearing the sizer instead (you dont need SendSizeEvent() for this case):

class MainPanel(wx.lib.scrolledpanel.ScrolledPanel):
    def __init__(self,parent):
        wx.lib.scrolledpanel.ScrolledPanel.__init__(self, parent=parent)
        self.SetupScrolling()
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.fill()
        self.SetSizer(self.sizer)

    def fill(self):
        tup = [wx.StaticText(self, wx.ID_ANY, "I'm static text") for i in range(200)]
        self.sizer.AddMany(tup)
        self.Layout()

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="FrameTest", size=(600,800))
        self.InitMenu()
        self.panel = None
        self.panel = MainPanel(self)

    def InitMenu(self):
        self.menuBar = wx.MenuBar()
        menuFile = wx.Menu()
        menuFile.Append(wx.ID_NEW, "&New")
        self.Bind(wx.EVT_MENU, self.OnNew, id=wx.ID_NEW)
        self.menuBar.Append(menuFile, "&File")
        self.SetMenuBar(self.menuBar)

    def OnNew(self, evt):
        if self.panel:
            self.panel.sizer.Clear()
        self.panel.fill()


来源:https://stackoverflow.com/questions/8675017/wxpython-panel-in-existing-window-slow-and-small

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!