首页 > 解决方案 > Kivy 将值传递给进度条

问题描述

该代码正在运行,但我想从一个函数(使用 Raspberrypi GPIO 引脚获取传感器值)中传递值来获取该值,而不是此代码中使用的滑块,但我不知道如何实现它。你能帮我么。

我从这里引用了这段代码https://github.com/olivier-boesch/garden.imageprogressbar/blob/master/imageprogressbar.py

from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.properties import OptionProperty, StringProperty, ObjectProperty, ListProperty, AliasProperty, \
    BooleanProperty, NumericProperty
from kivy.lang.builder import Builder
from kivy.clock import Clock


# kv info for ImageProgressBar
kvstr = """
<CroppedImage>
    canvas.before:
        StencilPush
        Rectangle:
            pos: self.rectangle_pos
            size: self.rectangle_size
        StencilUse
    
    canvas.after:
        StencilUnUse
        Rectangle:
            pos: self.rectangle_pos
            size: self.rectangle_size
        StencilPop

<ImageProgressBar>
    Image:
        id: background_progress_image
        source: root.source_progress if root.draw_progress_background else None
        color : root.color_progress_background if root.draw_progress_background else [0,0,0,0]
        pos: root.pos
        size: root.size
        allow_stretch: True
    CroppedImage:
        id: progress_image
        source: root.source_progress
        color: root.color_progress
        pos: root.pos
        size: root.size
        allow_stretch: True
    Image:
        id: front_image
        color: root.color_front
        source: root.source_front
        pos: root.pos
        size: root.size
        allow_stretch: True 
    Label:
        id: text_lbl
        pos: root.pos
        size: root.size
        
"""


class CroppedImage(Image):
    """CroppedImage : Image widget where texture can be cropped with Stencil Instructions"""
    # position and size of the stencil mask (internal use)
    rectangle_pos = ListProperty([0.1, 0.7])
    rectangle_size = ListProperty([0, 0])
    # direction of cropping (bt -> bottom to top, lr -> left to right, ...)
    direction = OptionProperty('bt', options=['bt', 'tb', 'lr', 'rl'])
    # visible percentage of the image [0,100]
    visible_percent = NumericProperty(0)
    # minimum position of the portion of the image corresponding to 0% and length of 0% to 100% (in pixel of the image file)
    min_pos = NumericProperty(0)
    max_length = NumericProperty(100)

    def on_visible_percent(self, inst, val):
        self.update_view()

    def update_view(self):
        """update_view : update the pos and size of the rectangle stencil mask"""
        if self.texture:
            # get how image is resized (zoom factor)
            zoom_ratio = self.norm_image_size[1] / float(self.texture.size[1])
            # where going from bottom (0%) to top (100%)
            if self.direction == 'bt':
                self.rectangle_pos = self.center_x - self.norm_image_size[0] / 2., self.center_y - self.norm_image_size[
                    1] / 2.
                self.rectangle_size = self.norm_image_size[0], (
                            self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio
            # where going from top (0%) to bottom (100%)
            elif self.direction == 'tb':
                self.rectangle_pos = self.center_x - self.norm_image_size[0] / 2., (
                            self.center_y + self.norm_image_size[1] / 2.) - (
                                                 self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio
                self.rectangle_size = self.norm_image_size[0], (
                            self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio
            # where going from left (0%) to right (100%)
            elif self.direction == 'lr':
                self.rectangle_pos = self.center_x - self.norm_image_size[0] / 2., self.center_y - self.norm_image_size[
                    1] / 2.
                self.rectangle_size = (self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio, \
                                      self.norm_image_size[1]
            # where going from right (0%) to left (100%)
            elif self.direction == 'rl':
                self.rectangle_pos = (self.center_x + self.norm_image_size[0] / 2.) - (
                            self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio, self.center_y - \
                                     self.norm_image_size[1] / 2.
                self.rectangle_size = (self.min_pos + self.max_length * self.visible_percent / 100.0) * zoom_ratio, \
                                      self.norm_image_size[1]

    def on_direction(self, inst, val):
        self.update_view()

    def on_size(self, inst, val):
        self.update_view()

    def on_pos(self, inst, val):
        self.update_view()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)


class ImageProgressBar(FloatLayout):
    # Images Properties
    source_front = StringProperty(None)
    color_front = ListProperty([1, 1, 1, 1])
    source_progress = StringProperty(None)
    color_progress = ListProperty([0.196, 0.643, 0.808, 1])
    draw_progress_background = BooleanProperty(False)
    color_progress_background = ListProperty([0.035, 0.118, 0.149, 1])
    min_pos = NumericProperty(0)
    max_length = NumericProperty(0)
    value = NumericProperty(0)
    direction = OptionProperty('rl', options=['bt', 'tb', 'lr', 'rl'])
    text_auto = BooleanProperty(True)
    text = StringProperty('')

    def get_text_label(self):
        return self.ids['text_lbl']

    def on_text(self, inst, val):
        if self.text_auto:
            self.ids['text_lbl'].text = '%d %%' % (val,)
        else:
            self.ids['text_lbl'].text = self.text

    def on_text_auto(self, inst, val):
        self.ids['progress_image'].update_view()
        if self.text_auto:
            self.ids['text_lbl'].text = '%d %%' % (val,)
        else:
            self.ids['text_lbl'].text = self.text

    def on_value(self, inst, val):
        self.ids['progress_image'].visible_percent = val
        if self.text_auto:
            self.ids['text_lbl'].text = '%d %%' % (val,)
        else:
            self.ids['text_lbl'].text = self.text

    def on_direction(self, inst, val):
        self.ids['progress_image'].direction = val

    def on_min_pos(self, inst, val):
        self.ids['progress_image'].min_pos = val

    def on_max_length(self, inst, val):
        self.ids['progress_image'].max_length = val

    def first_update(self):
        self.ids['progress_image'].update_view()
        if self.text_auto:
            self.ids['text_lbl'].text = '%d %%' % (self.value,)
        else:
            self.ids['text_lbl'].text = self.text

    def __init__(self, **kwargs):
        Builder.load_string(kvstr)
        super().__init__(**kwargs)
        Clock.schedule_once(lambda dt: self.first_update(), 2.1)


if __name__ == '__main__':
    from kivy.uix.boxlayout import BoxLayout
    from kivy.app import App

    appkvstr = """
#:import syringe shapes.syringe.info
#:import dna shapes.dna.info
#:import simple shapes.simple_tank.info
#:import graph shapes.graph.info
<Main@BoxLayout>:
    orientation: 'horizontal'
    padding: 10
    BoxLayout:
        orientation: 'vertical'
        spacing: 5
        
        ImageProgressBar:
            source_front: 'shapes/simple_tank/front.png'
            source_progress: 'shapes/simple_tank/back.png'
            value: sldr.value
            min_pos: simple.start
            max_length: simple.length
            direction: simple.direction
            
  
    Slider:
        id: sldr
        max: 100
        min: 0
"""


    class Main(BoxLayout):
        pass


    class TestApp(App):

        def __init__(self, **kwargs):
            Builder.load_string(appkvstr)
            super().__init__(**kwargs)

        def build(self):
            return Main()


    TestApp().run()

标签: pythonkivy

解决方案


我没有测试过这个,但我认为你可以创建一个NumericProperty地方,并将其用于ImageProgressBar价值。例如,在Main课堂上:

class Main(BoxLayout):
    value = NumericProperty(0)

然后,在kv你可以参考上面Property

<Main@BoxLayout>:
    orientation: 'horizontal'
    padding: 10
    BoxLayout:
        orientation: 'vertical'
        spacing: 5
        
        ImageProgressBar:
            source_front: 'shapes/simple_tank/front.png'
            source_progress: 'shapes/simple_tank/back.png'
            value: root.value  # use the value from the Main class
            min_pos: simple.start
            max_length: simple.length
            direction: simple.direction

然后你只需要更新value Propertyof Main,并且ImageProgressBar应该自动更新。更新value属性可以在一个单独的线程中完成,也许在一个循环中。


推荐阅读