Как был бы Вы дизайн a очень “Pythonic” платформа UI?

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

12
задан dbr 4 November 2008 в 13:30
поделиться

15 ответов

Вы могли на самом деле осуществить это, но это потребует метаклассов использования, которые являются глубоким волшебством (там быть драконами). Если Вы хотите введение к метаклассам, существует ряд статей от IBM, которым удается представить идеи, не расплавляя Ваш мозг.

Исходный код от ORM как SQLObject мог бы помочь также, так как он использует этот тот же вид декларативного синтаксиса.

7
ответ дан 2 December 2019 в 03:49
поделиться

Описание - не обязательно больше (или меньше) pythonic, чем функциональный, по моему скромному мнению. Я думаю, что многоуровневый подход был бы лучшим (от кнопки):

  1. Исходный слой, который принимает и возвращает типы данных Python.
  2. Функциональный динамический слой.
  3. Один или несколько декларативных/объектно-ориентированных слоев.

Подобный Elixir + SQLAlchemy.

0
ответ дан 2 December 2019 в 03:49
поделиться

Вот подход, который идет об определениях GUI немного по-другому использующего основанного на классах метапрограммирования, а не наследования.

Это - в основном Django/SQLAlchemy, вселенный, в котором он в большой степени основан на метапрограммировании и разделяет Ваш код GUI от Вашего "кода кода". Я также думаю, что это должно сделать интенсивное использование менеджеров по расположению как Java, делает, потому что, когда Вы отбрасываете код, никто не хочет постоянно настроить пиксельное выравнивание. Я также думаю, что было бы здорово, если у нас могли бы быть подобные CSS свойства.

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

from happygui.controls import *

MAIN_WINDOW = Window(width="500px", height="350px",
    my_layout=ColumnLayout(padding="10px",
        my_label=Label(text="What's your name kiddo?", bold=True, align="center"),
        my_edit=EditBox(placeholder=""),
        my_btn=Button(text="CLICK ME!", on_click=Handler('module.file.btn_clicked')),
    ),
)
MAIN_WINDOW.show()

def btn_clicked(sender): # could easily be in a handlers.py file
    name = MAIN_WINDOW.my_layout.my_edit.text
    # same thing: name = sender.parent.my_edit.text
    # best practice, immune to structure change: MAIN_WINDOW.find('my_edit').text
    MessageBox("Your name is '%s'" % ()).show(modal=True)

Одной прохладной вещью заметить является способ, которым можно сослаться на вход my_edit путем высказывания MAIN_WINDOW.my_layout.my_edit.text. В объявлении для окна я думаю, что важно смочь произвольно назвать средства управления в функции kwargs.

Вот то же приложение только с помощью абсолютного расположения (средства управления появятся в различных местах, потому что мы не используем необычного менеджера по расположению):

from happygui.controls import *

MAIN_WINDOW = Window(width="500px", height="350px",
    my_label=Label(text="What's your name kiddo?", bold=True, align="center", x="10px", y="10px", width="300px", height="100px"),
    my_edit=EditBox(placeholder="", x="10px", y="110px", width="300px", height="100px"),
    my_btn=Button(text="CLICK ME!", on_click=Handler('module.file.btn_clicked'), x="10px", y="210px", width="300px", height="100px"),
)
MAIN_WINDOW.show()

def btn_clicked(sender): # could easily be in a handlers.py file
    name = MAIN_WINDOW.my_edit.text
    # same thing: name = sender.parent.my_edit.text
    # best practice, immune to structure change: MAIN_WINDOW.find('my_edit').text
    MessageBox("Your name is '%s'" % ()).show(modal=True)

Я не совсем уверен все же, является ли это супер большим подходом, но я определенно думаю, что это находится на правильном пути. У меня нет времени для исследования этой идеи больше, но если кто-то поднял это как проект, я любил бы их.

1
ответ дан 2 December 2019 в 03:49
поделиться

Лично, я попытался бы реализовать JQuery как API в платформе GUI.

class MyWindow(Window):
    contents = (
        para('Hello World!'),
        button('Click Me', id='ok'),
        para('Epilog'),
    )

    def __init__(self):
        self['#ok'].click(self.message)
        self['para'].hover(self.blend_in, self.blend_out)

    def message(self):
        print 'You clicked!'

    def blend_in(self, object):
        object.background = '#333333'

    def blend_out(self, object):
        object.background = 'WindowBackground'
1
ответ дан 2 December 2019 в 03:49
поделиться

Если Вы действительно хотите кодировать UI, Вы могли бы попытаться получить что-то подобное ORM django; sth как это для получения простого браузера справки:

class MyWindow(Window):
    class VBox:
        entry = Entry()
        bigtext = TextView()

        def on_entry_accepted(text):
            bigtext.value = eval(text).__doc__

Идея состояла бы в том, чтобы интерпретировать некоторые контейнеры (как окна) как простые классы, некоторые контейнеры (как таблицы, v/hboxes) распознанный именами объектов и простыми виджетами как объекты.

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

О порядке элементов: в MyWindow выше Вас не должны отслеживать это (окно является концептуально контейнером с одним слотом). В других контейнерах можно попытаться отслеживать порядок, предполагающий, что у каждого конструктора виджета есть доступ к некоторому глобальному списку виджета. Это - то, как это сделано в django (AFAIK).

Немного взломов здесь, немного тонких настроек там... Существует все еще немного вещей думать, но я полагаю, что это возможно... и применимо, пока Вы не создаете сложный UIs.

Однако я довольно доволен PyGTK+Glade. UI является просто видом данных для меня, и это нужно рассматривать как данные. Существуют только слишком много параметры для тонкой настройки (как интервал в различных местах), и лучше справиться с тем использованием инструмента GUI. Поэтому я создаю свой UI в поляне, сохраняю как xml и синтаксический анализ с помощью gtk.glade.XML ().

1
ответ дан 2 December 2019 в 03:49
поделиться

У меня есть эта та же проблема. Я бледный к создать обертку вокруг любого инструментария GUI для Python, который прост в использовании, и вдохновленный Обувью, но должен быть подходом ООП (против рубиновых блоков).

Больше информации в: http://wiki.alcidesfonseca.com/blog/python-universal-gui-revisited

Чье-либо приветствие для присоединения к проекту.

1
ответ дан 2 December 2019 в 03:49
поделиться

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

2
ответ дан 2 December 2019 в 03:49
поделиться

Самое близкое, которое можно получить к rubyish блокам, с оператором от pep343:

http://www.python.org/dev/peps/pep-0343/

3
ответ дан 2 December 2019 в 03:49
поделиться

Возможно, не столь гладкий как версия Ruby, но как насчет чего-то вроде этого:

from Boots import App, Para, Button, alert

def Shoeless(App):
    t = Para(text = 'Not Clicked')
    b = Button(label = 'The label')

    def on_b_clicked(self):
        alert('You clicked the button!')
        self.t.text = 'Clicked!'

Как сказанный Justin, для реализации этого необходимо было бы использовать пользовательский метакласс на классе App, и набор свойств на Para и Button. Это на самом деле не было бы слишком твердо.

Проблема, с которой Вы сталкиваетесь затем: как Вы отслеживаете порядок, что вещи появляются в определении класса? В Python 2.x нет никакого способа знать если t должен быть выше b или наоборот, так как Вы получаете контент определения класса как Python dict.

Однако в Python 3.0 метаклассы изменяются несколькими (незначительными) способами. Один из них __prepare__ метод, который позволяет Вам предоставлять свой собственный подобный словарю объект, который будет использоваться вместо этого - это означает, что Вы сможете отследить заказ, в котором объекты определяются и располагают их соответственно в окно.

2
ответ дан 2 December 2019 в 03:49
поделиться

С некоторым волшебством Метакласса сохранить упорядочивание у меня есть следующая работа. Я не уверен, как pythonic, это - всего лишь это, является хорошим развлечением для создания простых вещей.

class w(Wndw):
  title='Hello World'
  class txt(Txt):  # either a new class
    text='Insert name here'
  lbl=Lbl(text='Hello') # or an instance
  class greet(Bbt):
    text='Greet'
    def click(self): #on_click method
      self.frame.lbl.text='Hello %s.'%self.frame.txt.text

app=w()
3
ответ дан 2 December 2019 в 03:49
поделиться

Единственная попытка сделать это, что я знаю о, является Воск Hans Nowak (который, к сожалению, мертв).

3
ответ дан 2 December 2019 в 03:49
поделиться

Это чрезвычайно изобретено и не pythonic вообще, но здесь является моей попыткой полубуквального перевода с помощью нового "с" оператором.

with Shoes():
  t = Para("Not clicked!")
  with Button("The Label"):
    Alert("You clicked the button!")
    t.replace("Clicked!")

Самая твердая часть имеет дело с тем, что Python не даст нам анонимные функции больше чем с одним оператором в них. Для обхождения этого мы могли создать список команд и пробежать их...

Так или иначе вот код бэкенда, с которым я выполнил это:

context = None

class Nestable(object):
  def __init__(self,caption=None):
    self.caption = caption
    self.things = []

    global context
    if context:
      context.add(self)

  def __enter__(self):
    global context
    self.parent = context
    context = self

  def __exit__(self, type, value, traceback):
    global context
    context = self.parent

  def add(self,thing):
    self.things.append(thing)
    print "Adding a %s to %s" % (thing,self)

  def __str__(self):
    return "%s(%s)" % (self.__class__.__name__, self.caption)


class Shoes(Nestable):
  pass

class Button(Nestable):
  pass

class Alert(Nestable):
  pass

class Para(Nestable):
  def replace(self,caption):
    Command(self,"replace",caption)

class Command(Nestable):
  def __init__(self, target, command, caption):
    self.command = command
    self.target  = target
    Nestable.__init__(self,caption)

  def __str__(self):
    return "Command(%s text of %s with \"%s\")" % (self.command, self.target, self.caption)

  def execute(self):
    self.target.caption = self.caption
4
ответ дан 2 December 2019 в 03:49
поделиться
## All you need is this class:

class MainWindow(Window):
    my_button = Button('Click Me')
    my_paragraph = Text('This is the text you wish to place')
    my_alert = AlertBox('What what what!!!')

    @my_button.clicked
    def my_button_clicked(self, button, event):
        self.my_paragraph.text.append('And now you clicked on it, the button that is.')

    @my_paragraph.text.changed
    def my_paragraph_text_changed(self, text, event):
        self.button.text = 'No more clicks!'

    @my_button.text.changed
    def my_button_text_changed(self, text, event):
        self.my_alert.show()


## The Style class is automatically gnerated by the framework
## but you can override it by defining it in the class:
##
##      class MainWindow(Window):
##          class Style:
##              my_blah = {'style-info': 'value'}
##
## or like you see below:

class Style:
    my_button = {
        'background-color': '#ccc',
        'font-size': '14px'}
    my_paragraph = {
        'background-color': '#fff',
        'color': '#000',
        'font-size': '14px',
        'border': '1px solid black',
        'border-radius': '3px'}

MainWindow.Style = Style

## The layout class is automatically generated
## by the framework but you can override it by defining it
## in the class, same as the Style class above, or by
## defining it like this:

class MainLayout(Layout):
    def __init__(self, style):
        # It takes the custom or automatically generated style class upon instantiation
        style.window.pack(HBox().pack(style.my_paragraph, style.my_button))

MainWindow.Layout = MainLayout

if __name__ == '__main__':
    run(App(main=MainWindow))

Было бы относительно легко сделать в Python с немного, что волшебство Python метакласса знает как. Который я имею. И знание PyGTK. Который я также имею. Получает идеи?

4
ответ дан 2 December 2019 в 03:49
поделиться

Я никогда не был удовлетворен статьями David Mertz в IBM на metaclsses, таким образом, я недавно написал свою собственную статью метакласса.Приятного отдыха.

4
ответ дан 2 December 2019 в 03:49
поделиться

Если Вы используете PyGTK с поляной и этой оберткой поляны, то PyGTK на самом деле становится несколько pythonic. Немного, по крайней мере.

В основном Вы создаете расположение GUI в Поляне. Вы также указываете обратные вызовы события в поляне. Затем Вы пишете класс для своего окна как это:

class MyWindow(GladeWrapper):
    GladeWrapper.__init__(self, "my_glade_file.xml", "mainWindow")
    self.GtkWindow.show()

    def button_click_event (self, *args):
        self.button1.set_label("CLICKED")

Здесь, я предполагаю, что у меня есть Кнопка GTK, где-нибудь названная button1 и что я указал button_click_event как нажатый обратный вызов. Обертка поляны вынимает большое усилие из отображения события.

Если бы я должен был разработать библиотеку Pythonic GUI, то я поддерживал бы что-то подобное, для помощи быстрой разработке. Единственная разница - то, что я удостоверился бы, чтобы виджеты имели больше интерфейса pythonic также. Текущие классы PyGTK кажутся очень C мне, за исключением того, что я использую foo.bar (...) вместо панели (нечто...), хотя я не уверен точно, что я сделал бы по-другому. Вероятно, допускайте Django, модели разрабатывают декларативные средства определения виджетов и событий в коде и разрешении Вас к данным доступа, хотя итераторы (где это имеет смысл, например, списки виджета, возможно), хотя я действительно не думал об этом.

3
ответ дан 2 December 2019 в 03:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: