Что такое хороший способ выразить иерархическую группировку виджетов в Python? - PullRequest
4 голосов
/ 16 февраля 2012

Это вопрос стиля Python - мой код на Python работает, я просто ищу предложения по соглашению о кодировании, которые облегчили бы чтение / понимание / отладку кода.

В частности, я работаю над классом Python, который позволяет вызывающей стороне добавлять виджеты в пользовательский графический интерфейс. Чтобы настроить графический интерфейс, пользователь должен написать метод, который добавляет виджеты (именованные или анонимные) в область виджетов, чтобы виджеты формировали дерево (как это обычно бывает в графических интерфейсах).

Чтобы позволить пользователю настроить дерево виджетов без необходимости давать имя каждому виджету-контейнеру (а затем явно ссылаться на этот родительский виджет при каждом добавлении дочернего виджета), мой API поддерживает понятие "стек родительского виджета". При объявлении контейнерного виджета пользователь может указать, чтобы поместить этот виджет в этот стек, а затем все остальные виджеты (которые явно не указывают родительский элемент) будут добавлены к родительскому элементу в верхней части стека по умолчанию. Вот простой пример того, что я имею в виду:

def SetupGUI(self):
   self.AddWidget(name="root", type="container", push=True)

   self.AddWidget(type="container", push=True)
   for i in range(0,8):
      self.AddWidget(name="button%i"%i, type="button")
   self.PopParentWidget()  # pop the buttons-container off the parents-stack

   self.AddWidget(type="container", push=True)
   for i in range(0,8):
      self.AddWidget(name="slider%i"%i, type="slider")
   self.PopParentWidget()  # pop the sliders-container off the parents-stack

   self.PopParentWidget()  # pop the container "root" off the parents-stack

Это удобно, но я считаю, что когда иерархия графического интерфейса становится более сложной, становится трудно определить, какой вызов self.PopParentWidget () соответствует какому виджету контейнера. Легко вставить одно слишком много или одно слишком мало, и в результате вы получите очень забавные, но непредвиденные результаты в графическом интерфейсе.

Так что мой вопрос, если не заставлять PopParentWidget () принимать явное имя виджета (которого я хочу избегать, потому что я не хочу называть каждый контейнерный виджет), могу ли я сделать что-нибудь, чтобы сделать пара push / pop в коде более очевидна для глаз?

В C / C ++ я бы делал это с использованием отступов, но с Python мне не разрешено это делать. Например, я хотел бы иметь возможность сделать это:

def SetupGUI(self):
   self.AddWidget(name="root", type="container", push=True)
      self.AddWidget(type="container", push=True)
         for i in range(0,8):
            self.AddWidget(name="button%i"%i, type="button")
         self.PopParentWidget()  # pop the buttons-container off the parents-stack
      self.AddWidget(type="container", push=True)
         for i in range(0,8):
            self.AddWidget(name="slider%i"%i, type="slider")
         self.PopParentWidget()  # pop the sliders-container off the parents-stack
      self.PopParentWidget()  # pop the container "root" off the parents-stack

... но Python выдаст ошибку IndentationError, если я проявлю творческий подход.

1 Ответ

6 голосов
/ 16 февраля 2012

В такой ситуации, когда у вас есть пара противоположных операций, требуется менеджер контекста . Вместо того, чтобы явно помещать и извлекать контейнерные виджеты в / из стека, вы бы помещали дочерние элементы контейнера в блок with. Основываясь на коде, который вы здесь показали, это может быть реализовано как

@contextlib.contextmanager
def container(self, name=None):
    self.AddWidget(name=name, type='container', push=True)
    yield
    self.PopParentWidget()

(Документация для contextlib.contextmanager).

Ваш SetupGUI метод становится:

def SetupGUI(self):
    with self.container(name='root'):
        with self.container():
            for i in range(0,8):
                self.AddWidget(name='button%i' % i, type='button')
        with self.container():
            for i in range(0,8):
                self.AddWidget(name='slider%i' % i, type='slider')

Как видите, вложенность очищена от отступа, и нет необходимости вручную толкать и выдвигать.

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