Kivy Button组件text_size绑定后文本过早换行的问题求助
嘿,我看你遇到的这个问题挺典型的,大概率是布局时机不对导致的!你现在的代码里是在drawGui里一次性给按钮设置text_size = button.size,但这个时候按钮的实际尺寸可能还没完全确定——尤其是在手机或者模拟器上,布局加载和尺寸计算是异步的,你设置的可能是按钮初始的小尺寸,之后按钮宽度变宽了,但text_size没跟着更新,所以文本还是按照旧的窄宽度来换行,就出现了“Random”被拆成两行的尴尬情况。
另外你在on_size里直接调用drawGui,每次尺寸变化就重新创建所有按钮,这不仅效率低,还可能触发多次布局计算,加重了尺寸不同步的问题。
给你几个靠谱的解决办法:
方法一:给按钮绑定on_size事件,实时更新text_size
不要一次性设置text_size,而是让每个按钮自己监听尺寸变化,自动同步text_size:
#__version__ = '1.0' from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout from kivy.uix.button import Button class ButtonTest(BoxLayout): def __init__(self, **kwargs): super(ButtonTest, self).__init__(**kwargs) self.drawGui() def drawGui(self,instance=None): self.clear_widgets() self.orientation = 'vertical' # Buttons self.prac_button_layout = GridLayout(cols=3) # 创建按钮时绑定尺寸更新事件 def update_text_size(button, *args): button.text_size = button.size button.halign = 'center' button.valign = 'middle' prac_random = Button(text="Random") prac_random.bind(size=update_text_size) prac_depth_first = Button(text="Depth first") prac_depth_first.bind(size=update_text_size) prac_breadth_first = Button(text="Breadth first") prac_breadth_first.bind(size=update_text_size) self.prac_button_layout.add_widget(prac_random) self.prac_button_layout.add_widget(prac_breadth_first) self.prac_button_layout.add_widget(prac_depth_first) self.add_widget(self.prac_button_layout) # 注意:不要在on_size里重复调用drawGui!会导致无限循环和重复创建控件 # 删掉原来的on_size方法,因为我们已经给按钮绑定了size事件 class MyApp(App): def build(self): return ButtonTest() if __name__ == '__main__': MyApp().run()
这样每次按钮的尺寸变化时,text_size都会自动跟着更新,文本就会按照当前按钮的实际宽度来计算是否换行。
方法二:用Kv语言实现,更简洁可靠
Kivy的Kv语言天生擅长处理属性绑定,能避免手动处理布局时机的麻烦,推荐你试试这种方式:
#__version__ = '1.0' from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.lang import Builder Builder.load_string(''' <ButtonTest>: orientation: 'vertical' GridLayout: cols: 3 Button: text: "Random" text_size: self.size halign: 'center' valign: 'middle' Button: text: "Breadth first" text_size: self.size halign: 'center' valign: 'middle' Button: text: "Depth first" text_size: self.size halign: 'center' valign: 'middle' ''') class ButtonTest(BoxLayout): pass class MyApp(App): def build(self): return ButtonTest() if __name__ == '__main__': MyApp().run()
用Kv的话,text_size: self.size是实时绑定的,只要按钮尺寸变了,text_size会自动同步,完全不用手动处理事件,代码也更清晰。
额外提醒
你之前在on_size里调用drawGui会导致每次窗口/屏幕尺寸变化就重新创建所有按钮,这不仅浪费资源,还可能引发布局计算的循环问题,一定要删掉这个逻辑哦。
按照上面的方法修改后,不管是电脑上调整窗口大小,还是打包成apk在手机/模拟器上运行,按钮文本都能根据实际宽度正确显示,不会出现莫名其妙的换行啦!
备注:内容来源于stack exchange,提问作者Dr Xorile

