2012-03-31 17 views
5

Sono nuovo in Python - scusa se la mia terminologia è errata. Ho una classe che eredita lo Enthought Traits attributes. Ecco una versione semplificata:Modifica parametro proprietà dal costruttore della classe [Python/Tratti]

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

Questo crea semplicemente una finestra con una slider in esso, originariamente intenzione 0,0-0,6 con valore iniziale 0,1. Quando si crea un'istanza di GUIThing, voglio variare il valore massimo per il cursore in base al valore corrente di top_range. Tuttavia la linea

self.my_slider._high = arg1

risultati in

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

Quando all'interno __init__(), self.my_slider rendimenti non dell'oggetto cursore, ma il valore corrente del cursore.

Cosa sto sbagliando? Grazie!

Edit:

seguito anche non funziona:

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

Questo sarebbe il modo diretto di fare quello che sto cercando di fare, ma si traduce in una GUI in cui invece di un cursore, c'è una casella di testo che legge "enthought.traits.trait_types.oggetto Ranger a 0xa61946c". Quindi il problema è che quando my_slider viene creato all'interno di __init__() allora "my_slider" diventa l'oggetto stesso (che non viene visualizzato correttamente tramite Visualizza); ma se my_slider viene creato al di fuori di __init__() allora "my_slider" diventa il valore corrente (un valore float che impedisce l'accesso alle proprietà dell'oggetto).

Non so se questo è peculiare di Tratti o semplicemente non so come inizializzare correttamente gli oggetti.

+3

In generale, la sottolineatura prefisso in '' _high'' implica che è privato e non si deve accedervi in ​​questo modo. –

+0

Giusto, grazie. Ma non riesco a trovare nei documenti come si potrebbe invece accedervi. E anche se non è il modo corretto - funziona al di fuori di '__init__'. Quindi non capisco perché è diverso * all'interno di * '__init__' (vedi anche modifica su OP). – Pteridium

+0

La mia ipotesi (non ho familiarità con la libreria) è che il '' __init __() '' della superclasse usa '' Range'', ma non mantiene alcun riferimento ad esso. Se ciò è vero, hai provato a mettere la riga '' self.my_slider = Range (0.0, arg1, 0.0) '' prima di '' HasTraits .__ init __ (self) '' all'interno di '' __init __() ''? –

risposta

0

My Gut Feeling è che non è necessario modificare quella classe, ma piuttosto estendere la classe Range e aggiungere la logica aggiuntiva necessaria per gestire il caso specifico.

+0

Grazie, un problema è che non riesco a trovare il modo in cui Range funziona internamente; in realtà non sembra essere una classe, ma piuttosto una funzione/'definizione del tipo' ... vedi [qui] (http://code.enthought.com/projects/files/ets_api/enthought.traits.traits.html)? Non ho capito bene. – Pteridium

+0

nah, non c'è bisogno di scherzare con Range - ha tutte le funzionalità richieste dall'OP – DrSAR

0

È necessario utilizzare il metodo add_trait che consente di creare dinamicamente nuovi tratti di intervallo con i valori necessari.

questo è preso dalla Advanced page of the traits user manual

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

Grazie! Non l'avevo notato. E sì, funziona, se si aggiunge 'view = View (Item ('Value'))' alla classe. Questo non succederebbe se volessi creare più GUISlider con etichette diverse. – Pteridium

4

finalmente trovato la risposta nella a recent mailing list message.

Il codice seguente funziona. Sembra che il diavolo sia nei dettagli di come viene chiamato Range(): Range(my_slider_low, my_slider_hi, 0.1) fa non lavoro.

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

C'è in realtà un problema nella risposta di Pteridium. Funziona ma rompe due regole/raccomandazioni.

In primo luogo, il costruttore è stato sovrascritto con il proprio init.Se lo fai (e se evitabile non dovresti seguire le raccomandazioni di codifica per i Tratti), dovresti chiamare il costruttore genitore con qualcosa come super (GUISlider, self). init (self, ** kwargs)

In secondo luogo, l'inizializzazione consigliata per i bambini HasTraits viene eseguita durante l'istanziazione nel costruttore che accetta gli argomenti delle parole chiave. Nel tuo caso il codice potrebbe essere come

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

Lì vai, fa quello che vuoi (credo), meno codice e segue i Tratti. Se qualcuno può spiegare perché non dovremmo usare costruttori mi piacerebbe sapere. Probabilmente Robert Kern potrebbe dircelo.

+0

Questo non ha funzionato per me, il cursore mostra sempre il valore iniziale 1.0 – kezzos

0

ho potato giù un bel esempio di dynamic range from Jonathan March. questo dà tutto il comportamento che il PO vuole AFAICT:

# 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() 
Problemi correlati