Python Kivy获取canvas元素ID、修复canvas布局错位问题
Kivy开发两类问题解决方案
问题1:无法获取Canvas内Rectangle尺寸触发AttributeError
报错原因
*Kivy的id作用域仅覆盖Widget控件树,canvas块内的Rectangle、Line等属于图形指令,不属于控件层级,直接给图形指令配置的id不会被注册到控件的ids字典中,因此直接调用self.ids.Canvas.ids.rect会触发属性不存在的报错。
修复方案(推荐)
通过ObjectProperty绑定图形指令的引用,外部可直接通过控件属性访问:
- 先在Python代码中导入属性类,给
Canvas_Widget添加专门存储Rectangle引用的属性:
from kivy.app import App from kivy.uix.widget import Widget from kivy.uix.boxlayout import BoxLayout from kivy.core.window import Window from kivy.metrics import dp from kivy.properties import ObjectProperty Window.size= dp(500),dp(500) class Canvas_Widget(Widget): rect = ObjectProperty(None) def __init__(self,**kwargs): super().__init__(**kwargs) class MainWidget(BoxLayout): def __init__(self,**kwargs): super(MainWidget, self).__init__(**kwargs) def minimizer(self,button): button.background_color=(1,0,0,1) # 直接访问Canvas_Widget实例的rect属性获取尺寸 print(self.ids.Canvas.rect.size) def minimizer_release(self,button): button.background_color=(.3,.3,1,1) class mynewApp(App): pass mynewApp().run()
- 修改kv配置文件,将Rectangle实例绑定到新增的属性上:
MainWidget: <Canvas_Widget>: canvas: Color: rgb:.4,.4,.4,1 Rectangle: id:rect pos:dp(100),dp(100) size:self.width - dp(200),self.height - dp(200) Color: rgb:0,1,0,1 Line: points:(dp(100),self.height - dp(100),self.width - dp(100),dp(100)) Line: points:(dp(100),dp(100),self.width - dp(100),self.height - dp(100)) # 绑定rect引用到类属性 rect: rect <MainWidget>: orientation: 'horizontal' Button: text:'press' size_hint_x: 0.2 on_press:root.minimizer(self) background_color:(.3,.3,1,1) on_release: root.minimizer_release(self) Canvas_Widget: id:Canvas size_hint_x: 0.8
备选方案:如果不想新增属性,可以遍历Canvas_Widget的canvas指令列表匹配Rectangle对象,但是该方法需要遍历判断,多图形指令场景下效率低、易出错,示例代码:
from kivy.graphics import Rectangle def minimizer(self,button): button.background_color=(1,0,0,1) cw = self.ids.Canvas for instr in cw.canvas.children: if isinstance(instr, Rectangle): print(instr.size) break
问题2:Canvas布局错位、覆盖左侧按钮
错位原因
- 未显式指定BoxLayout的排列方向,部分运行环境下默认排列方向不符合预期
- 未给Button、Canvas_Widget两个子控件明确尺寸占比,默认
size_hint权重分配异常,加上Widget默认透明,视觉上呈现Canvas内容覆盖按钮的效果
修复方案
在kv的<MainWidget>规则中显式声明排列方向、给子控件配置宽度占比即可,上述修复后的kv代码已经包含该部分修改:
- 给MainWidget加
orientation: 'horizontal',明确子控件从左到右水平排列 - 给Button设置
size_hint_x: 0.2,固定占20%宽度 - 给Canvas_Widget设置
size_hint_x: 0.8,固定占80%宽度
内容的提问来源于stack exchange,提问作者amir_hossain oroujlou
相关产品推荐
相关产品推荐

