如何在Kivy中制作圆形进度条?

10

我想使用kivy和python制作一个简单的圆形进度条。我查找了在线文档和GitHub仓库,但没有找到任何一个合适的例子来解释圆形进度条的概念。

就像下面附加的图片一样。我想开发它。请有人在这个问题上帮助我。enter image description here


我改进了上一个答案,添加了文本和更易用性,希望这会有所帮助。 - Kacperito
1个回答

20

全新、更好的版本

这篇文章获得了比我预期的更多关注,因此我决定花一点时间创建一个升级版的小部件。它现在可以在 GitHub 上获取。以下是其示例(进度条实际上是透明的,我添加了黑色背景以使所有内容都可见):

动态的更好的圆形进度条

如果有人感兴趣,我会在下面保留旧帖子供参考。

旧帖子

我制作了一个小部件来表示您想要实现的功能。但是有一些限制,具体如下:

  1. 您需要调用set_value方法来设置进度条值,而不仅仅是使用.value。我非常不确定应该如何才能实现与原始ProgressBar类中相同的行为;

  2. 您必须指定大小才能实现圆形,因为对象本身是椭圆形。

以下是代码和示例用法:

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)
            #added pos[0]and pos[1] for centralizing label text whenever pos_hint is set
            Rectangle(texture=self.label.texture, size=self.texture_size,
                  pos=(self.size[0] / 2 - self.texture_size[0] / 2 + self.pos[0], self.size[1] / 2 - self.texture_size[1] / 2 + self.pos[1]))


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

    # Simple animation to show the circular progress bar in action
    def animate(self, dt):
        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)
        return container


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

输出:

动态圆形进度条


如果可能的话,您能否建议我如何为上述单个Python文件创建Kivy和Python的单独文件,而不改变功能? - Nandakishor Jahagirdar
是否可以手动设置圆形进度条的值,而不是自动更新?例如,在kivy字符串中定义滑块,并根据滑块的值移动和更改圆形进度条内部的文本。 - Nandakishor Jahagirdar
你可以像使用 ProgressBar 一样使用我的小部件,只是每当你想设置一个值时,你必须调用 set_value(value)(请查看我提供的示例)。这将自动更新圆形和文本进度。关于分离,只需创建一个新模块来放置该类,并在需要使用它的任何地方导入它。据我所知,在你的 .kv 布局中使用它,你还必须在具有主要 App 类的模块中导入它。尝试一下,看看你能做什么! - Kacperito
1
@NandakishorJahagirdar - 如果您仍然有兴趣使用它,请查看小部件的新版本。也许它会更有用! - Kacperito

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接