在IMChat屏幕上添加标签kivy。

问题描述 投票:0回答:1

我想在我的kivy应用中制作一个屏幕,让两个用户可以互相聊天,但我对如何在屏幕上显示聊天信息有问题。

以下是我想要的例子。(向下滚动约60%的页面即可看到)https:/medium.comflutter-communitybuilding-a-chat-app-with-flutter-and-firebase-from-scratch-9eaa7f41782e。

我曾用这个答案在屏幕左侧添加标签(用户发送的消息)。标签一直在滚动视图屏幕边缘运行 x轴 Kivy:

但我现在想知道如何在屏幕右侧添加标签(用户收到的消息)。我想我需要一个 GridLayout 有两列,我需要先添加一个白色标签,之后再添加信息标签,然后它应该出现在右边。我遇到的问题是如何让标签尽可能地出现在屏幕上的右边。

我也有问题,标签的大小取决于每个标签中文字的数量,我想我可能需要把每一行都添加为一个新的 "标签"。GridLayout

kivy肯定已经做了类似的事情,而且有一个指南可以遵循,但我找了一圈,我只能找到老式的UI聊天屏幕设计。

py文件

import kivy
from kivymd.app import MDApp
from kivy.properties import ObjectProperty, StringProperty, NumericProperty, ListProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.core.text import Label as CoreLabel
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDFillRoundFlatButton, MDRoundFlatIconButton, MDRaisedButton, MDTextButton, MDIconButton
from kivy.core.window import Window

Window.size = (481, 600)
Window.clearcolor = (1,1,1,1)

class Chat(Screen):
    chat_layout = ObjectProperty(None)
    def send_message(self):
        if self.ids.message.text:
            lab1 = Label()

            # calculate max allowable width in the GridLayout
            max_width = self.chat_layout.width - self.chat_layout.spacing[0] - self.chat_layout.padding[0] - \
                        self.chat_layout.padding[2]

            # specify font and font_size (so that the CoreLabel uses the same)
            self.chat_layout.add_widget(
                SmoothLabel.create_sized_label(text=self.ids.message.text, max_width=max_width, font_name='Roboto',
                                               font_size=15))

            self.chat_layout.add_widget(lab1)
            self.ids.message.text = ""
        else:
            pass

    def recv_message(self):
        if self.ids.message.text:
            # calculate max allowable width in the GridLayout
            max_width = self.chat_layout.width - self.chat_layout.spacing[0] - self.chat_layout.padding[0] - \
                        self.chat_layout.padding[2]

            # specify font and font_size (so that the CoreLabel uses the same)
            chat_label = SmoothLabel.create_sized_label(text=self.ids.message.text, max_width=max_width, font_name='Roboto',
                                               font_size=15)
            lab1 = Label(width=max_width)
            self.chat_layout.add_widget(lab1)
            self.chat_layout.add_widget(chat_label)
            self.ids.message.text = ""
        else:
            pass

class SmoothLabel(Label):
    @staticmethod
    def create_sized_label(**kwargs):
        max_width = kwargs.pop('max_width', 0)
        if max_width <= 0:
            # just create a SmoothLabel without a text_size
            return SmoothLabel(**kwargs)

        # calculate what the SmoothLabel size will be
        core_label = CoreLabel(padding=[10,10], **kwargs)  # use same padding as SmoothLabel
        core_label.refresh()

        if core_label.width > max_width:
            # width is too big, use text_size to force wrapping
            return SmoothLabel(text_size=(max_width,None), **kwargs)
        else:
            # width is OK, no need for text_size
            return SmoothLabel(**kwargs)

class WindowManager(ScreenManager):
    pass


class MyApp(MDApp):
    def build(self):
        kv = Builder.load_file("kivy.kv")
        self.sm = WindowManager()

        screens = [Chat(name="chat")]
        for screen in screens:
            self.sm.add_widget(screen)

        self.sm.current = "chat"
        return self.sm


if __name__ == '__main__':
    MyApp().run()

kv文件

<Chat>:
    name: "chat"
    chat_layout: chat_layout

    GridLayout:
        cols: 1
        GridLayout:
            cols: 2
            id: chat_layout
            padding: 15

        GridLayout:
            cols: 3
            MDRaisedButton:
                on_release: root.send_message()
                text: "send message"
            TextInput:
                id: message
                size_hint: None, None
                size: 150,50
                hint_text:
                    "Send message"
            MDRaisedButton:
                on_release: root.recv_message()
                text: "receive message"

<SmoothLabel>:
    size_hint: None, None
    size: self.texture_size
    padding: 10, 10
    multiline: True
    background_color: 0,0,0,0
    background_normal: ""
    back_color: 1,0,1,1
    border_radius: [6]
    canvas.before:
        Color:
            rgba: 0.2,0.6,1,1 #This changes the label colour
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: self.border_radius
kivy kivy-language
1个回答
0
投票

我想您可以通过使用 BoxLayout 而非 GridLayout,并使用 pos_hint 以将聊天标签定位在左边或右边。

import kivy
from kivymd.app import MDApp
from kivy.properties import ObjectProperty, StringProperty, NumericProperty, ListProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.core.text import Label as CoreLabel
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDFillRoundFlatButton, MDRoundFlatIconButton, MDRaisedButton, MDTextButton, MDIconButton
from kivy.core.window import Window

Window.size = (481, 600)
Window.clearcolor = (1,1,1,1)

class Chat(Screen):
    chat_layout = ObjectProperty(None)
    def send_message(self):
        if self.ids.message.text:
            # calculate max allowable width in the BoxLayout
            max_width = (self.chat_layout.width - self.chat_layout.spacing - self.chat_layout.padding[0] - \
                        self.chat_layout.padding[2]) * 0.75

            # specify font and font_size (so that the CoreLabel uses the same)
            self.chat_layout.add_widget(
                SmoothLabel.create_sized_label(text=self.ids.message.text, max_width=max_width, font_name='Roboto',
                                               font_size=15, pos_hint={'x':0}))
            self.ids.message.text = ""
            self.ids.scroll.scroll_y = 0  # make sure last message is visible
        else:
            pass

    def recv_message(self):
        if self.ids.message.text:
            # calculate max allowable width in the BoxLayout
            max_width = (self.chat_layout.width - self.chat_layout.spacing - self.chat_layout.padding[0] - \
                        self.chat_layout.padding[2]) * 0.75

            # specify font and font_size (so that the CoreLabel uses the same)
            self.chat_layout.add_widget(
                SmoothLabel.create_sized_label(text=self.ids.message.text, max_width=max_width, font_name='Roboto',
                                               font_size=15, pos_hint={'right':1}))
            self.ids.message.text = ""
            self.ids.scroll.scroll_y = 0  # make sure last message is visible
        else:
            pass

class SmoothLabel(Label):
    @staticmethod
    def create_sized_label(**kwargs):
        max_width = kwargs.pop('max_width', 0)
        if max_width <= 0:
            # just create a SmoothLabel without a text_size
            return SmoothLabel(**kwargs)

        # calculate what the SmoothLabel size will be
        core_label = CoreLabel(padding=[10,10], **kwargs)  # use same padding as SmoothLabel
        core_label.refresh()

        if core_label.width > max_width:
            # width is too big, use text_size to force wrapping
            return SmoothLabel(text_size=(max_width,None), **kwargs)
        else:
            # width is OK, no need for text_size
            return SmoothLabel(**kwargs)


class WindowManager(ScreenManager):
    pass

kv_str = '''
<Chat>:
    name: "chat"
    chat_layout: chat_layout

    GridLayout:
        cols: 1
        ScrollView:
            id: scroll
            BoxLayout:
                orientation: 'vertical'
                id: chat_layout
                padding: 15
                spacing: 15
                size_hint: 1, None
                height: self.minimum_height

        GridLayout:
            cols: 3
            MDRaisedButton:
                on_release: root.send_message()
                text: "send message"
            TextInput:
                id: message
                size_hint: None, None
                size: 150,50
                hint_text:
                    "Send message"
            MDRaisedButton:
                on_release: root.recv_message()
                text: "receive message"

<SmoothLabel>:
    size_hint: None, None
    size: self.texture_size
    padding: 10, 10
    multiline: True
    background_color: 0,0,0,0
    background_normal: ""
    back_color: 1,0,1,1
    border_radius: [6]
    canvas.before:
        Color:
            rgba: 0.2,0.6,1,1 #This changes the label colour
        RoundedRectangle:
            size: self.size
            pos: self.pos
            radius: self.border_radius
'''

class MyApp(MDApp):
    def build(self):
        # kv = Builder.load_file("kivy.kv")
        Builder.load_string(kv_str)
        self.sm = WindowManager()

        screens = [Chat(name="chat")]
        for screen in screens:
            self.sm.add_widget(screen)

        self.sm.current = "chat"
        return self.sm


if __name__ == '__main__':
    MyApp().run()

我添加了 spacingBoxLayout 并消除了空 Labels 不再需要的。

我曾经 Builder.load_string() 而不是 load_file() 只是为了我自己方便。

© www.soinside.com 2019 - 2024. All rights reserved.