如何在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
相关产品推荐
相关产品推荐

