使用 Python 创建聊天应用
在本教程中,我们将创建一个简单的内存聊天应用,帮助您了解 Flet 框架的基础知识。这个应用可以作为您自己的更复杂和有用的项目的起点。
在本教程中,您将学习如何:
完整的应用程序如下所示:
您可以在此处查看实时演示:https://flet-chat.fly.dev。
完整的应用程序代码可以在此处找到:https://github.com/flet-dev/examples/blob/main/python/tutorials/chat/chat.py。
入门
让我们从 "Hello, world!" 应用程序开始!
要创建一个多平台应用程序,需要安装 Flet,并且需要基本的 Python 和面向对象编程知识。
在创建第一个 Flet 应用程序之前,您需要 设置开发环境,这需要 Python 3.8 或更高版本和 flet
包。
一旦安装了 Flet,让我们创建一个简单的 hello-world 应用程序。
创建 hello.py
文件,内容如下:
import flet as ft
def main(page: ft.Page):
page.add(ft.Text(value="Hello, world!"))
ft.app(target=main)
运行此应用程序,您将看到一个新窗口显示问候语:
添加页面控件和处理事件
首先,我们希望能够接受用户输入(聊天消息)并在屏幕上显示消息历史。该布局如下所示:
要实现此布局,我们将使用以下 Flet 控件:
- Column - 一个容器,用于垂直显示聊天消息(Text 控件)。
- Text - 在聊天 Column 中显示的聊天消息。
- TextField - 输入控件,用于接受用户的新消息输入。
- ElevatedButton - "发送" 按钮,用于将新消息添加到聊天 Column 中。
- Row - 一个容器,用于水平显示 TextField 和 ElevatedButton。
创建 chat.py
文件,内容如下:
import flet as ft
def main(page: ft.Page):
chat = ft.Column()
new_message = ft.TextField()
def send_click(e):
chat.controls.append(ft.Text(new_message.value))
new_message.value = ""
page.update()
page.add(
chat, ft.Row(controls=[new_message, ft.ElevatedButton("Send", on_click=send_click)])
)
ft.app(target=main)
当用户单击 "发送" 按钮时,会触发 on_click
事件,该事件调用 send_click
方法。 send_click
方法会将新 Text
控件添加到 Column 的 controls
列表中,并清除 new_message
TextField 的值。
更新控件的任何属性后,应调用控件(或其父控件)的 update()
方法,以使更新生效。
聊天应用程序现在如下所示:
广播聊天消息
在前面的步骤中,我们创建了一个简单的应用程序,接受用户输入并在屏幕上显示聊天消息。如果您在两个 Web 浏览器标签中打开此应用程序,它将创建两个应用程序会话。每个会话都有自己的消息列表。
要在本地打开应用程序的两个 Web 浏览器标签,请运行以下命令:
flet run --web <path_to_your
我将继续翻译剩余的内容。
## 广播聊天消息
在前面的步骤中,我们创建了一个简单的应用程序,接受用户输入并在屏幕上显示聊天消息。如果您在两个 Web 浏览器标签中打开此应用程序,它将创建两个应用程序会话。每个会话都有自己的消息列表。
:::note
要在本地打开应用程序的两个 Web 浏览器标签,请运行以下命令:
```bash
flet run --web <path_to_your_app>
一旦打开,复制 URL 并粘贴到新标签中。
要构建实时聊天应用程序,我们需要以某种方式在聊天应用程序会话之间传递消息。当用户发送消息时,它应该广播给所有其他应用程序会话并显示在它们的页面上。
Flet 提供了一个简单的内置 PubSub 机制,用于应用程序会话之间的异步通信。
首先,我们需要订阅用户接收广播消息:
page.pubsub.subscribe(on_message)
pubsub.subscribe()
方法将当前应用程序会话添加到订阅者列表中。它接受 handler
作为参数,该参数将在发布者调用 pubsub.send_all()
方法时被调用。
在 handler
中,我们将添加新消息(Text
)到聊天 controls
列表中:
def on_message(message: Message):
chat.controls.append(ft.Text(f"{message.user}: {message.text}"))
page.update()
最后,我们需要在用户单击 "发送" 按钮时调用 pubsub.send_all()
方法:
def send_click(e):
page.pubsub.send_all(Message(user=page.session_id, text=new_message.value))
new_message.value = ""
page.update()
pubsub.send_all()
将调用 on_message()
并传递 Message
对象。
这里是此步骤的完整代码:
import flet as ft
class Message():
def __init__(self, user: str, text: str):
self.user = user
self.text = text
def main(page: ft.Page):
chat = ft.Column()
new_message = ft.TextField()
def on_message(message: Message):
chat.controls.append(ft.Text(f"{message.user}: {message.text}"))
page.update()
page.pubsub.subscribe(on_message)
def send_click(e):
page.pubsub.send_all(Message(user=page.session_id, text=new_message.value))
new_message.value = ""
page.update()
page.add(chat, ft.Row([new_message, ft.ElevatedButton("Send", on_click=send_click)]))
ft.app(target=main)
用户名对话框
聊天应用程序现在已经具有基本功能,用于在用户会话之间交换消息。然而,它不太用户友好,因为它显示 session_id
,而不是用户名。
让我们改进应用程序,以显示用户名而不是 session_id
。为此,我们将使用 AlertDialog
控件。让我们将其添加到页面:
user_name = ft.TextField(label="输入您的名字")
page.dialog = ft.AlertDialog(
open=True,
modal=True,
title=ft.Text("欢迎!"),
content=ft.Column([user_name], tight=True),
actions=[ft.ElevatedButton(text="加入聊天", on_click=join_click)],
actions_alignment="end",
)
对话框将在程序开始时打开,因为我们将其 open
属性设置为 True
。
当用户单击 "加入聊天" 按钮时,将调用 join_click
方法,该方法应发送消息给所有订阅者,通知他们用户已加入聊天。该消息应与常规聊天消息不同,例如:
让我们向 Message
类添加 message_type
属性,以区分登录消息和聊天消息:
class Message():
def __init__(self, user: str, text: str, message_type: str):
self.user = user
self.text = text
self.message_type = message_type
我们将在 on_message
方法中检查 message_type
:
def on_message(message: Message):
if message.message
我将继续翻译剩余的内容。
## 用户名对话框
聊天应用程序现在已经具有基本功能,用于在用户会话之间交换消息。然而,它不太用户友好,因为它显示 `session_id`,而不是用户名。
让我们改进应用程序,以显示用户名而不是 `session_id`。为此,我们将使用 [`AlertDialog`](/docs/controls/alertdialog) 控件。让我们将其添加到页面:
```python
user_name = ft.TextField(label="输入您的名字")
page.dialog = ft.AlertDialog(
open=True,
modal=True,
title=ft.Text("欢迎!"),
content=ft.Column([user_name], tight=True),
actions=[ft.ElevatedButton(text="加入聊天", on_click=join_click)],
actions_alignment="end",
)
对话框将在程序开始时打开,因为我们将其 open
属性设置为 True
。
当用户单击 "加入聊天" 按钮时,将调用 join_click
方法,该方法应发送消息给所有订阅者,通知他们用户已加入聊天。该消息应与常规聊天消息不同,例如:
让我们向 Message
类添加 message_type
属性,以区分登录消息和聊天消息:
class Message():
def __init__(self, user: str, text: str, message_type: str):
self.user = user
self.text = text
self.message_type = message_type
我们将在 on_message
方法中检查 message_type
:
def on_message(message: Message):
if message.message_type == "chat_message":
chat.controls.append(ft.Text(f"{message.user}: {message.text}"))
elif message.message_type == "login_message":
chat.controls.append(
ft.Text(message.text, italic=True, color=ft.colors.BLACK45, size=12)
)
page.update()