Kivy中Widget在Layout内显示位置异常问题求助
问题描述
我在S2中绘制了一个方框,本应显示在S2(即右侧中间区域),但它却出现在屏幕左下角(100,100)位置。是否是我在属性赋值上出现了错误?
相关代码:
class R(Widget): def __init__(self,x,y,szer,wys, kB=(1, 1, 1, 1)): self.x=x self.y=y self.szer=szer self.wys=wys super().__init__() with self.canvas: Color(*kB) Line(rectangle=(self.x,self.y,self.szer,self.wys),width=1.5) Okno = BoxLayout(orientation='vertical', spacing=10) Top = BoxLayout(orientation='horizontal', spacing=10,size_hint=(1, .35)) F.CustomGraphics.SetBG(Top, bg_color=[0,1,0,0.2]) Top.add_widget(Label(text="aaaaa")) Srodek = BoxLayout(orientation='horizontal', spacing=10) S1 = BoxLayout(orientation='vertical', spacing=10) F.CustomGraphics.SetBG(S1, bg_color=[1,0,0,0.2]) S1.add_widget(Label(text="bb 11")) Srodek.add_widget(S1) S2 = BoxLayout(orientation='vertical', spacing=10) F.CustomGraphics.SetBG(S2, bg_color=[1,1,0,0.2]) S2.add_widget(F.R(100,100,100,100, kB=Ziel50)) Srodek.add_widget(S2) Bottom = BoxLayout(orientation='horizontal', spacing=10,size_hint=(1, .35)) F.CustomGraphics.SetBG(Bottom, bg_color=[0,0,1,0.2]) Bottom.add_widget(Label(text="cccc")) Okno.add_widget(Top) Okno.add_widget(Srodek) Okno.add_widget(Bottom) self.add_widget(Okno)
这个绿色方框本应显示在其他位置。
问题原因
问题出在自定义Widget的画布绘制逻辑和属性处理上:
- Kivy中Widget的画布默认使用全局屏幕坐标系,你直接用
self.x、self.y绘制矩形,这个坐标是相对于屏幕原点(左下角)的,而非S2容器的局部坐标系。 - 直接给
self.x、self.y赋值,没有使用Kivy的Property属性系统,导致Widget无法和布局系统联动,布局容器也无法管理它的位置。 - 自定义的
R组件未设置size_hint或固定大小,布局容器无法正确计算它的尺寸和位置。
解决方案
修改R类,让绘制基于Widget自身的局部坐标系,并通过Kivy属性系统与布局联动:
方案1:绘制Widget内部填充矩形
如果需要让矩形占满Widget的整个区域:
from kivy.uix.widget import Widget from kivy.graphics import Color, Line from kivy.properties import ListProperty class R(Widget): # 用Kivy属性定义颜色,支持动态更新 kB = ListProperty((1, 1, 1, 1)) def __init__(self, **kwargs): super().__init__(**kwargs) # 绑定属性变化时自动更新画布 self.bind(pos=self.update_canvas, size=self.update_canvas, kB=self.update_canvas) self.update_canvas() def update_canvas(self, *args): self.canvas.clear() with self.canvas: Color(*self.kB) # 基于Widget自身坐标系绘制((0,0)是Widget的左下角) Line(rectangle=(0, 0, self.size[0], self.size[1]), width=1.5)
添加到S2时,指定固定大小避免布局压缩:
# 设置固定宽高,size_hint设为None让布局不自动缩放 S2.add_widget(F.R(size=(100,100), size_hint=(None, None), kB=Ziel50))
方案2:支持自定义偏移的内部矩形
如果需要让矩形在Widget内部有偏移:
from kivy.uix.widget import Widget from kivy.graphics import Color, Line, PushMatrix, Translate from kivy.properties import NumericProperty, ListProperty class R(Widget): x_offset = NumericProperty(0) y_offset = NumericProperty(0) rect_width = NumericProperty(100) rect_height = NumericProperty(100) kB = ListProperty((1, 1, 1, 1)) def __init__(self, **kwargs): super().__init__(**kwargs) self.bind(pos=self.update_canvas, size=self.update_canvas, x_offset=self.update_canvas, y_offset=self.update_canvas, rect_width=self.update_canvas, rect_height=self.update_canvas, kB=self.update_canvas) self.update_canvas() def update_canvas(self, *args): self.canvas.clear() with self.canvas: # 切换到Widget自身的局部坐标系 PushMatrix() Translate(self.pos[0], self.pos[1]) Color(*self.kB) Line(rectangle=(self.x_offset, self.y_offset, self.rect_width, self.rect_height), width=1.5)
使用示例:
S2.add_widget(F.R(x_offset=50, y_offset=50, rect_width=100, rect_height=100, size=(200,200), size_hint=(None, None), kB=Ziel50))
修改后,矩形会显示在S2容器内部的对应位置,而非屏幕左下角。
内容的提问来源于stack exchange,提问作者Kolkornik
相关产品推荐
相关产品推荐

