意外的整数 RangeEditor
Unexpected RangeEditor for Integers
看来 RangeEditor 天生就期待浮动特征。以下示例脚本说明了该行为。有没有更简洁的方法来为整数特征指定 RangeEditor?
import sys
print (sys.version) # '3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)]'
from traits import __version__
print (__version__) # '4.6.0.dev0'
from traits.api import HasTraits, Int, Range
from traitsui.api import Item, RangeEditor, View
class Exposure (HasTraits):
duration = Range (low=0.0, high=3600.0, exclude_low=True , exclude_high=False, editor=RangeEditor(mode='slider'))
min_count = Int ( 1)
max_count = Int (10000)
#<1>count = Range (low=1 , high=10000 , exclude_low=False, exclude_high=False, editor=RangeEditor(mode='slider'))
count = Range (low=1 , high=10000 , exclude_low=False, exclude_high=False, editor=RangeEditor(mode='slider', low_name='min_count', high_name='max_count'))
traits_view = View (Item('duration'), Item('count'), buttons=['OK', 'Cancel'])
exposure = Exposure (duration = 0.00032, count=1500)
exposure.configure_traits()
# Specifying `count` as per <1>, above, raises the following exception:
# traits.trait_errors.TraitError: The 'count' trait of an Exposure instance must be 1 <= a long integer <= 10000, but a value of 1.0 <class 'float'> was specified.
#
# A work-around is to declare min_count and max_count, and include them in the
# RangeEditor definition of `count`. Note, I am now duplicating `count` low and
# high limits in 2 places. Is there a better approach?
A RangeEditor
确实默认返回 float
值,除非您通过将 high
或 low
参数设置为 int
值来覆盖默认值. Range
特征的 low
和 high
参数不会传递给特征的默认编辑器 (see the source here),因此您必须单独设置它们。 (从源头上应该可以看出为什么使用 low_name
和 high_name
确实 有效。)IIUC,这是从它的角度来看有意将特征解耦,但是如果您认为行为应该有所不同,欢迎您在 Traits 中提出问题进行讨论。
可能有助于阐明您的代码的一件事是将模型和视图的定义分开。在特征定义中指定编辑器很容易混淆 w.r.t。特征的参数与其视图。如果值的约束是 Exposure
模型固有的,请使用 Range
,否则只需使用基础特征类型。单独定义视图可以让你的代码更清晰:哪些约束属于模型,哪些属于视图。另外,如果你想定义第二个具有不同约束的视图,这样做也没问题。
以下是我建议重写代码的方法:
from traits.api import HasTraits, Int, Range
from traitsui.api import Item, RangeEditor, View
class Exposure (HasTraits):
duration = Range (low=0.0, high=3600.0, exclude_low=True , exclude_high=False)
count = Int( 1500)
my_view = View(
Item('duration', editor=RangeEditor(mode='slider')),
Item('count', editor=RangeEditor(low=1, high=10000, mode='slider')),
buttons=['OK', 'Cancel']
)
exposure = Exposure (duration = 0.00032, count=1500)
exposure.configure_traits(view=my_view)
看来 RangeEditor 天生就期待浮动特征。以下示例脚本说明了该行为。有没有更简洁的方法来为整数特征指定 RangeEditor?
import sys
print (sys.version) # '3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)]'
from traits import __version__
print (__version__) # '4.6.0.dev0'
from traits.api import HasTraits, Int, Range
from traitsui.api import Item, RangeEditor, View
class Exposure (HasTraits):
duration = Range (low=0.0, high=3600.0, exclude_low=True , exclude_high=False, editor=RangeEditor(mode='slider'))
min_count = Int ( 1)
max_count = Int (10000)
#<1>count = Range (low=1 , high=10000 , exclude_low=False, exclude_high=False, editor=RangeEditor(mode='slider'))
count = Range (low=1 , high=10000 , exclude_low=False, exclude_high=False, editor=RangeEditor(mode='slider', low_name='min_count', high_name='max_count'))
traits_view = View (Item('duration'), Item('count'), buttons=['OK', 'Cancel'])
exposure = Exposure (duration = 0.00032, count=1500)
exposure.configure_traits()
# Specifying `count` as per <1>, above, raises the following exception:
# traits.trait_errors.TraitError: The 'count' trait of an Exposure instance must be 1 <= a long integer <= 10000, but a value of 1.0 <class 'float'> was specified.
#
# A work-around is to declare min_count and max_count, and include them in the
# RangeEditor definition of `count`. Note, I am now duplicating `count` low and
# high limits in 2 places. Is there a better approach?
A RangeEditor
确实默认返回 float
值,除非您通过将 high
或 low
参数设置为 int
值来覆盖默认值. Range
特征的 low
和 high
参数不会传递给特征的默认编辑器 (see the source here),因此您必须单独设置它们。 (从源头上应该可以看出为什么使用 low_name
和 high_name
确实 有效。)IIUC,这是从它的角度来看有意将特征解耦,但是如果您认为行为应该有所不同,欢迎您在 Traits 中提出问题进行讨论。
可能有助于阐明您的代码的一件事是将模型和视图的定义分开。在特征定义中指定编辑器很容易混淆 w.r.t。特征的参数与其视图。如果值的约束是 Exposure
模型固有的,请使用 Range
,否则只需使用基础特征类型。单独定义视图可以让你的代码更清晰:哪些约束属于模型,哪些属于视图。另外,如果你想定义第二个具有不同约束的视图,这样做也没问题。
以下是我建议重写代码的方法:
from traits.api import HasTraits, Int, Range
from traitsui.api import Item, RangeEditor, View
class Exposure (HasTraits):
duration = Range (low=0.0, high=3600.0, exclude_low=True , exclude_high=False)
count = Int( 1500)
my_view = View(
Item('duration', editor=RangeEditor(mode='slider')),
Item('count', editor=RangeEditor(low=1, high=10000, mode='slider')),
buttons=['OK', 'Cancel']
)
exposure = Exposure (duration = 0.00032, count=1500)
exposure.configure_traits(view=my_view)