wx python BoxSizer 未扩展到 window 加上 GUI 顶部的奇怪空白间隙
wx python BoxSizer not expanding to window plus an odd blank gap at top of GUI
我在正确扩展我的 sizer 时遇到了一些问题。我添加了两个子面板,我希望它们能解决我的问题,但它似乎让事情变得更糟。我希望做的是 top_panel
扩展到主要 panel
宽度的范围。 vbox_top_right
应该扩展以填充 hbox_top
的其余部分。然后 bottom_panel
应该水平和垂直扩展以填充主要 panel
的 space 的其余部分。 None 正在发生。
将所有内容拆分为两个子面板后,我现在遇到了一个问题,即顶部有一个大空白 space。另外,我的 bottom_panel
似乎没有任何扩展。我也不确定我是否正确使用 SetSizerAndFit
因为我没有看到任何地方提到在多个面板上使用它。我应该只将它应用到主要 panel
吗?
请注意,我强制使用 wx 3.0。我安装了 2.8 和 3.0,但 2.8 的 wx.StaticBoxSizer 有问题。我知道这可能与我的问题无关,只是如果您在 2.8 中尝试,代码将无法正常工作。
代码:
import wxversion
wxversion.select('3.0')
import wx
import os
import sys
VERSION = '1.0.0'
class GUI(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=title, pos=wx.DefaultPosition,
size=wx.Size(1280, 768), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
menu_bar = wx.MenuBar()
file_menu = wx.Menu()
self.cwd = os.getcwd()
# Quit code
file_item = file_menu.Append(wx.ID_EXIT, 'Quit', 'Quit Application')
menu_bar.Append(file_menu, '&File')
self.SetMenuBar(menu_bar)
# Add Main panel
self.panel = wx.Panel(self)
# Add Top and Bottom Panels
self.top_panel = wx.Panel(self.panel)
self.bottom_panel = wx.Panel(self.panel)
# Create horizontal and vertical boxes
self.hbox_main = wx.BoxSizer(wx.HORIZONTAL)
self.vbox_main = wx.BoxSizer(wx.VERTICAL)
self.hbox_top = wx.BoxSizer(wx.HORIZONTAL)
self.vbox_top_left = wx.BoxSizer(wx.VERTICAL)
self.vbox_top_right = wx.BoxSizer(wx.VERTICAL)
####################################################
# TOP
####################################################
##########################
# TOP LEFT
##########################
# List box text
self.lbl_filter = wx.StaticText(self.top_panel, wx.ID_ANY,
u"Select all cases to apply file to",
wx.DefaultPosition, wx.DefaultSize, 0)
self.lbl_filter.Wrap(-1)
self.vbox_top_left.Add(self.lbl_filter, 0, wx.EXPAND)
# The list box that all the file names are in
self.list_box = wx.CheckListBox(self.top_panel, id=wx.ID_ANY, pos=wx.DefaultPosition, size=(300, 300),
choices=[], style=wx.LB_HSCROLL|wx.LB_MULTIPLE|wx.LB_NEEDED_SB|wx.LB_SORT)
self.vbox_top_left.Add(self.list_box, 0, wx.EXPAND, 5)
# List box filter text
self.lbl_filter = wx.StaticText(self.top_panel, wx.ID_ANY,
u"Case filter (separate wildcards with a comma and choose filter logic (AND or OR)\n(i.e. HS, 2022 with AND selected will modify all 2022 HS cases)",
wx.DefaultPosition, wx.DefaultSize, 0)
self.lbl_filter.Wrap(-1)
self.vbox_top_left.Add(self.lbl_filter, 0, wx.EXPAND)
# List box filter
self.hbox_filter = wx.BoxSizer(wx.HORIZONTAL)
self.txt_filter = wx.TextCtrl(self.top_panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
self.txt_filter.SetMinSize(wx.Size(300, -1))
self.hbox_filter.Add(self.txt_filter, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5)
# List box radio buttons
logic_choices = [u"AND", u"OR"]
self.rdo_logic = wx.RadioBox(self.top_panel, wx.ID_ANY, u"Filter Logic", wx.DefaultPosition, wx.DefaultSize,
logic_choices, 1, wx.RA_SPECIFY_ROWS)
self.rdo_logic.SetSelection(0)
self.hbox_filter.Add(self.rdo_logic, 0, wx.EXPAND, 5)
# Add filter stuff to vbox_top
self.vbox_top_left.Add(self.hbox_filter, 0, wx.EXPAND)
# Add top components to hbox
self.hbox_top.Add(self.vbox_top_left, 0, wx.EXPAND)
##########################
# TOP RIGHT
##########################
# Add warning text
self.lbl_warning = wx.StaticText(self.top_panel, wx.ID_ANY,
u"*** WARNING *** HELLO WORLD ",
wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTER_HORIZONTAL)
self.lbl_warning.Wrap(-1)
self.vbox_top_right.Add(self.lbl_warning, 0, wx.EXPAND, 5)
# Radio buttons for software choice
rdo_choices = [u"App 1", u"App 2", u"App 3"]
self.rdo_software = wx.RadioBox(self.top_panel, wx.ID_ANY, u"Select Software", wx.DefaultPosition,
wx.DefaultSize, rdo_choices, 1, wx.RA_SPECIFY_COLS)
self.rdo_software.SetSelection(0)
self.vbox_top_right.Add(self.rdo_software, 0, wx.EXPAND, 5)
# Checkbox for archive
self.cb_archive = wx.CheckBox(self.top_panel, wx.ID_ANY, u"Archive files before running", wx.DefaultPosition,
wx.DefaultSize, 0)
self.vbox_top_right.Add(self.cb_archive, 0, wx.EXPAND, 5)
# Checkbox for saving
self.cb_save = wx.CheckBox(self.top_panel, wx.ID_ANY, u"Save files after running", wx.DefaultPosition,
wx.DefaultSize, 0)
self.vbox_top_right.Add(self.cb_save, 0, wx.EXPAND, 5)
# Folder selection label
self.lbl_cases = wx.StaticText(self.top_panel, wx.ID_ANY, u"Select Folder With Cases", wx.DefaultPosition,
wx.DefaultSize, 0)
self.lbl_cases.Wrap(-1)
self.vbox_top_right.Add(self.lbl_cases, 0, wx.EXPAND, 5)
# Add Folder selection
self.hbox_folder = wx.BoxSizer(wx.HORIZONTAL)
self.txt_cases = wx.TextCtrl(self.top_panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
self.txt_cases.SetMinSize(wx.Size(400, -1))
self.hbox_folder.Add(self.txt_cases, 0, wx.EXPAND, 5)
# Folder select button
self.btn_cases = wx.Button(self.top_panel, wx.ID_ANY, u"Case Folder", wx.DefaultPosition, wx.DefaultSize, 0)
self.hbox_folder.Add(self.btn_cases, 0, wx.EXPAND, 5)
# Add to sizer
self.vbox_top_right.Add(self.hbox_folder, 1, wx.SHAPED, 5)
self.hbox_top.Add(self.vbox_top_right, 0, wx.EXPAND, 5)
self.vbox_main.Add(self.hbox_top, 0, wx.EXPAND)
####################################################
# BOTTOM
####################################################
self.bottom_box = wx.StaticBox(self.bottom_panel, label='Progress Output')
self.hbox_output = wx.StaticBoxSizer(self.bottom_box, wx.HORIZONTAL)
self.txt_output = wx.TextCtrl(self.bottom_box, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
wx.TE_MULTILINE | wx.TE_READONLY)
# Put it all together
self.vbox_main.Add(self.top_panel, 1, wx.EXPAND)
self.vbox_main.Add(self.bottom_panel, 1, wx.EXPAND)
self.top_panel.SetSizerAndFit(self.hbox_top)
self.bottom_panel.SetSizerAndFit(self.hbox_output)
self.panel.SetSizerAndFit(self.vbox_main)
self.Centre()
self.Layout()
if __name__ == '__main__':
app = wx.App(0)
MainFrame = GUI(None, title='Batch Apply %s' % VERSION)
app.SetTopWindow(MainFrame)
MainFrame.Show()
app.MainLoop()
这是 GUI 的粗略图
这是我得到的:
主机只有一个child叫panel
。因此,这个 只有 child 的框架(不是另一种 window 的框架)在调整大小时将适合它的 parent 的客户区.好的。如果超过一个 child.
就不是真的了
您还有两个面板,作为 panel
的 children。例如,如果您想要不同的背景颜色,这会很好。如果没有,那就没必要了,但是这些多余的面板没有任何问题。
有两个不同的区域:顶部(垂直方向不可调整大小)和底部(可调整大小)。这将需要处理 panel
内容布局的 'main sizer' 中的两个 sub-sizers。但是您正在为这些区域使用两个面板,所以最好让我们使用一个主要的 sizer(我将使用 vbox_main
)作为这两个面板 panel
内的布局。 sub-panel 的内容布局将由 sizer 处理。
在'top'地区也有两个不同的地区;所以另外两个 sub-sizers。你的设计是正确的。
vbox_top_left
希望它管理的控件(children of top_panel
)适合可用的 space。因为这是一个 vertical sizer,所以我们需要:
1) A child 可以改变垂直尺寸:使用 proportion=1
2) child 可以改变水平大小:使用 wx.EXPAND
标志。
3) 如果在某些控件之间添加垂直可调整大小的 spacers 会很好。
对vbox_top_right
的控制size-handled应用类似的标准(children of top_panel
)。
底部区域很特殊,因为您希望在标签和文本控件周围绘制一个矩形。为此,我们需要一个特殊的 sizer:StaticBoxSizer。它的特殊之处在于它处理的控件 children 不是面板的,而是底层 wx.StaticBox
的。有关示例和更多解释,请参阅上层文档 link。
self.hbox_output = wx.StaticBoxSizer(wx.HORIZONTAL, self.bottom_panel)
self.hbox_output.Add(wx.StaticText(self.hbox_output.GetStaticBox(), ....), ...)
self.hbox_output.Add(wx.TextCtrl(self.hbox_output.GetStaticBox(), ....), 1, wx.EXPAND, 5)
要将 children 添加到此 sizer,请遵循与 'top' 区域相同的标准。这里没有什么不同。
现在,sizer 的行为(我跳过你使用的其他 sub-sizers):
# No vertical nor horizontal expanding
# self.hbox_top.Add(self.vbox_top_left, 0, wx.EXPAND) <<== not what expected
self.hbox_top.Add(self.vbox_top_left, 0)
# Only horizontal expanding
# self.hbox_top.Add(self.vbox_top_right, 0, wx.EXPAND, 5) <<== not what expected
self.hbox_top.Add(self.vbox_top_right, 1, 0, 5)
最后的工作是绑定面板和sizer:
self.top_panel.SetSizer(self.hbox_top)
self.bottom_panel.SetSizer(self.hbox_output)
# Top panel expands only in horizontal
self.vbox_main.Add(self.top_panel, 0, wx.EXPAND)
# Bottom part expands in both directions
self.vbox_main.Add(self.bottom_panel, 1, wx.EXPAND)
self.panel.SetSizerAndFit(self.vbox_main)
self.Centre()
self.Layout()
使用单个面板更容易。我使用了你的两个 sub-panels 只是为了演示它是如何工作的:主 sizer 处理 sub-panels,每个面板为其处理 children.[=26= 的 sizer 使用一个 sizer ]
我在正确扩展我的 sizer 时遇到了一些问题。我添加了两个子面板,我希望它们能解决我的问题,但它似乎让事情变得更糟。我希望做的是 top_panel
扩展到主要 panel
宽度的范围。 vbox_top_right
应该扩展以填充 hbox_top
的其余部分。然后 bottom_panel
应该水平和垂直扩展以填充主要 panel
的 space 的其余部分。 None 正在发生。
将所有内容拆分为两个子面板后,我现在遇到了一个问题,即顶部有一个大空白 space。另外,我的 bottom_panel
似乎没有任何扩展。我也不确定我是否正确使用 SetSizerAndFit
因为我没有看到任何地方提到在多个面板上使用它。我应该只将它应用到主要 panel
吗?
请注意,我强制使用 wx 3.0。我安装了 2.8 和 3.0,但 2.8 的 wx.StaticBoxSizer 有问题。我知道这可能与我的问题无关,只是如果您在 2.8 中尝试,代码将无法正常工作。
代码:
import wxversion
wxversion.select('3.0')
import wx
import os
import sys
VERSION = '1.0.0'
class GUI(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=title, pos=wx.DefaultPosition,
size=wx.Size(1280, 768), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
menu_bar = wx.MenuBar()
file_menu = wx.Menu()
self.cwd = os.getcwd()
# Quit code
file_item = file_menu.Append(wx.ID_EXIT, 'Quit', 'Quit Application')
menu_bar.Append(file_menu, '&File')
self.SetMenuBar(menu_bar)
# Add Main panel
self.panel = wx.Panel(self)
# Add Top and Bottom Panels
self.top_panel = wx.Panel(self.panel)
self.bottom_panel = wx.Panel(self.panel)
# Create horizontal and vertical boxes
self.hbox_main = wx.BoxSizer(wx.HORIZONTAL)
self.vbox_main = wx.BoxSizer(wx.VERTICAL)
self.hbox_top = wx.BoxSizer(wx.HORIZONTAL)
self.vbox_top_left = wx.BoxSizer(wx.VERTICAL)
self.vbox_top_right = wx.BoxSizer(wx.VERTICAL)
####################################################
# TOP
####################################################
##########################
# TOP LEFT
##########################
# List box text
self.lbl_filter = wx.StaticText(self.top_panel, wx.ID_ANY,
u"Select all cases to apply file to",
wx.DefaultPosition, wx.DefaultSize, 0)
self.lbl_filter.Wrap(-1)
self.vbox_top_left.Add(self.lbl_filter, 0, wx.EXPAND)
# The list box that all the file names are in
self.list_box = wx.CheckListBox(self.top_panel, id=wx.ID_ANY, pos=wx.DefaultPosition, size=(300, 300),
choices=[], style=wx.LB_HSCROLL|wx.LB_MULTIPLE|wx.LB_NEEDED_SB|wx.LB_SORT)
self.vbox_top_left.Add(self.list_box, 0, wx.EXPAND, 5)
# List box filter text
self.lbl_filter = wx.StaticText(self.top_panel, wx.ID_ANY,
u"Case filter (separate wildcards with a comma and choose filter logic (AND or OR)\n(i.e. HS, 2022 with AND selected will modify all 2022 HS cases)",
wx.DefaultPosition, wx.DefaultSize, 0)
self.lbl_filter.Wrap(-1)
self.vbox_top_left.Add(self.lbl_filter, 0, wx.EXPAND)
# List box filter
self.hbox_filter = wx.BoxSizer(wx.HORIZONTAL)
self.txt_filter = wx.TextCtrl(self.top_panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
self.txt_filter.SetMinSize(wx.Size(300, -1))
self.hbox_filter.Add(self.txt_filter, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5)
# List box radio buttons
logic_choices = [u"AND", u"OR"]
self.rdo_logic = wx.RadioBox(self.top_panel, wx.ID_ANY, u"Filter Logic", wx.DefaultPosition, wx.DefaultSize,
logic_choices, 1, wx.RA_SPECIFY_ROWS)
self.rdo_logic.SetSelection(0)
self.hbox_filter.Add(self.rdo_logic, 0, wx.EXPAND, 5)
# Add filter stuff to vbox_top
self.vbox_top_left.Add(self.hbox_filter, 0, wx.EXPAND)
# Add top components to hbox
self.hbox_top.Add(self.vbox_top_left, 0, wx.EXPAND)
##########################
# TOP RIGHT
##########################
# Add warning text
self.lbl_warning = wx.StaticText(self.top_panel, wx.ID_ANY,
u"*** WARNING *** HELLO WORLD ",
wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTER_HORIZONTAL)
self.lbl_warning.Wrap(-1)
self.vbox_top_right.Add(self.lbl_warning, 0, wx.EXPAND, 5)
# Radio buttons for software choice
rdo_choices = [u"App 1", u"App 2", u"App 3"]
self.rdo_software = wx.RadioBox(self.top_panel, wx.ID_ANY, u"Select Software", wx.DefaultPosition,
wx.DefaultSize, rdo_choices, 1, wx.RA_SPECIFY_COLS)
self.rdo_software.SetSelection(0)
self.vbox_top_right.Add(self.rdo_software, 0, wx.EXPAND, 5)
# Checkbox for archive
self.cb_archive = wx.CheckBox(self.top_panel, wx.ID_ANY, u"Archive files before running", wx.DefaultPosition,
wx.DefaultSize, 0)
self.vbox_top_right.Add(self.cb_archive, 0, wx.EXPAND, 5)
# Checkbox for saving
self.cb_save = wx.CheckBox(self.top_panel, wx.ID_ANY, u"Save files after running", wx.DefaultPosition,
wx.DefaultSize, 0)
self.vbox_top_right.Add(self.cb_save, 0, wx.EXPAND, 5)
# Folder selection label
self.lbl_cases = wx.StaticText(self.top_panel, wx.ID_ANY, u"Select Folder With Cases", wx.DefaultPosition,
wx.DefaultSize, 0)
self.lbl_cases.Wrap(-1)
self.vbox_top_right.Add(self.lbl_cases, 0, wx.EXPAND, 5)
# Add Folder selection
self.hbox_folder = wx.BoxSizer(wx.HORIZONTAL)
self.txt_cases = wx.TextCtrl(self.top_panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0)
self.txt_cases.SetMinSize(wx.Size(400, -1))
self.hbox_folder.Add(self.txt_cases, 0, wx.EXPAND, 5)
# Folder select button
self.btn_cases = wx.Button(self.top_panel, wx.ID_ANY, u"Case Folder", wx.DefaultPosition, wx.DefaultSize, 0)
self.hbox_folder.Add(self.btn_cases, 0, wx.EXPAND, 5)
# Add to sizer
self.vbox_top_right.Add(self.hbox_folder, 1, wx.SHAPED, 5)
self.hbox_top.Add(self.vbox_top_right, 0, wx.EXPAND, 5)
self.vbox_main.Add(self.hbox_top, 0, wx.EXPAND)
####################################################
# BOTTOM
####################################################
self.bottom_box = wx.StaticBox(self.bottom_panel, label='Progress Output')
self.hbox_output = wx.StaticBoxSizer(self.bottom_box, wx.HORIZONTAL)
self.txt_output = wx.TextCtrl(self.bottom_box, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize,
wx.TE_MULTILINE | wx.TE_READONLY)
# Put it all together
self.vbox_main.Add(self.top_panel, 1, wx.EXPAND)
self.vbox_main.Add(self.bottom_panel, 1, wx.EXPAND)
self.top_panel.SetSizerAndFit(self.hbox_top)
self.bottom_panel.SetSizerAndFit(self.hbox_output)
self.panel.SetSizerAndFit(self.vbox_main)
self.Centre()
self.Layout()
if __name__ == '__main__':
app = wx.App(0)
MainFrame = GUI(None, title='Batch Apply %s' % VERSION)
app.SetTopWindow(MainFrame)
MainFrame.Show()
app.MainLoop()
这是 GUI 的粗略图
这是我得到的:
主机只有一个child叫panel
。因此,这个 只有 child 的框架(不是另一种 window 的框架)在调整大小时将适合它的 parent 的客户区.好的。如果超过一个 child.
您还有两个面板,作为 panel
的 children。例如,如果您想要不同的背景颜色,这会很好。如果没有,那就没必要了,但是这些多余的面板没有任何问题。
有两个不同的区域:顶部(垂直方向不可调整大小)和底部(可调整大小)。这将需要处理 panel
内容布局的 'main sizer' 中的两个 sub-sizers。但是您正在为这些区域使用两个面板,所以最好让我们使用一个主要的 sizer(我将使用 vbox_main
)作为这两个面板 panel
内的布局。 sub-panel 的内容布局将由 sizer 处理。
在'top'地区也有两个不同的地区;所以另外两个 sub-sizers。你的设计是正确的。
vbox_top_left
希望它管理的控件(children of top_panel
)适合可用的 space。因为这是一个 vertical sizer,所以我们需要:
1) A child 可以改变垂直尺寸:使用 proportion=1
2) child 可以改变水平大小:使用 wx.EXPAND
标志。
3) 如果在某些控件之间添加垂直可调整大小的 spacers 会很好。
对vbox_top_right
的控制size-handled应用类似的标准(children of top_panel
)。
底部区域很特殊,因为您希望在标签和文本控件周围绘制一个矩形。为此,我们需要一个特殊的 sizer:StaticBoxSizer。它的特殊之处在于它处理的控件 children 不是面板的,而是底层 wx.StaticBox
的。有关示例和更多解释,请参阅上层文档 link。
self.hbox_output = wx.StaticBoxSizer(wx.HORIZONTAL, self.bottom_panel)
self.hbox_output.Add(wx.StaticText(self.hbox_output.GetStaticBox(), ....), ...)
self.hbox_output.Add(wx.TextCtrl(self.hbox_output.GetStaticBox(), ....), 1, wx.EXPAND, 5)
要将 children 添加到此 sizer,请遵循与 'top' 区域相同的标准。这里没有什么不同。
现在,sizer 的行为(我跳过你使用的其他 sub-sizers):
# No vertical nor horizontal expanding
# self.hbox_top.Add(self.vbox_top_left, 0, wx.EXPAND) <<== not what expected
self.hbox_top.Add(self.vbox_top_left, 0)
# Only horizontal expanding
# self.hbox_top.Add(self.vbox_top_right, 0, wx.EXPAND, 5) <<== not what expected
self.hbox_top.Add(self.vbox_top_right, 1, 0, 5)
最后的工作是绑定面板和sizer:
self.top_panel.SetSizer(self.hbox_top)
self.bottom_panel.SetSizer(self.hbox_output)
# Top panel expands only in horizontal
self.vbox_main.Add(self.top_panel, 0, wx.EXPAND)
# Bottom part expands in both directions
self.vbox_main.Add(self.bottom_panel, 1, wx.EXPAND)
self.panel.SetSizerAndFit(self.vbox_main)
self.Centre()
self.Layout()
使用单个面板更容易。我使用了你的两个 sub-panels 只是为了演示它是如何工作的:主 sizer 处理 sub-panels,每个面板为其处理 children.[=26= 的 sizer 使用一个 sizer ]