Невозможно добавить пользовательский Sizer в качестве родительского для его дочерних виджетов в wxPython - PullRequest
1 голос
/ 26 мая 2019

В настоящее время я пытаюсь сделать графический интерфейс в wxPython.Макет представляет собой панель с правой стороны графического интерфейса с 3 StaticBoxSizer.Один из них намного сложнее, чем другие, с возможностью добавления к нему большего количества элементов нажатием кнопки, поэтому я решил разбить файл GUI и создать собственный класс, чтобы попытаться сделать код немного более сложным.clear.

Текущий инициализатор класса выглядит следующим образом:

class MonitorBox(wx.StaticBoxSizer):
    def __init__(self, monitors, pins, devices, *args, **kw):
        super().__init__(*args, **kw)
        self.monitors = monitors
        self.pin_choices = pins
        self.dev_choices = devices
        self.InitUI()

    def InitUI(self):
        monList = wx.FlexGridSizer(cols=4, vgap=5, hgap=5)
        add_monitor = wx.Button(self, wx.ID_ANY, "Add Monitor")
        add_monitor.Bind(wx.EVT_BUTTON, self.on_add_button)

        # create list headings
        nametxt = wx.StaticText(self, wx.ID_ANY, "Name:")
        devtxt = wx.StaticText(self, wx.ID_ANY, "Device:")
        pintxt = wx.StaticText(self, wx.ID_ANY, "Pin:")
        blnktxt = wx.StaticText(self, wx.ID_ANY, "")

        # Add Headings to sizer
        monList.AddMany([nametxt, devtxt, pintxt, blnktxt])
        self.monitor_rows = {}  # dictionary to store references to all the widgets

        # Create a row for each item in the mons dictionary
        for monitor, dev in self.mons.items():
            del_mon_button = wx.Button(self, wx.ID_ANY, '-', name=monitor, style=wx.BU_EXACTFIT)
            del_mon_button.Bind(wx.EVT_BUTTON, self.on_del_monitor)
            mon_name = wx.TextCtrl(self, wx.ID_ANY, monitor,
                                   style=wx.TE_PROCESS_ENTER,
                                   name=monitor)
            dev_name = wx.ComboBox(self, wx.ID_ANY, choices=self.dev_choices,
                                   style=wx.CB_READONLY, value=dev[0],
                                   name=monitor)
            pin_name = wx.ComboBox(self, wx.ID_ANY, choices=self.pin_choices[dev[0]],
                                   style=wx.CB_READONLY, value=dev[1],
                                   name=monitor)

            dev_name.Bind(wx.EVT_COMBOBOX, self.on_dev_choice)
            pin_name.Bind(wx.EVT_COMBOBOX, self.on_pin_choice)
            self.monitor_rows[monitor] = [mon_name, dev_name, pin_name, del_mon_button]
            monList.AddMany(self.monitor_rows[monitor])
        # TODO: make sure all the combo boxes are the same size
        self.monList = monList
        self.Add(monList, 1, wx.ALL, 5)
        self.Add(add_monitor, 0, wx.ALL, 5)

Однако, когда я пытаюсь запустить графический интерфейс, я получаю сообщение об ошибке:

add_monitor = wx.Button(self, wx.ID_ANY, "Add Monitor")
TypeError: Button(): arguments did not match any overloaded call:
  overload 1: too many arguments
  overload 2: argument 1 has unexpected type 'MonitorBox'

IПолагаю, это потому, что я пытаюсь использовать свой пользовательский класс в качестве родительского для всех виджетов внутри него, но я не совсем понимаю, почему это происходит?

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

Мой оригинальный код был просто функцией InitUI(self), вызываемой из основного wx.Frame графического интерфейса и создающей monBox как StaticBoxSizer, который слишком напрямую добавляет все дочерние виджеты.Как уже упоминалось в начале, причина, по которой я хотел разделить это, состоит в том, что на этой панели было создано несколько обработчиков событий и дополнительных блоков diaglog, которые я хотел сохранить в отдельном файле, чтобы обеспечить читабельность кода.

Исходный код (не разбитый на отдельный класс) создает панель «Мониторы», которую можно увидеть на рисунке:

GUI

1 Ответ

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

Проблема в том, что вы извлекаете класс MonitorBox из wx.StaticBoxSizer, а wx.Button может быть только дочерним элементом окна (wx.Frame, wx.Panel и т. Д.), А не sizer (wx.StaticBoxSizer).

Если вы хотите отделить код, тогда ваш класс MonitorBox должен быть из wx.Panel. Посмотрите код (и его комментарии) ниже для способа сделать это.

import wx

class MonitorBox(wx.Panel):
    """
    This is the class with all the widgets in your MonitorBox class.
    You need to arrange the widget in a sizer here. 
    """
    def __init__(self, parent):
        super().__init__(parent=parent)

        #### Parent panel
        # No need to define a parent panel because the class itself is already a
        # panel. So self refers to a panel.

        #### Widgets
        # Here self is a panel not a sizer like in your question. So no problem
        # adding the button.
        self.add_monitor = wx.Button(self, wx.ID_ANY, "Add Monitor")
        #### Sizers
        self.sizer = wx.BoxSizer()
        #### Add widgets to sizer
        self.sizer.Add(self.add_monitor, flag=wx.CENTER)
        #### Add sizer to panel
        self.SetSizer(self.sizer)
        self.Fit()

class Main(wx.Frame):
    def __init__(self):
        super().__init__(None, title='Panel 3 comes from a different class',
                         size=(500, 500))
        #### Parent panel
        self.panel = wx.Panel(self)

        #### Some widgets
        ## The Static Box widget
        self.monitorsBox = wx.StaticBox(self.panel, label="Monitors")

        self.panelB = wx.Panel(self.panel, size=(200, 100))
        self.panelB.SetBackgroundColour((0, 0, 255))
        self.panelR = wx.Panel(self.panel, size=(200, 100))
        self.panelR.SetBackgroundColour((255, 0, 0))
        ## Add panel 3 as a child of the wx.StaticBox!!!
        self.panel3 = MonitorBox(self.monitorsBox)

        #### Sizers
        ## Main sizer
        self.sizer = wx.FlexGridSizer(3, 1, 5, 5)
        ## Sizers for the static box
        # The static box sizer
        self.monitorsBoxSizer = wx.StaticBoxSizer(self.monitorsBox, wx.VERTICAL)
        # Sizer for the content of the static box
        self.monitorsBoxSizerContent = wx.BoxSizer()

        #### Add widgets to sizers
        ## Static box content
        self.monitorsBoxSizerContent.Add(self.panel3, flag=wx.EXPAND)
        self.monitorsBoxSizer.Add(self.monitorsBoxSizerContent)
        ## Add everything to the main sizer
        self.sizer.Add(self.panelB, flag=wx.EXPAND|wx.ALL, border=10)
        self.sizer.Add(self.panelR, flag=wx.EXPAND|wx.ALL, border=10)
        self.sizer.Add(self.monitorsBoxSizer, flag=wx.EXPAND|wx.ALL, border=10)

        #### Add sizer to self.panel
        self.panel.SetSizer(self.sizer)
        self.panel.Fit()

if __name__ == '__main__':
    app = wx.App()                            
    frame = Main()
    frame.Show()  
    app.MainLoop()

Скорее всего, в исходном коде основной класс был получен из wx.Frame, верно? Если нет, игнорируйте все остальное. Вот почему это сработало. Потому что вы делали пуговицу дочерней, а не сортировочной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...