Kivyとpythonを使用して1つのシンプルな円形のプログレスバーを作成することを考えました。オンラインドキュメントとGitHubレパートリーを検索しましたが、円形のプログレスバーの概念を説明する適切な例が1つも見つかりませんでした。
この投稿は予想以上に多くの注目を集めたため、このウィジェットのアップグレードされたバージョンを作成するために少し努力することにしました。 GitHub で利用できるようになりました。これを使ってできることの例を次に示します(進行状況バーは実際には透明です。すべてを表示するためにgifに黒い背景を追加しました)。
興味のある方がいたら、以下の参考のために古い記事を保管しておきます。
あなたが達成したいことを表すウィジェットを作りました。ただし、いくつかの制限があります。
.value
を使用してプログレスバーの値を設定する代わりに、set_value
メソッドを呼び出す必要があります。元のProgressBar
クラスと同じ動作を実現するために何をすべきかは非常にわかりません。
オブジェクト自体は楕円であるため、円を実現するにはサイズを指定する必要があります。
以下は、コードと使用例です。
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()
出力: