Kivy在布局的不同侧面添加小部件

时间:2018-02-22 09:16:42

标签: python kivy

我有一个使用小部件打印消息的聊天应用。我想在不同的侧面打印这些,所以用户输入在右边,答案在左边。此外,我希望聊天框滚动到新消息。这是我的代码,我试图使用StackLayout,只是意识到它不起作用:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder

class Message(Widget):
    pass

class KatApp(App):
    def post(self):
        msg = self.root.ids.usrinp.text
        if len(msg) > 0:
            self.root.ids.chatbox.orientation = 'tb-rl'
            msgbox = Message()
            msgbox.ids.mlab.text = msg
            self.root.ids.chatbox.add_widget(msgbox)
            self.root.ids.scrlv.scroll_to(msgbox)
            self.root.ids.usrinp.text = ''
    def resp(self,msg):
        if len(msg) > 0:
            ansr = msg
            self.root.ids.chatbox.orientation = 'tb-lr'
            ansrbox = Message()
            ansrbox.ids.mlab.text = str(ansr)
            self.root.ids.chatbox.add_widget(ansrbox)
            self.root.ids.scrlv.scroll_to(ansrbox)
            self.root.ids.usrinp.text = ''

    def build(self):
        return Builder.load_string('''
<Message@Widget>:
    size_hint: None, None
    height: mlab.height
    width: mlab.width
    canvas:
        Color:
            rgba: 0, 1, 0, 0.7
        Rectangle:
            pos: self.pos
            size: self.size
    Label:
        id: mlab
        center: root.center
        padding: 10, 10
        markup: True
        text_size: (None, None)
        text: ''
        haligh: 'left'
        valign: 'top'
        size_hint: (1, None)
        size: self.texture_size
        color: 0, 0, 0

ScreenManager:
    Screen:

        BoxLayout:
            orientation: 'vertical'

            ScrollView:

                canvas.before:
                    Color:
                        rgb: 1, 1, 1
                    Rectangle:
                        pos: self.pos
                        size: self.size

                StackLayout:
                    id: chatbox
                    padding: 10, 10
                    orientation: 'tb-rl'

            BoxLayout:
                orientation: 'horizontal'
                padding: 10, 10, 10, 10
                size_hint: 1, None
                height: 50

                BoxLayout:
                    id: inpbox
                    height: max(40, scrlv.height)
                    size_hint: 0.9, None

                    ScrollView:
                        id: scrlv
                        width: inpbox.width - 15
                        x: inpbox.x + 10
                        y: inpbox.y
                        height: 
                            (len(usrinp._lines)+1) * usrinp.line_height - 5 \
                            if (len(usrinp._lines)+1 <= 5) \
                            else 5 * usrinp.line_height - 5

                        TextInput:
                            id: usrinp
                            valign: 'middle'
                            halign: 'left'
                            font_size: 16
                            multiline: True
                            size_hint: scrlv.size_hint_x, None
                            padding: 10, 0, 10, 0


                Button:
                    id: post
                    border: 0, 0, 0, 0
                    size: 40, 40
                    size_hint: None, None
                    on_press:
                        root.inp = usrinp.text
                        app.post()
                    on_release:
                        app.resp(root.inp)
''')

if __name__ == "__main__":
    KatApp().run()

为了这个例子,右下方的按钮发送用户输入on_press并使用相同的输入on_release回答。

此外,是否可以为消息窗口小部件设置最大宽度,例如,如果它到达页面中间,它应该在下一行?

我很难搞清楚的另一件事是TextInput。看起来,使用多行选项,当一个单词足够长以进入下一行并且我尝试删除它时,一些空间仍然存在并且它使框保持不调整大小。要重现这一点,只需键入&#34; aaaaaaaaaa&#34;直到它在第3行并尝试将其删除。

2 个答案:

答案 0 :(得分:2)

要包装小部件的宽度,请尝试以下操作:

读取文本和创建标签的功能

if(NETSTACK_RADIO().channel_clear()) {
      printf("channel not busy\n");
    } else {
      printf("channel busy\n");
    }

测量展开文字的长度

  def Sender_chat_bubble():

如果文本不长,请为我添加的填充保留相同的宽度+ 10

    Measure = Label(text=self.chatinputfield.text)
    Measure.texture_update()

    if Measure.texture_size[0]== 0 or self.chatinputfield.text=='':
        return 0

如果展开后的文本超出了您的限制(此处为250个),请将其包装为260个(250 + 10个填充)

    elif Measure.texture_size[0]<250:
        xsize = Measure.texture_size[0] 
        chatbubble = ChatBubble_Send(text=self.chatinputfield.text, width=xsize+10, padding_y=10, padding_x=10)
    

创建标签颜色的类

else:
     chatbubble = ChatBubble_Send(text=self.chatinputfield.text, width=250+10, padding_y=10, padding_x=10)

用于包装文字和标签的类

class ColorLabelSEND(Label):
    bgcolor = ListProperty([0.7, 0.7, 0.7, 0.7])
    def __init__(self, **kwargs):
        super(ColorLabelSEND, self).__init__(**kwargs)
        with self.canvas.before:
            r, g, b, a = self.bgcolor
            Color(r, g, b, a)
            self.rect = Rectangle(
                            size=self.size,
                            pos=self.pos)
            self.bind(size=self._update_rect,
                      pos=self._update_rect)

    def _update_rect(self, instance, value):
        self.rect.pos = instance.pos
        self.rect.size = instance.size

Example

答案 1 :(得分:0)

可以使用BoxLayout完成每一面的书写。

def post(self):
    msg = self.root.ids.usrinp.text
    if len(msg) > 0:
        msgbox = Message()
        msgbox.ids.mlab.text = msg
        msgbox.pos_hint = {'right': 1}
        self.root.ids.chatbox.add_widget(msgbox)
        self.root.ids.scrlv.scroll_to(msgbox)
        self.root.ids.usrinp.text = ''

def resp(self, msg):
    if len(msg) > 0:
        ansr = msg
        ansrbox = Message()
        ansrbox.ids.mlab.text = str(ansr)
        ansrbox.pos_hint = {'x': 0}
        self.root.ids.chatbox.add_widget(ansrbox)
        self.root.ids.scrlv.scroll_to(ansrbox)
        self.root.ids.usrinp.text = ''

在建设者中:

        ScrollView:

            canvas.before:
                Color:
                    rgb: 1, 1, 1
                Rectangle:
                    pos: self.pos
                    size: self.size

            BoxLayout:
                orientation: 'vertical'
                id: chatbox
                padding: 10, 10
                spacing: 5

pos_hint: {'right': 1}添加到输入窗口小部件后,文本现在位于右侧,如下所示:

问题现在仍然是小部件的宽度:

我尝试将窗口小部件的宽度设置为max(root.width, mlab.width),但它不起作用。此外,现在,向上滚动也不起作用。