You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kivy的FloatLayout中让圆形进度条及数值随窗口调整保持居中

问题根因

  • KV配置中给圆形进度条写死了固定坐标pos: 250, 250,不会跟随父容器尺寸变化自动调整位置
  • 自定义CircularProgressBar没有绑定尺寸、位置变化事件,窗口调整时画布不会自动重绘,进度条显示位置不会同步更新

修复步骤

1. 调整Python代码

给CircularProgressBar新增位置、尺寸变化的事件绑定,每次属性变化自动触发重绘:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
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)
        self.thickness = 40
        self.label = CoreLabel(text="0", font_size=self.thickness)
        self.texture_size = None
        self.refresh_text()
        # 绑定位置、尺寸变化事件自动重绘
        self.bind(pos=self.draw, size=self.draw)
        self.draw()
    def draw(self, *args):
        with self.canvas:
            self.canvas.clear()
            Color(0.26,0.26,0.26)
            Ellipse(pos=self.pos, size=self.size)
            Color(1,0,0)
            Ellipse(pos=self.pos,size=self.size,angle_end=(self.value/100.0)*360)
            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))
            Color(1, 1, 1, 1)
            # 修正文字位置计算逻辑,避免偏移
            Rectangle(texture=self.label.texture,size=self.texture_size,pos=(self.size[0]/2 + self.pos[0] - self.texture_size[0]/2,self.size[1]/2 + self.pos[1] - self.texture_size[1]/2))
            self.label.text = str(int(self.value))

    def refresh_text(self):
        self.label.refresh()
        self.texture_size=list(self.label.texture.size)
    def set_value(self, value):
        self.value = value
        self.label.text = str(int(self.value))
        self.refresh_text()
        self.draw()

class MainWindow(Screen):
    current = ""

class WindowManager(ScreenManager):
    pass

class Main(App):
    def animate(self,dt):
        circProgressBar = self.root.get_screen('main').ids.cp
        if circProgressBar.value < 99:
            circProgressBar.set_value(circProgressBar.value+1)
        else:
            circProgressBar.set_value(0)

    def build(self):
        sm = WindowManager()
        sm.add_widget(MainWindow(name="main"))
        Clock.schedule_interval(self.animate, 0.1)
        return sm

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

注:移除了多余的多重继承逻辑,避免类属性冲突

2. 调整KV文件(main.kv)

把固定坐标替换为FloatLayout的相对居中属性:

WindowManager:
    MainWindow:

<MainWindow>:
    name: "main"

    FloatLayout:
        CircularProgressBar:
            id: cp
            pos_hint: {"center_x": 0.5, "center_y": 0.5}
            size_hint:(None,None)
            height:200
            width:200
            max:100

效果说明

修改后进度条会始终保持在窗口居中位置,调整窗口尺寸、切换不同分辨率的设备都不会出现位置偏移,布局完全自适应。

内容的提问来源于stack exchange,提问作者Ded Meme

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 21:42:03