Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python&;wxPython-代码评论-简写/方便/重复_Python_Layout_Automation_Wxpython_Repeat - Fatal编程技术网

Python&;wxPython-代码评论-简写/方便/重复

Python&;wxPython-代码评论-简写/方便/重复,python,layout,automation,wxpython,repeat,Python,Layout,Automation,Wxpython,Repeat,事实上,我想首先承认我很害怕问这个问题。也就是说,我有以下课程组合: 对话类: class formDialog(wx.Dialog): def __init__(self, parent, id = -1, panel = None, title = _("Unnamed Dialog"), modal = False, sizes = (400, -1)): wx.Dialog.__init__(self, parent, id, _(title),

事实上,我想首先承认我很害怕问这个问题。也就是说,我有以下课程组合:

对话类:

class formDialog(wx.Dialog):
  def __init__(self, parent, id = -1, panel = None, title = _("Unnamed Dialog"),
               modal = False, sizes = (400, -1)):
    wx.Dialog.__init__(self, parent, id, _(title),
                       style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)

    if panel is not None:
      self._panel = panel(self)

      self._panel.SetSizeHints(*sizes)

      ds = wx.GridBagSizer(self._panel._gap, self._panel._gap)

      ds.Add(self._panel, (0, 0), (1, 1), wx.EXPAND | wx.ALL, self._panel._gap)

      ds.Add(wx.StaticLine(self), (1, 0), (1, 1), wx.EXPAND | wx.RIGHT | wx.LEFT, self._panel._gap)

      self.bs = self.CreateButtonSizer(self._panel._form['Buttons'])

      ds.Add(self.bs, (2, 0), (1, 1), wx.ALIGN_RIGHT | wx.ALL, self._panel._gap)

      ds.AddGrowableCol(0)
      ds.AddGrowableRow(0)

      self.SetSizerAndFit(ds)

      self.Center()

      self.Bind(wx.EVT_BUTTON, self._panel.onOk, id = wx.ID_OK)
      self.Bind(wx.EVT_BUTTON, self._panel.onClose, id = wx.ID_CANCEL)
      self.Bind(wx.EVT_CLOSE, self._panel.onClose)

      if modal:
        self.ShowModal()
      else:
        self.Show()
窗体类:

class Form(wx.Panel):
  reqFields = [
    ('Defaults', {}),
    ('Disabled', [])
  ]

  def __init__(self, parent = None, id = -1, gap = 2, sizes = (-1, -1)):
    wx.Panel.__init__(self, parent, id)

    self.SetSizeHints(*sizes)

    self._gap = gap

    self.itemMap = {}

    if hasattr(self, '_form'):
      # There are a number of fields which need to exist in the form
      # dictionary.  Set them to defaults if they don't exist already.
      for k, d in self.reqFields:
        if not self._form.has_key(k):
          self._form[k] = d

      self._build()

  def _build(self):
    """
    The Build Method automates sizer creation and element placement by parsing
    a properly constructed object.
    """

    # The Main Sizer for the Panel.
    panelSizer = wx.GridBagSizer(self._gap, self._gap)

    # Parts is an Ordered Dictionary of regions for the form.
    for group, (key, data) in enumerate(self._form['Parts'].iteritems()):
      flags, sep, display = key.rpartition('-') #@UnusedVariable

      # HR signifies a Horizontal Rule for spacing / layout.  No Data Field.
      if display == 'HR':
        element = wx.StaticLine(self)

        style = wx.EXPAND

      # Any other value contains elements that need to be placed.
      else:
        element = wx.Panel(self, -1)

        # The Row Sizer
        rowSizer = wx.GridBagSizer(self._gap, self._gap)

        for row, field in enumerate(data):
          for col, item in enumerate(field):
            style = wx.EXPAND | wx.ALL

            pieces = item.split('-')

            # b for Buttons
            if pieces[0] == 'b':
              control = wx._controls.Button(element, -1, pieces[1])

            # custom items - Retrieve from the _form object
            if pieces[0] == 'custom':
              control = self._form[pieces[1]](element)

              # The row in the Grid needs to resize for Lists.
              panelSizer.AddGrowableRow(group)

              # Now the Row has to grow with the List as well.
              rowSizer.AddGrowableRow(row)

            # custom2 - Same as custom, but does not expand
            if pieces[0] == 'custom2':
              control = self._form[pieces[1]](element)

              style = wx.ALL

            # c for CheckBox
            if pieces[0] == 'c':
              control = wx.CheckBox(element, label = _(pieces[2]), name = pieces[1])

              control.SetValue(int(self._form['Defaults'].get(pieces[1], 0)))

            # d for Directory Picker
            if pieces[0] == 'd':
              control = wx.DirPickerCtrl(element, name = pieces[1])

              control.GetTextCtrl().SetEditable(False)

              control.GetTextCtrl().SetName(pieces[1])

              control.GetTextCtrl().SetValue(self._form['Defaults'].get(pieces[1], ''))

            # f for File Browser
            if pieces[0] == 'f':
              control = wx.FilePickerCtrl(element, name = pieces[1], wildcard = pieces[2])

              control.GetTextCtrl().SetEditable(False)

              control.GetTextCtrl().SetValue(self._form['Defaults'].get(pieces[1], ''))

            # f2 for Save File
            if pieces[0] == 'f2':
              control = wx.FilePickerCtrl(element, name = pieces[1],
                style = wx.FLP_SAVE | wx.FLP_OVERWRITE_PROMPT | wx.FLP_USE_TEXTCTRL,
                wildcard = pieces[2])

              control.GetTextCtrl().SetEditable(False)

            # h for Horizontal Rule - layout helper.
            if pieces[0] == 'h':
              control = wx.StaticLine(element)
              style = wx.EXPAND

            # l for Label (StaticText)
            if pieces[0] == 'l':
              control = wx.StaticText(element, label = _(pieces[1]))

              # Labels do not expand - override default style.
              style = wx.ALL | wx.ALIGN_CENTER_VERTICAL

            # p for Password (TextCtrl with Style)
            if pieces[0] == 'p':
              control = wx.TextCtrl(element, name = pieces[1], style = wx.TE_PASSWORD)

              control.SetValue(self._form['Defaults'].get(pieces[1], ''))

            # s for ComboBox (Select)
            if pieces[0] == 's':
              control = wx.ComboBox(element, name = pieces[1],
                choices = self._form['Options'].get(pieces[1], []),
                style = wx.CB_READONLY)

              control.SetValue(self._form['Defaults'].get(pieces[1], ''))

            # s2 for Spin Control
            if pieces[0] == 's2':
              control = wx.SpinCtrl(element, name = pieces[1], size = (55, -1),
                min = int(pieces[2]), max = int(pieces[3]))

              control.SetValue(int(self._form['Defaults'].get(pieces[1], 1)))

              # Spin Ctrl's do not expand.
              style = wx.ALL

            # t for TextCtrl
            if pieces[0] == 't':
              control = wx.TextCtrl(element, name = pieces[1])

              try:
                control.SetValidator(self._form['Validators'][pieces[1]])
              except KeyError: pass # No Validator Specified.

              control.SetValue(self._form['Defaults'].get(pieces[1], ''))

            # tr for Readonly TextCtrl
            if pieces[0] == 'tr':
              control = wx.TextCtrl(element, name = pieces[1], style = wx.TE_READONLY)

              control.SetValue(self._form['Defaults'].get(pieces[1], ''))

            # Check for elements disabled by default.  Store reference to 
            # Element in itemMap for reference by other objects later.
            if len(pieces) > 1:
              if pieces[1] in self._form['Disabled']:
                control.Enable(False)

              self.itemMap[pieces[1]] = control

            # Place the control in the row.
            rowSizer.Add(control, (row, col), (1, 1), style, self._gap)

            if style == wx.EXPAND | wx.ALL:
              rowSizer.AddGrowableCol(col)

        if 'NC' not in flags:
          sb = wx.StaticBox(element, -1, _(display))
          sz = wx.StaticBoxSizer(sb, wx.VERTICAL)

          sz.Add(rowSizer, 1, flag = wx.EXPAND)

          element.SetSizerAndFit(sz)
        else:
          element.SetSizerAndFit(rowSizer)

      panelSizer.Add(element, (group, 0), (1, 1), wx.EXPAND | wx.ALL, self._gap)

    panelSizer.AddGrowableCol(0)

    self.SetSizerAndFit(panelSizer)

  def getDescendants(self, elem, list):
    children = elem.GetChildren()

    list.extend(children)

    for child in children:
      self.getDescendants(child, list)

  def getFields(self):
    fields = []

    self.getDescendants(self, fields)

    # This removes children we can't retrieve values from.  This should result
    # in a list that only contains form fields, removing all container elements.
    fields = filter(lambda x: hasattr(x, 'GetValue'), fields)

    return fields

  def onOk(self, evt):
    self.onClose(evt)

  def onClose(self, evt):
    self.GetParent().Destroy()
该表单用于子类化,如下所示:

class createQueue(Form):
  def __init__(self, parent):
    self._form = {
      'Parts' : OrderedDict([
        ('Queue Name', [
          ('t-Queue Name',)
        ])
      ]),
      'Buttons' : wx.OK | wx.CANCEL
    }

    Form.__init__(self, parent)

class generalSettings(Form):
  def __init__(self, parent):
    self._form = {
      'Parts': OrderedDict([
        ('Log Settings', [
          ('l-Remove log messages older than: ', 's2-interval-1-10', 's-unit')
        ]),
        ('Folder Settings', [
          ('l-Spool Folder Location:', 'd-dir'),
          ('l-Temp Folder Location:', 'd-temp')
        ]),
        ('Email Notifications', [
          ('l-Alert Email To:', 't-alert_to'),
          ('l-Alert Email From:', 't-alert_from'),
          ('l-Status Email From:', 't-status_from'),
          ('l-Alert Email Server:', 't-alert_host'),
          ('l-Login:', 't-alert_login'),
          ('l-Password:', 'p-alert_password')
        ]),
        ('Admin User', [
          ('c-req_admin-Require Admin Rights to make changes.',)
        ]),
        ('Miscellaneous', [
          ('l-Print Worker Tasks:', 's2-printtasks-1-256', 'l-Job Drag Options:', 's-jobdrop')
        ])
      ]),
      'Options': {
        'unit': ['Hours', 'Days', 'Months'],
        'jobdrop': ['Move Job to Queue', 'Copy Job to Queue']
      },
      'Buttons': wx.OK | wx.CANCEL
    }

    Form.__init__(self, parent)
可以这样使用:

formDialog(parent, panel = createQueue, title = 'Create a Queue', sizes = (200, -1))

formDialog(parent, panel = generalSettings, title = "General Settings")
哇,那是一吨,感谢所有走到这一步的人。我的想法是,我想要一些能够处理wxPython中单调的布局部分的东西。我正在设计一个用户界面,需要创建100个不同的对话框和表单。我想要的是能够从结构化对象动态生成表单的东西

我想听听其他开发者对这种方法的想法。我见过的最接近类似的东西是Drupal的FormAPI。我觉得这是可行的,原因如下:

  • 轻松地重新排列字段
  • 无需手动创建/管理大小调整器
  • 可以轻松创建复合/复杂表单
  • 可以轻松添加显示辅助元素(StaticBoxSizer、静态线)
我担心这是一种不可取的做法,原因如下:

  • \u build()
    函数体在表单类中
  • 其他开发人员乍一看可能不清楚
  • 使用结构化字符串定义字段
  • 也许有更好的办法

任何具有建设性、破坏性或其他性质的想法都将受到赞赏。谢谢

既然您使用的是wx,那么您应该学习wxglade。它是一个图形化GUI构建器,您可以使用它来构建GUI,并生成一个带有布局的
.wxg
文件,您可以将其加载到脚本中


该文件实际上只是xml,因此您可以通过编程生成它并从中动态加载不同的GUI。也许这会有帮助。

你也应该试试wxFormDesigner或XRCed。

我看了一下wxglade,但发现它生成的代码过于冗长。但是我不知道.wxg文件是xml文件,所以我可能需要重新访问它。谢谢我不喜欢XML,但在建议的项目中发现了一些东西,可以用来清理上面的类。谢谢你的建议。我可能会得到类似于我上面所说的东西,但这已经清理了一点。