首页 > 解决方案 > wxPython 分层布局似乎没有正确调整大小

问题描述

我无法弄清楚为什么我的分层布局没有像我在 wxPython 中所期望的那样做。

基本思路如下:

+- Win1 ------+ +- Win2 -----+ +- Win3 ----------+
|             | |            | |                 |
+-------------+ +------------+ +-----------------+
+- Win4 ----------+ +- Win5 ---------------------+
|                 | |                            |
+-----------------+ +----------------------------+
+- Win6 -----------------------------------------+
|                                                |
+------------------------------------------------+

我正在创建一个垂直框布局来处理三个区域{1/2/3, 4/5, 6}。在这些区域中的每一个内部都有另一个(水平)框布局来处理(例如在第一个区域中){1, 2, 3}子区域。

然后,在这些子区域中的每一个内,我都有一个静态 box sizer 给我一个多行、非用户可编辑的文本控件的边框。

现在,下面的代码已简化为两行,第一行两列,第二行一列。只有第一行中的第一列是绘制漂亮边框控件的尝试,其他只是静态文本控件。

import wx

class MyFrame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, pos=(150,50), size=(1720,930))
        self.Bind(wx.EVT_CLOSE, self.OnClose)

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

        self.screenPanel = wx.Panel(self.topPanel, wx.ID_ANY)
        self.spacer0 = wx.StaticText(self.topPanel, wx.ID_ANY, "")
        self.dummy1 = wx.StaticText(self.topPanel, wx.ID_ANY, "dummy1")
        self.dummy2 = wx.StaticText(self.topPanel, wx.ID_ANY, "dummy2")

        self.topSizer = wx.BoxSizer(wx.VERTICAL)
        self.row1Sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.row2Sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.screenSizer = wx.StaticBoxSizer(wx.HORIZONTAL,
            self.screenPanel, "Screen")

        self.screen = wx.TextCtrl(self.screenPanel, wx.ID_ANY,
            "This is the first line\nXYZZY\nPLUGH",
            wx.DefaultPosition, wx.DefaultSize,
            wx.TE_MULTILINE | wx.TE_READONLY)

        self.row1Sizer.Add(self.screenSizer, 0, wx.ALL, 5)
        self.row1Sizer.Add(self.spacer0, 1, wx.ALL, 5)
        self.row1Sizer.Add(self.dummy1, 0, wx.ALL, 5)

        self.row2Sizer.Add(self.dummy2, 0, wx.ALL, 5)

        self.topSizer.Add(self.row1Sizer, 0, wx.ALL | wx.EXPAND, 5)
        self.topSizer.Add(self.row2Sizer, 0, wx.ALL | wx.EXPAND, 5)

        self.screenPanel.SetSizer(self.screenSizer)
        self.topPanel.SetSizer(self.topSizer)
        self.topPanel.Layout()

    def OnClose(self, event):
        self.Destroy()

app = wx.App()
top = MyFrame("My")
top.Show()
app.MainLoop()

但是,似乎存在一些问题,我认为这可能是由于我对 sizers 或 non-sizer 是否应该拥有被控制的资源感到困惑,但我无法让它发挥作用。目前的代码给了我:

在此处输入图像描述

如您所见,第一个控件周围似乎缺少静态框,并且大小似乎搞砸了。我会认为大小将根据布局计算,以便它至少足够大以容纳内部控件和边框。

谁能让我知道我对这段代码做错了什么?

它也在退出时崩溃,这可能是相关的。如果没有,我可以将其作为一个单独的问题处理。

标签: python-3.xwindowslayoutwxpython

解决方案


静态框可以单独创建,也可以为方便起见,sizer 可以自己创建。在任何情况下,sizer 都拥有 wx.StaticBox 控件,并将在 wx.StaticBoxSizer 析构函数中将其删除。

请注意,从 wxWidgets 2.9.1 开始,鼓励您创建添加到 wx.StaticBoxSizer 作为 wx.StaticBox 子级的窗口

所以是这样的:

import wx

class MyFrame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, pos=(150,50), size=(500,400))
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.SetMinSize((500,400))
        self.topPanel = wx.Panel(self, wx.ID_ANY)

        box1 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win1")
        box1.SetForegroundColour('#000000')

        self.textCtrl1 = wx.TextCtrl(box1, wx.ID_ANY,
            "This is the first line\nXYZZY\nPLUGH",
            wx.DefaultPosition, size = (200,100), style = wx.TE_MULTILINE | wx.TE_READONLY)
        self.dummy4 = wx.StaticText(box1, wx.ID_ANY, "Text below textctrl 1")

        boxSizer1 = wx.StaticBoxSizer(box1, wx.VERTICAL)
        boxSizer1.Add(self.textCtrl1, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)
        boxSizer1.Add(self.dummy4, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        box2 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win2")
        box2.SetForegroundColour('#000000')

        self.spacer = wx.StaticText(box2, wx.ID_ANY, "A spacer")

        boxSizer2 = wx.StaticBoxSizer(box2, wx.VERTICAL)
        boxSizer2.Add(self.spacer, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        box3 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win3")
        box3.SetForegroundColour('#000000')

        self.dummy1 = wx.StaticText(box3, wx.ID_ANY, "dummy text 1")

        boxSizer3 = wx.StaticBoxSizer(box3, wx.VERTICAL)
        boxSizer3.Add(self.dummy1, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        box4 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win4")
        box4.SetForegroundColour('#000000')

        self.textCtrl2 = wx.TextCtrl(box4, wx.ID_ANY,
            "This is the second line\nXYZZY\nPLUGH",
            wx.DefaultPosition, size = (200,100), style = wx.TE_MULTILINE | wx.TE_READONLY)

        boxSizer4 = wx.StaticBoxSizer(box4, wx.VERTICAL)
        boxSizer4.Add(self.textCtrl2, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        box5 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win5")
        box5.SetForegroundColour('#000000')

        self.dummy2 = wx.StaticText(box5, wx.ID_ANY, "dummy text 2")

        boxSizer5 = wx.StaticBoxSizer(box5, wx.VERTICAL)
        boxSizer5.Add(self.dummy2, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        box6 = wx.StaticBox(self.topPanel, wx.ID_ANY, "Win6")
        box6.SetForegroundColour('#000000')

        self.dummy3 = wx.StaticText(box6, wx.ID_ANY, "dummy text 3")

        boxSizer6 = wx.StaticBoxSizer(box6, wx.VERTICAL)
        boxSizer6.Add(self.dummy3, proportion = 0, flag=wx.ALIGN_CENTER|wx.EXPAND)

        self.topSizer = wx.BoxSizer(wx.VERTICAL)
        self.row1Sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.row2Sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.row3Sizer = wx.BoxSizer(wx.HORIZONTAL)


        self.row1Sizer.Add(boxSizer1, 0, wx.ALL, 5)
        self.row1Sizer.Add(boxSizer2, 1, wx.ALL|wx.EXPAND, 5) #Matches size of box1
        self.row1Sizer.Add(boxSizer3, 0, wx.ALL|wx.EXPAND, 5) #Matches size of box1

        self.row2Sizer.Add(boxSizer4, 0, wx.ALL, 5)
        self.row2Sizer.Add(boxSizer5, 1, wx.ALL, 5) # Does not match size of box4

        self.row3Sizer.Add(boxSizer6, 1, wx.ALL, 5)

        self.topSizer.Add(self.row1Sizer, 0, wx.ALL | wx.EXPAND, 5)
        self.topSizer.Add(self.row2Sizer, 0, wx.ALL | wx.EXPAND, 5)
        self.topSizer.Add(self.row3Sizer, 0, wx.ALL | wx.EXPAND, 5)

        self.topPanel.SetSizer(self.topSizer)
        self.topPanel.Layout()

    def OnClose(self, event):
        self.Destroy()

app = wx.App()
top = MyFrame("My Window Layout")
top.Show()
app.MainLoop()

在此处输入图像描述

但是,请注意,有时您的操作系统桌面上的主题无法处理盒子,所以它不是给定的!
具体来说,Linux Mint 上的 Mint-X 惨遭失败,与主题 Mint-X 相同的代码看起来像这样。

在此处输入图像描述


推荐阅读