为什么在Kivy中调用'root'关键字时会有所不同?

时间:2018-10-02 07:03:17

标签: python kivy

How to make circular progress bar in kivy?

我在上面找到了圆形进度条的来源,并指出了一些奇怪的地方。

from kivy.app import App
from kivy.uix.progressbar import ProgressBar
from kivy.core.text import Label as CoreLabel
from kivy.lang.builder import Builder
from kivy.graphics import Color, Ellipse, Rectangle
from kivy.clock import Clock


class CircularProgressBar(ProgressBar):

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

        # Set constant for the bar thickness
        self.thickness = 40

        # Create a direct text representation
        self.label = CoreLabel(text="0%", font_size=self.thickness)

        # Initialise the texture_size variable
        self.texture_size = None

        # Refresh the text
        self.refresh_text()

        # Redraw on innit
        self.draw()

    def draw(self):

        with self.canvas:

            # Empty canvas instructions
            self.canvas.clear()

            # Draw no-progress circle
            Color(0.26, 0.26, 0.26)
            Ellipse(pos=self.pos, size=self.size)

            # Draw progress circle, small hack if there is no progress (angle_end = 0 results in full progress)
            Color(1, 0, 0)
            Ellipse(pos=self.pos, size=self.size,
                    angle_end=(0.001 if self.value_normalized == 0 else self.value_normalized*360))

            # Draw the inner circle (colour should be equal to the background)
            Color(0, 0, 0)
            Ellipse(pos=(self.pos[0] + self.thickness / 2, self.pos[1] + self.thickness / 2),
                    size=(self.size[0] - self.thickness, self.size[1] - self.thickness))

            # Center and draw the progress text
            Color(1, 1, 1, 1)
            Rectangle(texture=self.label.texture, size=self.texture_size,
                      pos=(self.size[0]/2 - self.texture_size[0]/2, self.size[1]/2 - self.texture_size[1]/2))

    def refresh_text(self):
        # Render the label
        self.label.refresh()

        # Set the texture size each refresh
        self.texture_size = list(self.label.texture.size)

    def set_value(self, value):
        # Update the progress bar value
        self.value = value

        # Update textual value and refresh the texture
        self.label.text = str(int(self.value_normalized*100)) + "%"
        self.refresh_text()

        # Draw all the elements
        self.draw()


class Main(App):

    def just_function(self):
        print(self.root) # <----- this will print None

    # Simple animation to show the circular progress bar in action
    def animate(self, dt):
        print(self.root) # <---- this prints CircularProgressBar object
        if self.root.value < 80:
            self.root.set_value(self.root.value + 1)
        else:
            self.root.set_value(0)

    # Simple layout for easy example
    def build(self):
        container = Builder.load_string(
            '''CircularProgressBar:
    size_hint: (None, None)
    height: 200
    width: 200
    max: 80''')

        # Animate the progress bar
        Clock.schedule_interval(self.animate, 0.1)
        print(self.root) # <---- this prints None
        self.just_function() # <---- this prints None
        return container


if __name__ == '__main__':
    Main().run()

看看Main(App)

在此来源中,self.root在这里被视为CircularProgressBar

但是,当我执行print(self.root)时,它会打印None

仅当CircularProgressBar处于self.root所调用的函数中时,它才能识别Clock.scheduled_interval(func, rate)

有人知道这里发生了什么吗?

1 个答案:

答案 0 :(得分:1)

解释非常简单,并且在docs中有清楚的解释:

  

根=无

     

由build()方法或load_kv()返回的根窗口小部件   如果kv文件包含根窗口小部件,则该方法。

从以上内容可以理解,root是在build()方法中返回的元素,因此在返回该函数之前,root将是None ,因此,当您在self.root中打印build()或调用返回self.root的函数,然后再返回该函数时,将始终得到None。返回根之后,它将返回您返回的内容,即containerCircularProgressBar的对象。