Wxpython Sizer 位置

1 投票
2 回答
71 浏览
提问于 2025-04-14 17:29

我有一个示例应用程序,里面有几个简单的布局,但不知道为什么它们垂直居中显示,这不是我想要的(见附件)。我希望wxchoice布局能固定在窗口的顶部,而不是在中间,即使我调整窗口大小,它也应该保持在那个位置,但我就是找不到解决办法。

在这里输入图片描述

import wx

class Mywin(wx.Frame):
    def __init__(self, parent, id, title):

        super(Mywin, self).__init__(parent, title=title)
        self.panel = wx.Panel(self)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        nm = wx.StaticBox(self.panel, -1, 'Drop List:')
        nmSizer = wx.StaticBoxSizer(nm, wx.VERTICAL)

        self.workflowList = ["choice 1", "choice 2"]
        nmbox = wx.BoxSizer(wx.HORIZONTAL)
        self.workflowChoice = wx.Choice(self.panel, choices=self.workflowList)

        self.vbox.Add(nmSizer, 0, wx.ALL | wx.EXPAND, 0)
        nmbox.Add(self.workflowChoice, 0, wx.ALL, 5)
        nmSizer.Add(nmbox, 0, wx.ALL, 5)

        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.buttonGo = wx.Button(self.panel, -1, "Go")

        self.buttonClose = wx.Button(self.panel, -1, "Quit")

        self.btnSizer.Add(self.buttonGo, 0, wx.ALL, 5)
        self.btnSizer.Add(self.buttonClose, 0, wx.ALL, 5)

        self.vbox.Add(nmSizer, 0, wx.ALL | wx.CENTER | wx.TOP, 5)
        self.vbox.Add(self.btnSizer, 0, wx.ALL | wx.CENTER, 5)

        self.panel.SetSizer(self.vbox)

        self.panel.Fit()
        self.Show()

app = wx.App()
Mywin(None, -1, 'Test App ')
app.MainLoop()

2 个回答

0

首先,你的程序中的下拉列表位置奇怪地在切换。这是因为你把 nmSizer 添加了两次到 self.vbox。我把第一次的“添加”注释掉了,奇怪的行为就消失了。

接下来,关于如何让项目保持在窗口顶部的问题:

wxPython 使用 布局管理器的比例属性 来实现这个功能。

比例值高的布局管理器会把比例值低的布局管理器推到一边,具体推到上、下、左、右,取决于它们被添加到的布局管理器类型。

在你的代码中,我给 self.vbox 里的布局管理器设置了比例值为 1。

self.vbox.Add(nmSizer, 1, wx.ALL | wx.CENTER | wx.TOP, 5)  # proportion 1
self.vbox.Add(self.btnSizer, 1, wx.ALL | wx.CENTER, 5)  # proportion 1

接下来,我在 self.vbox 中添加了一个叫做 间隔器 的东西,并给它设置了比例值为 10。

self.vbox.Add( ( 0, 0), 10, wx.EXPAND, 5 )  # proportion 10

这个间隔器的比例值 10 会把其他的布局管理器推到顶部。间隔器本身是看不见的,它只是“推”其他的布局管理器到顶部。

调整后的代码:

import wx

class Mywin(wx.Frame):
    def __init__(self, parent, id, title):

        super(Mywin, self).__init__(parent, title=title)
        self.panel = wx.Panel(self)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        nm = wx.StaticBox(self.panel, -1, 'Drop List:')
        nmSizer = wx.StaticBoxSizer(nm, wx.VERTICAL)

        self.workflowList = ["choice 1", "choice 2"]
        nmbox = wx.BoxSizer(wx.HORIZONTAL)
        self.workflowChoice = wx.Choice(self.panel, choices=self.workflowList)

        # ADD nmSizer 1st time commented this out
        # self.vbox.Add(nmSizer, 0, wx.ALL | wx.EXPAND, 0)
        nmbox.Add(self.workflowChoice, 0, wx.ALL, 5)
        nmSizer.Add(nmbox, 1, wx.ALL, 5)  # proportion 1

        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.buttonGo = wx.Button(self.panel, -1, "Go")

        self.buttonClose = wx.Button(self.panel, -1, "Quit")

        self.btnSizer.Add(self.buttonGo, 0, wx.ALL, 5)
        self.btnSizer.Add(self.buttonClose, 0, wx.ALL, 5)

        # ADD nmSizer 2nd time, KEPT THIS ONE
        self.vbox.Add(nmSizer, 1, wx.ALL | wx.CENTER | wx.TOP, 5)  # proportion 1
        self.vbox.Add(self.btnSizer, 1, wx.ALL | wx.CENTER, 5)  # proportion 1
        # add spacer
        self.vbox.Add( ( 0, 0), 10, wx.EXPAND, 5 )  # proportion 10

        self.panel.SetSizer(self.vbox)

        self.panel.Fit()
        self.Show()

app = wx.App()
Mywin(None, -1, 'Test App ')
app.MainLoop()

使用间隔器来保持物体在顶部。

在这里输入图片描述

其他的 wx 对象也可以用作“推器/填充器”。如果你想把面板的剩余部分用作一个文本框,那么给创建的文本框一个高的比例值。

import wx

class Mywin(wx.Frame):
    def __init__(self, parent, id, title):

        super(Mywin, self).__init__(parent, title=title)
        self.panel = wx.Panel(self)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        nm = wx.StaticBox(self.panel, -1, 'Drop List:')
        nmSizer = wx.StaticBoxSizer(nm, wx.VERTICAL)

        self.workflowList = ["choice 1", "choice 2"]
        nmbox = wx.BoxSizer(wx.HORIZONTAL)
        self.workflowChoice = wx.Choice(self.panel, choices=self.workflowList)

        # ADD nmSizer 1st time commented this out
        # self.vbox.Add(nmSizer, 0, wx.ALL | wx.EXPAND, 0)
        nmbox.Add(self.workflowChoice, 0, wx.ALL, 5)
        nmSizer.Add(nmbox, 1, wx.ALL, 5)  # proportion 1

        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.buttonGo = wx.Button(self.panel, -1, "Go")

        self.buttonClose = wx.Button(self.panel, -1, "Quit")

        self.btnSizer.Add(self.buttonGo, 0, wx.ALL, 5)
        self.btnSizer.Add(self.buttonClose, 0, wx.ALL, 5)

        # ADD nmSizer 2nd time, KEPT THISS ONE
        self.vbox.Add(nmSizer, 1, wx.ALL | wx.CENTER | wx.TOP, 5)  # proportion 1
        self.vbox.Add(self.btnSizer, 1, wx.ALL | wx.CENTER, 5)  # proportion 1

        # add spacer not needed, the following textctrl is used for this
        # self.vbox.Add( ( 0, 0), 10, wx.EXPAND, 5 )  # proportion 10

        # add text ctrl
        self.textctrl_info = wx.TextCtrl(self.panel, wx.ID_ANY,
                                         wx.EmptyString, wx.DefaultPosition,
                                         wx.DefaultSize, wx.TE_MULTILINE)
        self.vbox.Add(self.textctrl_info, 25, wx.ALL | wx.EXPAND, 5)  # proportion 25

        self.panel.SetSizer(self.vbox)

        self.panel.Fit()
        self.Show()


app = wx.App()
Mywin(None, -1, 'Test App ')
app.MainLoop()

使用文本框来保持物体在顶部。

在这里输入图片描述

想把推器填充器放在按钮上面吗?只需改变添加到 self.vbox 的顺序即可。

    # ADD nmSizer 2nd time, KEPT THISS ONE
    self.vbox.Add(nmSizer, 1, wx.ALL | wx.CENTER | wx.TOP, 5)  # proportion 1

    # add text ctrl
    self.textctrl_info = wx.TextCtrl(self.panel, wx.ID_ANY,
                                     wx.EmptyString, wx.DefaultPosition,
                                     wx.DefaultSize, wx.TE_MULTILINE)
    self.vbox.Add(self.textctrl_info, 25, wx.ALL | wx.EXPAND, 5)  # proportion 25

    self.vbox.Add(self.btnSizer, 1, wx.ALL | wx.CENTER, 5)  # proportion 1

在这里输入图片描述

0

你正在把一个静态框(StaticBox)添加到一个静态框布局(StaticBoxSizer)中,所以可能会出现一些问题。

可以试试下面这样的做法:

import wx

class Mywin(wx.Frame):
    def __init__(self, parent, id, title):

        super(Mywin, self).__init__(parent, id=id, title=title)
        self.panel = wx.Panel(self)

        self.vbox = wx.BoxSizer(wx.VERTICAL)
        nm = wx.StaticBoxSizer(wx.VERTICAL, self.panel, 'Drop List:')

        self.workflowList = ["choice 1", "choice 2"]
        self.workflowChoice = wx.Choice(self.panel, choices=self.workflowList)
        nm.Add(self.workflowChoice, 0, wx.ALL|wx.EXPAND, 5)

        self.vbox.Add(nm, 0, wx.ALL, 5) # Add the box to the sizer

        self.btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.buttonGo = wx.Button(self.panel, -1, "Go")

        self.buttonClose = wx.Button(self.panel, -1, "Quit")

        self.btnSizer.Add(self.buttonGo, 0, wx.ALL, 5)
        self.btnSizer.Add(self.buttonClose, 0, wx.ALL, 5)

        self.vbox.Add(self.btnSizer, 0, wx.ALL|wx.EXPAND, 0)

        self.panel.SetSizer(self.vbox)

        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.buttonClose.Bind(wx.EVT_BUTTON, self.OnClose)
        self.Show()

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

app = wx.App()
Mywin(None, -1, 'Test App ')
app.MainLoop()

在这里输入图片描述

撰写回答