代码之家  ›  专栏  ›  技术社区  ›  falcoso

无法在wxPython中将自定义大小工具添加为其子窗口小部件的父级

  •  0
  • falcoso  · 技术社区  · 5 年前

    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'
    

    我相信这是因为我试图使用我的自定义类作为它内部所有小部件的父类,但是我不明白为什么会发生这种情况?

    我是非常新的创建图形用户界面(这是我的第一个项目),但我目前正在经历和修复所有的过程中提到家长等,所以我很难知道正确的搜索条件,看看是否有其他人有这个问题。

    我原来的代码只是 InitUI(self) 从main调用的函数wx.框架将monBox创建为一个StaticBoxSizer,它直接添加了所有的子部件。正如一开始提到的,我之所以要将其拆分,是因为有许多事件处理程序和由这个面板创建的其他dialog框,我想将它们保存在一个单独的文件中,以帮助保持代码可读性。

    GUI

    0 回复  |  直到 5 年前
        1
  •  1
  •   kbr85    5 年前

    问题是您是从中派生MonitorBox类的 wx.StaticBoxSizer 和一个 wx.Button 只能是窗户的孩子( wx.Frame wx.Panel 等)不是一个尺寸( ).

    如果您想分离代码,那么MonitorBox类应该来自 . 请参阅下面的代码(及其注释)以了解执行此操作的方法。

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