Kivy:调整按钮大小以适应下拉列表中的包装文本

Kivy: Sizing Buttons to fit wrapped text within dropdown

我在为文本启用了自动换行的情况下构建 Kivy 下拉菜单时遇到问题,这样按钮小部件的大小就会相应地容纳全文。

我遵循了下面的堆栈溢出线程和同样链接的类似博客 post 的指导。

文本按预期换行,但是随着文本字符串变长,呈现按钮时文本上方和下方的 "padding" 数量也在增加。我不确定是什么原因造成的,希望消除这种影响。

更新:(编辑代码使问题更简洁。编辑图像以匹配)

"extra padding" 与文本长度无关,而是与添加到下拉列表的循环索引 and/or 小部件计数有关。

进一步编辑这行代码:

btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(1,None))

收件人:

btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(None,None),width=700)

(设置 size_hint=(none,none) 而不是 (1,none) 并添加 width=700)

消除了这个问题。我无法理解导致这种行为的原因。编辑后的代码失去了按钮的自动宽度调整,我无法想象宽度 size_hint 是如何导致垂直 "padding".

显示问题的屏幕截图

这段代码演示了这个问题:

from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.base import runTouchApp
from kivy.lang import Builder

Builder.load_string('''
<WrapButton>:
    halign: "center"
    valign: "center"
    font_size: 20
    size_hint_y: None
    text_size : self.size
    height: self.texture_size[1]
''')

class WrapButton(Button):
    pass

dropdown2 = DropDown()

layout = BoxLayout(padding=0,orientation='vertical')

mainbutton2 = WrapButton(text='Select...', size_hint=(1, None),height=95,pos_hint={'center_x': .5, 'center_y': 0})
mainbutton2.bind(on_release=dropdown2.open)
layout.add_widget(mainbutton2)

for index in range(20):
    btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|') , size_hint=(1,None))
    btn2.bind(on_release=lambda btn2: dropdown2.select(btn2.text))
    dropdown2.add_widget(btn2)

dropdown2.bind(on_select=lambda instance, x: setattr(mainbutton2, 'text', x))

runTouchApp(layout)

截图

更新: 下面接受的答案会导致 Android 上出现伪影。我正在努力在其他设备上进行测试以排除设备本身。我们将不胜感激来自社区的任何意见!

Artifacts..broken Kivy install?

解决办法是将text_size : self.size换成text_size : self.width, None。详情请参考示例和输出。

例子

main.py

from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.base import runTouchApp
from kivy.lang import Builder

Builder.load_string('''
<WrapButton>:
    halign: "center"
    valign: "center"
    font_size: 20
    size_hint_y: None
    text_size : self.width, None
    height: self.texture_size[1]
''')


class WrapButton(Button):
    pass


dropdown2 = DropDown()

layout = BoxLayout(padding=0, orientation='vertical')

mainbutton2 = WrapButton(text='Select...', size_hint=(1, None), height=95, pos_hint={'center_x': .5, 'center_y': 0})
mainbutton2.bind(on_release=dropdown2.open)
layout.add_widget(mainbutton2)

for index in range(20):
    btn2 = WrapButton(text=('|' + str('long text..is long...%d' % (21-index) * index) + '|'), size_hint=(1, None))
    btn2.bind(on_release=lambda btn2: dropdown2.select(btn2.text))
    dropdown2.add_widget(btn2)

dropdown2.bind(on_select=lambda instance, x: setattr(mainbutton2, 'text', x))

runTouchApp(layout)

输出