Skip to main content
 首页 » 编程设计

python之wxpython Gridsizer 不适合面板

2025年05月04日6lvdongjie

我正在研究 wxpython GUI。我有三个面板(两个在左侧水平分开,一个在右侧与其他两个垂直分开——想想左半边有两个正方形,右半边有高矩形)。我正在尝试在面板 3(图像中的 P3)中安装 Gridsizer。我似乎无法让网格面板“填充”整个面板 3。相反,它们会吸附到顶部和底部。理想情况下,我希望 10 个小面板(2 行,5 列)调整大小并很好地填充面板 3(所有大小相同且大到足以看到每个面板)。我究竟做错了什么?谢谢!

**** 编辑 **** 我已将代码更改为如下所示:

        sizer_31 = wx.BoxSizer(wx.VERTICAL) 
        gs = wx.GridSizer(0,4,7,7) 
 
        for i in self.Panel_Others.keys(): 
            gs.Add(self.Panel_Others[i],0,wx.ALIGN_CENTER|wx.ALL,5) 
 
        sizer_31.Add(gs,0,wx.ALIGN_CENTER|wx.ALL,5) 
        self.OtherTeams.SetSizer(sizer_31) 
        sizer_31.SetSizeHints(self.OtherTeams) 

我的新面板 3 如下图所示。这是一些改进。但是,我希望各个面板(总共 10 个)展开相同的数量,以便整个笔记本页面都被相同大小的较小面板覆盖(想象一下日历的样子,每一天都是一个面板)。

**** 结束编辑 ****

下面是我的原代码:

注意:self.OtherTeams是self.Panel3下的wx.Notebook Page。 self.Panel_Others 是一个包含我正在显示的 wx.Panel 的字典(它会动态变化,所以这就是为什么我有一个它们的字典而不是指定它们的原因)。

        sizer_31 = wx.BoxSizer(wx.HORIZONTAL) 
        gs = wx.GridSizer(2,5,5,5) 
 
        for i in self.Panel_Others.keys(): 
            sizer_temp = wx.BoxSizer(wx.VERTICAL) 
            sizer_temp.Add(self.Panel_Others[i],1,wx.EXPAND) 
            gs.Add(sizer_temp,1,wx.EXPAND,0) 
 
        sizer_31.Add(gs,0,wx.EXPAND) 
        self.OtherTeams.SetSizer(sizer_31) 

请您参考如下方法:

在 wxPython 2.8 中,这将导致页面左上角出现单一模糊。 wxPython 2.9 在 sizer 方面更智能一些,这就是为什么它看起来有点工作的原因。

首先,您在 BoxSizer 中创建了一个 GridSizer,但不允许它动态扩展 (wx.EXPAND)。 其次,您将 sizer 设置为 wx.Notebook 而不是页面(面板),这会将整个布局向下移动并裁剪网格 sizer 中控件/面板的底行,或者在 2.8 中将被完全忽略,因此将所有内容移动到左上角。

这应该可以解决问题:

sizer_31 = wx.BoxSizer(wx.VERTICAL) # page (panel) sizer for outer border 
gs = wx.GridSizer(0,4,7,7) # content sizer 
 
for i in self.Panel_Others.keys(): 
    gs.Add(self.Panel_Others[i],0,wx.EXPAND|wx.ALL,5)  
    # + wx.EXPAND: allow the content to fill the 'cells' 
    #              (proportion is ignored here so it can be 0) 
sizer_31.Add(gs,1,wx.EXPAND|wx.ALL,5)  
# + 1, wx.EXPAND: allow the grid to expand to the main sizer 
#                 which in turn fits to the page 
self.Panel3.SetSizer(sizer_31) # set the sizer to page, not the notebook 

编辑:以下示例演示了如何动态更新 wx.Notebook 页面中 wx.GridSizer 的内容:

import wx 
 
class MyFrame(wx.Frame): 
    def __init__(self): 
        wx.Frame.__init__(self, None, title='wx.Notebook') 
        # create a wx.Notebook 
        book = wx.Notebook(self) 
        # create a new page; wx.Notebook owns the page 
        # therefore the notebook must be the parent window 
        page = MyPage(parent=book) 
        # add the page to the notebook: 
        book.AddPage(page, 'Page 1') 
        book.AddPage(MyPage(book),'Page 2') 
        book.AddPage(MyPage(book),'Page 3') 
 
class MyPage(wx.Panel): 
    "a page for wx.Notebook" 
    def __init__(self, parent): 
        # NOTE: wxPython 2.9.4/winXP may create graphic  
        # artifacts when more than one page is added. This can 
        # be avoided by creating the page with a size of (0,0). 
        # the reason for this is: the page (here a panel) is 
        # created with the default size and position (upper 
        # left corner). Once the layout is applied, the page 
        # is moved to the proper coordinates. However, the 
        # wx.Notebook is not redrawn so it will leave a black 
        # spot where the page was moved away from. Alternatively, 
        # the frame or notebook can be Refresh()ed after the 
        # frame is shown. 
        wx.Panel.__init__(self, parent, size=(0,0)) 
        # create sizer to add a border 
        pageSizer = wx.BoxSizer(wx.VERTICAL) 
        # create a grid sizer for the content 
        self.grid = wx.GridSizer(0, 4, 5, 5) 
        # add the grid sizer to the page sizer: 
        # to allow the grid to fill the entire page, 
        # set proportion>0 and add the wx.EXPAND flag. 
        # the border of 10 is the spacing between the 
        # page and the cells of the grid 
        pageSizer.Add(self.grid, 1, wx.EXPAND|wx.ALL, 10) 
        # set the main sizer: 
        self.SetSizer(pageSizer) 
        # add content to the grid 
        self.GenerateContent() 
        # DEMO: click any white space on the page to  
        # generate new content 
        self.Bind(wx.EVT_LEFT_DOWN, self.GenerateContent) 
 
    def GenerateContent(self, event=None): 
        "dynamically create page content" 
        # remove all items from the grid and destroy them 
        # NOTE: if you don't actually create new controls here, 
        # but use a list of controls created elsewhere (like in 
        # in your code), do not delete the items! Use: 
        # deleteWindows=False instead. 
        self.grid.Clear(deleteWindows=True) 
        # generate new grid content 
        for i in range(10): 
            # the contents are owned by the page, 
            # therefore the page must be the parent window: 
            # NOTE: size=(0,0) here is not required but 
            # eliminates a briefly shown graphic artifact 
            cell = wx.Panel(self, size=(0,0)) 
            cell.SetBackgroundColour(self.NewColor()) 
            # add the content (cells) to the grid: 
            # specify the wx.EXPAND flag to fit the 
            # content to the grid cell 
            self.grid.Add(cell, flag=wx.EXPAND) 
        # DEMO: hint text 
        self.grid.Add(wx.StaticText(self, label= 
            'Click empty cell to update content ->'), 
                      flag=wx.EXPAND) 
        # recalculate the layout to move the new contents 
        # of the grid sizer into place 
        self.Layout() 
 
    col = 0 # DEMO: coloring 
    def NewColor(self): 
        self.col = (self.col + 3) % 241 
        return wx.Colour(0, self.col * 10 % 255, self.col % 255) 
 
app = wx.App(False) 
MyFrame().Show() 
app.MainLoop()