Kivy中的动态小部件大小调整

时间:2016-03-24 15:49:00

标签: python python-3.x kivy

我有一个自定义小部件Message,其中包含TextInputButtonLabelTextInput是不可编辑的,其目的只是显示文字。但我无法调整大小以适应文本。我见过有人询问动态身高,他得到了像wdg.height = (len(wdg._lines) + 1) * wdg.line_height这样的答案。虽然这确实适用于高度,但我不确定如何实现宽度类似的东西。也许有某种line_width财产?我想也许可以将font_size和最长的行相乘,但不同字母占用的大小并不一致,我也没有看到预测包装的方法,所以这是一个问题。有没有更好的变种? 这是我的一段代码,用于定义小部件:

Builder.load_string('''
<Message>:
    FloatLayout:
        pos: root.pos
        width: self.width
        height: self.height
        canvas:
            Color:
                rgba: 0, 0, 0, 1
            RoundedRectangle:
                pos: root.pos
                size: self.size
            Color:
                rgba: 1, 1, 1, 1
            RoundedRectangle:
                pos: root.x + 1, root.y + 1
                size: self.width - 2, self.height - 2

        Button:
            id: bt
            pos: root.pos
            size: self.size
            background_normal: ''
            background_down: ''
            background_color: 0, 0, 0, 0
            on_press: root.test()
            MyTextInput:
                pos: root.pos
                size: bt.size
                id: msg
                background_color: 0, 0, 0, 0
                readonly: True
                text: str(msg)
                cursor_color: 0, 0, 0, 0

        Label:
            x: root.x + 65
            y: root.y - 15
            size: 40, 2
            id: time
            color: 0, 0, 0, 1
            font_size: 10
''')

class Message(Widget):
    def __init__(self, **kwargs):
        super(Message, self).__init__(**kwargs)

    def test(self, *args, **kwargs):
        print("Touch received")

负责创建这些小部件的build方法中的函数:

def msg_in(*args, **kwargs):
    global pr_msg_y, msg_stack
    msg = tx1_main.text.strip("\n ")
    if msg not in string.whitespace:
        msg_stack.append(Message())  

        time = datetime.now().strftime("%H:%M")
        msg_stack[-1].ids['time'].text = time

        msg_stack[-1].ids['msg'].text = msg

        msg_stack[-1].width = 500
        msg_stack[-1].ids['msg'].height = (len(msg_stack[-1].ids['msg']._lines) + 1) * msg_stack[-1].ids['msg'].line_height

        for i in msg_stack[-1].children:
            i.height = (len(msg_stack[-1].ids['msg']._lines) + 1) * msg_stack[-1].ids['msg'].line_height
        msg_stack[-1].y = sv1_main.height - 5 - pr_msg_y - msg_stack[-1].height
        msg_stack[-1].x = 5

        tx1_main.text = ''

        msg_float.add_widget(msg_stack[-1])
        pr_msg_y += msg_stack[-1].height + 5

其中tx1_main是我从(TextInput)获取文字的地方,而sv1_mainScrollView,显示FloatLayoutmsg_float )显示这些消息小部件。

2 个答案:

答案 0 :(得分:0)

首先,TextInput有一个属性minimum_height。您只需将以下内容添加到kv即可使任何TextInput正确的高度:

size_hint_y: None
height: self.minimum_height

关于宽度,没有等价物。通常不需要这个(通常需要minimum_height,特别是对于单行输入)。如果您的目的是允许将文本复制到剪贴板,我建议您只使用Label并在其旁边放一个小Button,将整个文本复制到剪贴板。对于Label,您可以像这样调整大小:

size_hint: None, None
size: self.texture_size

更好的是,您还可以添加填充:

size_hint: None, None
height: self.texture_size[1] + dp(8)
width: self.texture_size[0] + dp(8)

答案 1 :(得分:0)

实际上,有一种方法。显然,TextInput有一个受保护的属性_lines_labels,它是一个纹理列表,可能代表这些行。这些纹理有大小,所以我可以访问它以找到最大值并适当调整我的小部件大小。