python kivy uix widget类与"隐藏"方法或属性?

时间:2017-02-23 01:40:24

标签: python user-interface widget kivy

kivy包含的小部件类是否有隐藏方法?我已经使用kivy几个月了解大多数事情,比如默认图册,绑定和kivy属性。

我的问题源于我尝试更改kivy.uix.slider.Slider小部件的光标图像失败。首先,文档说明应该有#34; cursor_image"等字符串属性。和" background_vertical"这指向默认的地图集。安装的版本在类上甚至没有这些属性。我去了github并得到了滑块类。这确实有属性,所以我试着改变它们,没有运气;它看起来仍然一样。事情变得陌生。如果我只是将类从Slider重命名为MySlider,则小部件甚至不会渲染!

下面是从github粘贴的代码,其中类名已更改。如果您在类中将名称更改回Slider并将其分配给root,则可以正常工作。如果我编辑默认的图集图像,这将改变外观,告诉我Slider类总是指向它。另外你会注意到类中没有使用atlas字符串属性,告诉我kivy在某种程度上使用一些默认值在运行时组装这个小部件的可见部分。我已经浏览了小部件的API而一无所获。知道发生了什么吗?

from kivy.base import runTouchApp

"""
Slider
======
.. image:: images/slider.jpg
The :class:`Slider` widget looks like a scrollbar. It supports horizontal and
vertical orientations, min/max values and a default value.
To create a slider from -100 to 100 starting from 25::
    from kivy.uix.slider import Slider
    s = Slider(min=-100, max=100, value=25)
To create a vertical slider::
    from kivy.uix.slider import Slider
    s = Slider(orientation='vertical')
To create a slider with a red line tracking the value::
    from kivy.uix.slider import Slider
    s = Slider(value_track=True, value_track_color=[1, 0, 0, 1])
"""
__all__ = ('Slider', )

from kivy.uix.widget import Widget
from kivy.properties import (NumericProperty, AliasProperty, OptionProperty,
                             ReferenceListProperty, BoundedNumericProperty,
                             StringProperty, ListProperty, BooleanProperty)


class MySlider(Widget):
    """Class for creating a Slider widget.
    Check module documentation for more details.
    """

    value = NumericProperty(0.)
    '''Current value used for the slider.
    :attr:`value` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 0.'''

    min = NumericProperty(0.)
    '''Minimum value allowed for :attr:`value`.
    :attr:`min` is a :class:`~kivy.properties.NumericProperty` and defaults to
    0.'''

    max = NumericProperty(100.)
    '''Maximum value allowed for :attr:`value`.
    :attr:`max` is a :class:`~kivy.properties.NumericProperty` and defaults to
    100.'''

    padding = NumericProperty('16sp')
    '''Padding of the slider. The padding is used for graphical representation
    and interaction. It prevents the cursor from going out of the bounds of the
    slider bounding box.
    By default, padding is 16sp. The range of the slider is reduced from
    padding \*2 on the screen. It allows drawing the default cursor of 32sp
    width without having the cursor go out of the widget.
    :attr:`padding` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 16sp.'''

    orientation = OptionProperty('horizontal', options=(
        'vertical', 'horizontal'))
    '''Orientation of the slider.
    :attr:`orientation` is an :class:`~kivy.properties.OptionProperty` and
    defaults to 'horizontal'. Can take a value of 'vertical' or 'horizontal'.
    '''

    range = ReferenceListProperty(min, max)
    '''Range of the slider in the format (minimum value, maximum value)::
        >>> slider = Slider(min=10, max=80)
        >>> slider.range
        [10, 80]
        >>> slider.range = (20, 100)
        >>> slider.min
        20
        >>> slider.max
        100
    :attr:`range` is a :class:`~kivy.properties.ReferenceListProperty` of
    (:attr:`min`, :attr:`max`) properties.
    '''

    step = BoundedNumericProperty(0, min=0)
    '''Step size of the slider.
    .. versionadded:: 1.4.0
    Determines the size of each interval or step the slider takes between
    min and max. If the value range can't be evenly divisible by step the
    last step will be capped by slider.max
    :attr:`step` is a :class:`~kivy.properties.NumericProperty` and defaults
    to 1.'''

    background_horizontal = StringProperty(
        'atlas://data/images/defaulttheme/sliderh_background')
    """Background of the slider used in the horizontal orientation.
    .. versionadded:: 1.10.0
    :attr:`background_horizontal` is a :class:`~kivy.properties.StringProperty`
    and defaults to `atlas://data/images/defaulttheme/sliderh_background`.
    """

    background_disabled_horizontal = StringProperty(
        'atlas://data/images/defaulttheme/sliderh_background_disabled')
    """Background of the disabled slider used in the horizontal orientation.
    .. versionadded:: 1.10.0
    :attr:`background_disabled_horizontal` is a
    :class:`~kivy.properties.StringProperty` and defaults to
    `atlas://data/images/defaulttheme/sliderh_background_disabled`.
    """

    background_vertical = StringProperty(
        'atlas://data/images/defaulttheme/sliderv_background')
    """Background of the slider used in the vertical orientation.
    .. versionadded:: 1.10.0
    :attr:`background_vertical` is a :class:`~kivy.properties.StringProperty`
    and defaults to `atlas://data/images/defaulttheme/sliderv_background`.
    """

    background_disabled_vertical = StringProperty(
        'atlas://data/images/defaulttheme/sliderv_background_disabled')
    """Background of the disabled slider used in the vertical orientation.
    .. versionadded:: 1.10.0
    :attr:`background_disabled_vertical` is a
    :class:`~kivy.properties.StringProperty` and defaults to
    `atlas://data/images/defaulttheme/sliderv_background_disabled`.
    """

    background_width = NumericProperty('36sp')
    """Slider's background's width (thickness), used in both horizontal
    and vertical orientations.
    .. versionadded 1.10.0
    :attr:`background_width` is a
    :class:`~kivy.properties.NumericProperty` and defaults to 36sp.
    """

    cursor_image = StringProperty(
        'atlas://data/images/defaulttheme/slider_cursor')
    """Path of the image used to draw the slider cursor.
    .. versionadded 1.10.0
    :attr:`cursor_image` is a :class:`~kivy.properties.StringProperty`
    and defaults to `atlas://data/images/defaulttheme/slider_cursor`.
    """

    cursor_disabled_image = StringProperty(
        'atlas://data/images/defaulttheme/slider_cursor_disabled')
    """Path of the image used to draw the disabled slider cursor.
    .. versionadded 1.10.0
    :attr:`cursor_image` is a :class:`~kivy.properties.StringProperty`
    and defaults to `atlas://data/images/defaulttheme/slider_cursor_disabled`.
    """

    cursor_width = NumericProperty('32sp')
    """Width of the cursor image.
    .. versionadded 1.10.0
    :attr:`cursor_width` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 32sp.
    """

    cursor_height = NumericProperty('32sp')
    """Height of the cursor image.
    .. versionadded 1.10.0
    :attr:`cursor_height` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 32sp.
    """

    cursor_size = ReferenceListProperty(cursor_width, cursor_height)
    """Size of the cursor image.
    .. versionadded 1.10.0
    :attr:`cursor_size` is a :class:`~kivy.properties.ReferenceListProperty`
    of (:attr:`cursor_width`, :attr:`cursor_height`) properties.
    """

    border_horizontal = ListProperty([0, 18, 0, 18])
    """Border used to draw the slider background in horizontal orientation.
    .. versionadded 1.10.0
    :attr:`border_horizontal` is a :class:`~kivy.properties.ListProperty`
    and defaults to [0, 18, 0, 18].
    """

    border_vertical = ListProperty([18, 0, 18, 0])
    """Border used to draw the slider background in vertical orientation.
    .. versionadded 1.10.0
    :attr:`border_horizontal` is a :class:`~kivy.properties.ListProperty`
    and defaults to [18, 0, 18, 0].
    """

    value_track = BooleanProperty(False)
    """Decides if slider should draw the line indicating the
    space between :attr:`min` and :attr:`value` properties values.
    .. versionadded 1.10.0
    :attr:`value_track` is a :class:`~kivy.properties.BooleanProperty`
    and defaults to False.
    """

    value_track_color = ListProperty([1, 1, 1, 1])
    """Color of the :attr:`value_line` in rgba format.
    .. versionadded 1.10.0
    :attr:`value_track_color` is a :class:`~kivy.properties.ListProperty`
    and defaults to [1, 1, 1, 1].
    """

    value_track_width = NumericProperty('3dp')
    """Width of the track line.
    .. versionadded 1.10.0
    :attr:`value_track_width` is a :class:`~kivy.properties.NumericProperty`
    and defaults to 3dp.
    """

    # The following two methods constrain the slider's value
    # to range(min,max). Otherwise it may happen that self.value < self.min
    # at init.

    def on_min(self, *largs):
        self.value = min(self.max, max(self.min, self.value))

    def on_max(self, *largs):
        self.value = min(self.max, max(self.min, self.value))

    def get_norm_value(self):
        vmin = self.min
        d = self.max - vmin
        if d == 0:
            return 0
        return (self.value - vmin) / float(d)

    def set_norm_value(self, value):
        vmin = self.min
        vmax = self.max
        step = self.step
        val = min(value * (vmax - vmin) + vmin, vmax)
        if step == 0:
            self.value = val
        else:
            self.value = min(round((val - vmin) / step) * step + vmin,
                             vmax)
    value_normalized = AliasProperty(get_norm_value, set_norm_value,
                                     bind=('value', 'min', 'max', 'step'))
    '''Normalized value inside the :attr:`range` (min/max) to 0-1 range::
        >>> slider = Slider(value=50, min=0, max=100)
        >>> slider.value
        50
        >>> slider.value_normalized
        0.5
        >>> slider.value = 0
        >>> slider.value_normalized
        0
        >>> slider.value = 100
        >>> slider.value_normalized
        1
    You can also use it for setting the real value without knowing the minimum
    and maximum::
        >>> slider = Slider(min=0, max=200)
        >>> slider.value_normalized = .5
        >>> slider.value
        100
        >>> slider.value_normalized = 1.
        >>> slider.value
        200
    :attr:`value_normalized` is an :class:`~kivy.properties.AliasProperty`.
    '''

    def get_value_pos(self):
        padding = self.padding
        x = self.x
        y = self.y
        nval = self.value_normalized
        if self.orientation == 'horizontal':
            return (x + padding + nval * (self.width - 2 * padding), y)
        else:
            return (x, y + padding + nval * (self.height - 2 * padding))

    def set_value_pos(self, pos):
        padding = self.padding
        x = min(self.right - padding, max(pos[0], self.x + padding))
        y = min(self.top - padding, max(pos[1], self.y + padding))
        if self.orientation == 'horizontal':
            if self.width == 0:
                self.value_normalized = 0
            else:
                self.value_normalized = (x - self.x - padding
                                         ) / float(self.width - 2 * padding)
        else:
            if self.height == 0:
                self.value_normalized = 0
            else:
                self.value_normalized = (y - self.y - padding
                                         ) / float(self.height - 2 * padding)
    value_pos = AliasProperty(get_value_pos, set_value_pos,
                              bind=('x', 'y', 'width', 'height', 'min',
                                    'max', 'value_normalized', 'orientation'))
    '''Position of the internal cursor, based on the normalized value.
    :attr:`value_pos` is an :class:`~kivy.properties.AliasProperty`.
    '''

    def on_touch_down(self, touch):
        if self.disabled or not self.collide_point(*touch.pos):
            return
        if touch.is_mouse_scrolling:
            if 'down' in touch.button or 'left' in touch.button:
                if self.step:
                    self.value = min(self.max, self.value + self.step)
                else:
                    self.value = min(
                        self.max,
                        self.value + (self.max - self.min) / 20)
            if 'up' in touch.button or 'right' in touch.button:
                if self.step:
                    self.value = max(self.min, self.value - self.step)
                else:
                    self.value = max(
                        self.min,
                        self.value - (self.max - self.min) / 20)
        else:
            touch.grab(self)
            self.value_pos = touch.pos
        return True

    def on_touch_move(self, touch):
        if touch.grab_current == self:
            self.value_pos = touch.pos
            return True

    def on_touch_up(self, touch):
        if touch.grab_current == self:
            self.value_pos = touch.pos
            return True

root = MySlider(orientation='vertical')

runTouchApp(root)

1 个答案:

答案 0 :(得分:0)

我发现了kivy“魔法”发生的地方。小部件确实有基于类名设置的绑定和图像,kivy / data /目录中的style.kv文件是Slider类的片段

<Slider>:
    canvas:
        Color:
            rgb: 1, 1, 1
        BorderImage:
            border: (0, 18, 0, 18) if self.orientation == 'horizontal' else (18, 0, 18, 0)
            pos: (self.x + self.padding, self.center_y - sp(18)) if self.orientation == 'horizontal' else (self.center_x - 18, self.y + self.padding)
            size: (self.width - self.padding * 2, sp(36)) if self.orientation == 'horizontal' else (sp(36), self.height - self.padding * 2)
            source: 'atlas://data/images/defaulttheme/slider{}_background{}'.format(self.orientation[0], '_disabled' if self.disabled else '')
        Rectangle:
            pos: (self.value_pos[0] - sp(16), self.center_y - sp(17)) if self.orientation == 'horizontal' else (self.center_x - (16), self.value_pos[1] - sp(16))
            size: (sp(32), sp(32))
            source: 'atlas://data/images/defaulttheme/slider_cursor{}'.format('_disabled' if self.disabled else '') 

有趣的是,在已安装的kivy版本(1.9.1)中,Slider类没有atlas属性。 github上的版本声称这些版本是在1.10.0版本中添加的,但我认为github上的主版本是1.9.2,所以我很困惑。看着我能够改变的课程(按钮),我看到了不同之处。您会注意到,在下面的style.kv文件的片段中,该文件使用kivy属性来设置state_image。

<-Button,-ToggleButton>:
    state_image: self.background_normal if self.state == 'normal' else self.background_down
    disabled_image: self.background_disabled_normal if self.state == 'normal' else self.background_disabled_down
    canvas:
        Color:
            rgba: self.background_color
        BorderImage:
            border: self.border
            pos: self.pos
            size: self.size
            source: self.disabled_image if self.disabled else self.state_image
        Color:
            rgba: self.disabled_color if self.disabled else self.color
        Rectangle:
            texture: self.texture
            size: self.texture_size
            pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.)

我检查了build.kv的主版本,并且滑块已更新为使用属性,并且可以作为API文档状态使用。我希望这会有所帮助。