2012-03-31 21 views
5

Tôi mới dùng python - xin lỗi nếu thuật ngữ của tôi sai. Tôi có một lớp kế thừa Enthought Traits attributes. Đây là một phiên bản đơn giản:Thay đổi thông số thuộc tính từ bên trong lớp khởi tạo [Python/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() 

này chỉ đơn giản là tạo ra một cửa sổ với một slider trong nó, ban đầu sẽ 0,0-0,6 với giá trị ban đầu 0.1. Khi tạo một thể hiện GUIThing, tôi muốn thay đổi giá trị tối đa cho thanh trượt tùy thuộc vào giá trị top_range hiện tại. Tuy nhiên dòng

self.my_slider._high = arg1

kết quả trong

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

Khi trong __init__(), self.my_slider lợi nhuận không phải là đối tượng thanh trượt, nhưng giá trị hiện tại của thanh trượt.

Tôi đang làm gì sai? Cảm ơn!

Edit:

Sau đây cũng không hoạt động:

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

Đó sẽ là cách trực tiếp để làm những gì tôi đang cố gắng để làm, nhưng nó kết quả trong một giao diện nơi thay vì một thanh trượt, có một hộp văn bản đọc "enthought.traits.trait_types.Range đối tượng tại 0xa61946c". Vì vậy, vấn đề là khi my_slider được tạo trong phạm vi __init__() thì "my_slider" có nghĩa là đối tượng chính nó (không hiển thị chính xác qua Chế độ xem); nhưng nếu my_slider được tạo bên ngoài __init__() thì "my_slider" có nghĩa là giá trị hiện tại (một phao; ngăn chặn quyền truy cập vào thuộc tính đối tượng).

Không chắc chắn điều này có đặc thù đối với Đặc điểm hay không, tôi không biết cách khởi tạo đối tượng đúng cách.

+3

Nói chung, gạch tiền tố trong ' '_high'' ngụ ý rằng nó là tư nhân và bạn không nên được truy cập nó như thế. –

+0

Phải, cảm ơn. Nhưng tôi không thể tìm thấy trong tài liệu như thế nào người ta sẽ truy cập nó thay vào đó. Và ngay cả khi nó không phải là cách thích hợp - nó hoạt động bên ngoài '__init__'. Vì vậy, tôi không hiểu tại sao nó khác * trong * '__init__' (cũng xem chỉnh sửa thành OP). – Pteridium

+0

Đoán của tôi (tôi không quen thuộc với thư viện) là '' __init __() '' của siêu lớp sử dụng '' Phạm vi'', nhưng không giữ tham chiếu đến nó. Nếu điều đó đúng, bạn đã thử đặt dòng '' self.my_slider = Range (0.0, arg1, 0.0) '' trước '' HasTraits .__ init __ (self) '' trong '' __init __() ''? –

Trả lời

0

Cảm giác Gut của tôi là bạn không cần phải sửa đổi lớp đó mà là mở rộng lớp Range và thêm logic bổ sung mà bạn cần để xử lý trường hợp cụ thể của bạn.

+0

Cảm ơn, một vấn đề là tôi không thể tìm thấy cách Range hoạt động nội bộ; nó không thực sự có vẻ là một lớp học mà là một chức năng/'định nghĩa kiểu' ... xem [ở đây] (http://code.enthought.com/projects/files/ets_api/enthought.traits.traits.html)? Tôi bối rối. – Pteridium

+0

nah, không cần phải gây rối với Range - nó có tất cả các chức năng theo yêu cầu của OP – DrSAR

0

Bạn cần sử dụng phương thức add_trait để cho phép bạn tạo các đặc điểm Phạm vi động mới với các giá trị bạn cần.

này được lấy từ các 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

Cảm ơn! Tôi đã không nhận ra điều đó. Và có, nó hoạt động, nếu ta thêm 'view = View (Item ('Value'))' vào lớp. Điều đó sẽ không làm nếu bạn muốn tạo nhiều GUISliders với các nhãn khác nhau. – Pteridium

4

Cuối cùng tìm thấy câu trả lời trong a recent mailing list message.

Mã bên dưới hoạt động. Dường như ma quỷ có chi tiết về cách Range() được gọi là: Range(my_slider_low, my_slider_hi, 0.1) không không hoạt động.

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

Thực sự có vấn đề trong câu trả lời của Pteridium. Nó hoạt động nhưng phá vỡ hai quy tắc/khuyến nghị.

Trước tiên, bạn đã ghi đè hàm tạo bằng init của riêng bạn.Nếu bạn làm điều đó (và nếu tránh được bạn không nên theo các khuyến nghị mã hóa cho các đặc điểm), bạn nên gọi hàm tạo con cái với một cái gì đó như siêu (GUISlider, self). init (tự, ** kwargs)

Thứ hai, việc khởi tạo đề xuất cho trẻ em HasTraits được thực hiện trong quá trình khởi tạo trong hàm tạo đối số từ khóa. Trong trường hợp của bạn, mã có thể giống như

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

Có bạn đi, làm những gì bạn muốn (tôi nghĩ), ít mã hơn và tuân theo các đặc điểm. Nếu ai đó có thể giải thích tại sao chúng ta không nên sử dụng các nhà thầu mà tôi muốn biết. Robert Kern có thể nói với chúng tôi.

+0

Điều này không hiệu quả đối với tôi, thanh trượt luôn hiển thị giá trị ban đầu 1.0 – kezzos

0

, tôi đã cắt xuống một ví dụ tốt đẹp của một dynamic range from Jonathan March. Điều này cho phép tất cả các hành vi mà OP muốn 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() 
Các vấn đề liên quan