wx python BoxSizer не расширяется до окна плюс странный пробел в верхней части графического интерфейса - PullRequest
0 голосов
/ 13 мая 2019

У меня проблемы с расширением размеров. Я добавил две вспомогательные панели, которые, как я надеялся, решат мою проблему, но, похоже, усугубили ее. Я надеюсь, что top_panel расширится до ширины основного panel. vbox_top_right должно расшириться, чтобы заполнить остальную часть hbox_top. Затем bottom_panel должен расширяться как по горизонтали, так и по вертикали, чтобы заполнить оставшуюся часть основного panel. Ничего этого не происходит.

После того, как я разделил все на две подпанели, у меня возникли проблемы, когда у меня большое пустое пространство сверху. Кроме того, мой bottom_panel, кажется, нигде не расширяется. Я также не уверен, правильно ли я использую SetSizerAndFit, потому что я нигде не упоминал об использовании его на нескольких панелях. Я должен только применить его к основному panel?

Обратите внимание, что я вынужден использовать wx 3.0. У меня установлены 2.8 и 3.0, и были проблемы с wx.StaticBoxSizer с 2.8. Я знаю, что это, скорее всего, не имеет никакого отношения к моей проблеме, просто код не будет работать правильно, если вы попробуете это в 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 Crude drawing of GUI

Вот что я получаю: Output

1 Ответ

1 голос
/ 14 мая 2019

В основном кадре есть только один дочерний элемент с именем panel.Таким образом, этот единственный дочерний элемент кадра (не окна другого типа) будет соответствовать клиентской области его родителя при изменении его размера.Хорошо.Это не будет верно в случае более чем одного ребенка.

У вас есть еще две панели, как дети panel.Это было бы хорошо, если, например, вы хотите разные цвета фона.Если нет, то в этом нет необходимости, но в этих лишних панелях нет ничего плохого.

Есть две разные области: верхняя (не изменяемая в вертикальном направлении) и нижняя (изменяемая).Для этого потребуется два подсайзера «главного классификатора», который обрабатывает макет содержимого panel.Но вы используете две панели для этих областей, поэтому лучше использовать основной размер (я буду использовать vbox_main) для макета внутри panel этих двух панелей.Расположение содержимого под-панели будет обрабатываться сайзером.

В «верхней» области также есть две разные области;так что еще два подсайзера.Ваш дизайн правильный.

vbox_top_left хочет, чтобы элементы управления, которыми он управляет (дочерние элементы top_panel), помещались в доступное пространство.Поскольку это размер вертикаль , нам нужно:
1) Ребенок может изменить размер по вертикали: используйте proportion=1
2) Ребенок может изменить размер по горизонтали: используйте флаг wx.EXPAND.
3) Если было бы целесообразно добавить вертикальные изменяемые размеры прокладок между некоторыми элементами управления.

Применять аналогичные критерии для элементов управления, размер которых обрабатывается как vbox_top_right (с дочерними элементами top_panel тоже).

Нижняя область отличается тем, что вы хотите, чтобы вокруг метки и текстового элемента управления был нарисован прямоугольник.Для этого нам понадобится специальный классификатор: StaticBoxSizer .Это необычно в том смысле, что элементы управления, которые он обрабатывает, являются потомками не панели, а подкладки wx.StaticBox.См. Верхнюю ссылку на документацию для примера и дополнительных объяснений.

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)


Чтобы добавить дочерних элементов в этот классификатор, следуйте тем же критериям, что и для верхней области.Здесь нет ничего особенного.

Теперь, поведение классификаторов (я пропускаю другие используемые вами подсайзеры):

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

Последняя задача - связать панели и классификаторы:

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

Использовать одну панель проще.Я использовал ваши две вспомогательные панели только для того, чтобы продемонстрировать, как это работает: главный классификатор обрабатывает вложенные панели, каждая панель использует свой размерный измеритель, который обрабатывает дочерние элементы.

...