wxPython分层布局似乎无法正确调整大小

时间:2019-02-26 04:46:36

标签: python-3.x windows layout wxpython

我无法弄清楚为什么为什么我的层次布局不像我在wxPython中所期望的那样。

基本思想如下:

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

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

然后,在每个子区域中,我都有一个静态框大小调整器,以便为我提供多行,用户不可编辑的文本控件边框。

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

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

但是,我似乎不太理解某些问题,这可能是由于我对大小调整器或非大小调整器应拥有受控资源的困惑,但我无法使其正常运行。现在的代码给了我:

enter image description here

如您所见,第一个控件周围似乎缺少静态框,并且大小调整看起来很混乱。我本来以为会在布局上计算尺寸,以使其至少足够容纳内部控件和边框。

有人可以让我知道我在用这段代码做错什么吗?

  

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

2 个答案:

答案 0 :(得分:1)

  

为方便起见,静态框可以独立创建,也可以由大小调整器自己创建。无论如何,sizer都拥有wx.StaticBox控件,并将在wx.StaticBoxSizer析构函数中将其删除。

     

请注意,自wxWidgets 2.9.1起,我们鼓励您创建作为wx.StaticBox的子级添加到wx.StaticBoxSizer的窗口

是这样的:

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

enter image description here

但是,请注意,有时您的OS桌面上的主题无法适应方框,因此这不是给定的!
具体来说,Linux Mint上的Mint-X惨遭失败,主题为Mint-X的相同代码看起来像这样。

enter image description here

答案 1 :(得分:0)

您的原始代码将进行一些修改。
我仍然无法通过将screenPanel添加到screenSizer来解决row1Sizer的问题,除了screen从未添加到sizer且未扩展。
您修改后的代码(已注明修改内容):

import wx

class MyFrame(wx.Frame):
    def __init__(self, title):
        wx.Frame.__init__(self, None, title=title, pos=(150,50), size=(420,230))
        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.screenSizer = wx.StaticBoxSizer(wx.HORIZONTAL,
            self.topPanel, "Screen")

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

        ##Additional line
        self.screenSizer.Add(self.screen, 0, wx.ALL|wx.EXPAND, 5)
        ##
        self.row1Sizer.Add(self.screenSizer, 0, wx.ALL|wx.EXPAND, 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()

结果: enter image description here