Изменить параметр свойства из конструктора класса [Python / Traits] - PullRequest
6 голосов
/ 31 марта 2012

Я новичок в python - извините, если моя терминология неверна. У меня есть класс, который наследует атрибуты Enthought Traits . Вот упрощенная версия:

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider = Range(0.0, 0.6, 0.1)
    my_slider._high = 0.7   # works; not what I need 'coz not instance-dependent

    view = View( Item('my_slider') )

    def __init__(self, arg1):
        # Call the parent's __init__
        HasTraits.__init__(self)

        self.my_slider._high = arg1  # what I need; doesn't work

# -- Main program -----

top_range = 0.9

my_gui = GUIThing(top_range)
my_gui.configure_traits()

Это просто создает окно с ползунком , которое изначально изменяется от 0,0 до 0,6 с начальным значением 0,1. При создании экземпляра GUIThing я хочу изменить максимальное значение для ползунка в зависимости от текущего значения top_range. Однако линия

self.my_slider._high = arg1

Результаты в

AttributeError: 'float' object has no attribute '_high'

Когда в __init__(), self.my_slider возвращает не объект слайдера, а текущее значение слайдера.

Что я делаю не так? Спасибо!

Edit:

Следующее также не работает:

class GUIThing(HasTraits):

    def __init__(self, arg1):
        # Call the parent's __init__
        HasTraits.__init__(self)

        self.my_slider = Range(0.0, arg1, 0.0)

    view = View( Item('my_slider') )

Это был бы прямой способ сделать то, что я пытаюсь сделать, но это приводит к GUI, где вместо ползунка есть текстовое поле, которое гласит «enthought.traits.trait_types.Range object at 0xa61946c» , Таким образом, проблема в том, что когда my_slider создается внутри __init__(), тогда «my_slider» означает сам объект (который не отображается должным образом через View); но если my_slider создается за пределами __init__(), тогда «my_slider» означает текущее значение (число с плавающей запятой; которое запрещает доступ к свойствам объекта).

Не уверен, свойственно ли это чертам или я просто не знаю, как правильно инициализировать объекты.

Ответы [ 5 ]

4 голосов
/ 01 апреля 2012

Наконец нашел ответ в недавнем сообщении списка рассылки .

Код ниже работает. Кажется, дьявол кроется в деталях того, как вызывается Range (): Range(my_slider_low, my_slider_hi, 0.1) делает не работает.

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider_low = 0.0
    my_slider_hi = 1.0

    my_slider = Range(low='my_slider_low', high='my_slider_hi', value=0.1)  

    def __init__(self, arg1):
        self.my_slider_hi = arg1 

    view = View( Item('my_slider') )

top_range = 0.2

my_gui = GUIThing(top_range)
my_gui.configure_traits()
0 голосов
/ 03 февраля 2015

Я обрезал хороший пример динамического диапазона от Джонатана Марча. Это дает все поведение, которое ОП хочет АФАКТ:

# Imports:
from traits.api import HasPrivateTraits, Float, Range, Int

from traitsui.api import View, Group, Item, Label, RangeEditor

class DynamicRangeEditor ( HasPrivateTraits ):
    """ Defines an editor for dynamic ranges (i.e. ranges whose bounds can be
        changed at run time).
    """

    # The value with the dynamic range:
    value = Float

    # This determines the low end of the range:
    low = Float(0.0)

    # This determines the high end of the range:
    high = Float(50)

    # Traits view definitions:
    traits_view = View(

        # Dynamic simple slider demo:
        Group(
            Item( 'value',
                   editor = RangeEditor( low_name    = 'low',
                                         high_name   = 'high',
                                         format      = '%.1f',
                                         label_width = 28,
                                         mode        = 'auto' )
            ),
            '_',
            Item( 'low' ),
            Item( 'high' ),
            '_',
        ),

        title     = 'Dynamic Range Editor Demonstration',
        buttons   = [ 'OK' ],
        resizable = True
    )


# Create the demo:
demo = DynamicRangeEditor()

# Run the demo (if invoked from the command line):
if __name__ == '__main__':
    demo.configure_traits()
0 голосов
/ 03 мая 2012

На самом деле проблема в ответе Птеридиума.Это работает, но нарушает два правила / рекомендации.

Во-первых, вы перезаписали конструктор своим собственным init .Если вы сделаете это (и если этого нельзя избежать, не следуйте рекомендациям по кодированию для черт), вы должны вызвать родительский конструктор с помощью чего-то вроде super (GUISlider, self). init (self, ** kwargs)

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

from enthought.traits.api import HasTraits, Range
from enthought.traits.ui.api import View, Item

class GUIThing(HasTraits):

    my_slider_low = 0.0
    my_slider_hi = 1.0

    my_slider = Range(low='my_slider_low', high='my_slider_hi', value=0.1)  

    view = View( Item('my_slider') )


my_gui = GUIThing(my_slider_hi=0.4)
my_gui.configure_traits()

Итак, вы делаете, что хотите (я думаю), меньше кода и следует за чертами.Если кто-то может объяснить, почему мы не должны использовать конструкторы, я хотел бы знать.Роберт Керн, вероятно, может сказать нам.

0 голосов
/ 31 марта 2012

Вам необходимо использовать метод add_trait, который позволит вам динамически создавать новые характеристики Range с нужными вам значениями.

Это взято с Расширенной страницы руководства пользователя черт

from traits.api import HasTraits, Range

class GUISlider (HasTraits):

def __init__(self, eval=None, label='Value',
             trait=None, min=0.0, max=1.0,
             initial=None, **traits):
    HasTraits.__init__(self, **traits)
    if trait is None:
        if min > max:
            min, max = max, min
        if initial is None:
            initial = min
        elif not (min <= initial <= max):
            initial = [min, max][
                        abs(initial - min) >
                        abs(initial - max)]
        trait = Range(min, max, value = initial)
    self.add_trait(label, trait)
0 голосов
/ 31 марта 2012

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

...