25.4.22学习总结
如何通过好友列表对聊天框的切换
首先,我们知道,你的好友列表是用ListView组件实现的,那么,接下来,我们将开始讲解如何实现切换。
一、改造数据结构
如果你是跟着我的上一篇文章做的话,应该需要修改一些的。如果不是,请了解上一篇用的再添加之后讲的。
1.Map存ObservableList<TextMessage>
你的每一项好友都对应着一个ObservableList<TextMessage>,你可以ObservableList<TextMessage>理解为消息数组,这是你的UI界面的数据源。
private Map<String,ObservableList<TextMessage>>chatHistoryMap=new HashMap<>();
2.当前选中的聊天
//删除private ObservableList<>messages1;
private SimpleObjectProperty<messageListMessage> selectedChat = new SimpleObjectProperty<>();
-
SimpleObjectProperty<messageListMessage>
:-
这是一个 JavaFX 属性类,专门用于存储一个
Object
类型的引用。 在这个例子中,它存储的是messageListMessage
类型的对象。 -
JavaFX 属性 (Properties): JavaFX 属性是 JavaFX 框架的核心概念之一,用于实现数据绑定和自动 UI 更新。 它们是包装了普通 Java 字段的特殊类,并添加了以下功能:
-
可观察性 (Observability): 当属性的值发生变化时,可以通知监听器 (Listeners)。
-
绑定 (Binding): 可以将一个属性绑定到另一个属性,这样当一个属性的值发生变化时,另一个属性的值也会自动更新。
-
-
SimpleObjectProperty
: 是ObjectProperty
接口的一个具体实现类。 它提供了一个简单的方式来创建和管理一个Object
类型的 JavaFX 属性。 -
<messageListMessage>
: 这是一个 泛型类型参数,指定了SimpleObjectProperty
将存储的对象的类型。 在这里,它表示selectedChat
属性将存储messageListMessage
类型的对象。messageListMessage
应该是你自定义的一个类,表示聊天消息的信息。
-
3.修改聊天会话
// 删除 private ObservableList<TextMessage> messages;
private ObservableList<messageListMessage> chatSessions = FXCollections.observableArrayList();
二、初始化聊天会话
在initialize()方法中添加以下代码:
1.绑定聊天会话列表
// 绑定聊天会话列表messageList.setItems(chatSessions);
2.初始化聊天记录存储
// 初始化聊天记录存储for (messageListMessage chat : chatSessions) {chatHistoryMap.put(chat.getUid(), FXCollections.observableArrayList());}
3.设置默认选中第一个会话(选做)
// 设置默认选中第一个会话messageList.getSelectionModel().selectFirst();
三、实现会话选择监听
// 在initialize()方法中添加:
messageList.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {if (newVal != null) {// 更新当前选中会话selectedChat.set(newVal);// 切换聊天记录ObservableList<TextMessage> history = chatHistoryMap.get(newVal.getUid());chatList.setItems(history);// 自动滚动到底部if (!history.isEmpty()) {chatList.scrollTo(history.size() - 1);}// 更新聊天窗口标题chatMemberText.setText(newVal.getName());}
});
-
messageList.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> { ... });
-
messageList.getSelectionModel()
: 获取messageList
(你的好友列表 ListView) 的选择模型 (SelectionModel)。 选择模型负责管理ListView
中的选中项。 -
.selectedItemProperty()
: 获取当前选中项的属性 (Property)。 这是一个ObjectProperty<messageListMessage>
,其中messageListMessage
是你自定义的类,代表一个好友。 -
.addListener((obs, oldVal, newVal) -> { ... })
: 为这个属性添加一个监听器 (Listener)。 监听器会在属性的值发生变化时被调用。-
(obs, oldVal, newVal) -> { ... }
: 这是一个 lambda 表达式,定义了监听器的回调函数。-
obs
:ObservableValue
对象,代表被监听的属性 (也就是selectedItemProperty
)。 -
oldVal
: 上一个选中的messageListMessage
对象 (在选中项变化之前的值)。 -
newVal
: 当前选中的messageListMessage
对象 (也就是新的选中项)。
-
-
总的来说,这行代码的作用是:当
messageList
(好友列表) 中选中的好友发生变化时,执行 lambda 表达式中的代码。 -
-
if (newVal != null) { ... }
-
这是一个条件判断,确保
newVal
(也就是当前选中的好友) 不为null
。 也就是说只有在真正选中了一个好友时,才会执行后面的代码。如果用户取消了选择,newVal
就会是null
,此时不应该执行后续的操作。
-
-
selectedChat.set(newVal);
-
selectedChat
: 你之前定义的SimpleObjectProperty<messageListMessage> selectedChat
,用于存储当前选中的好友对象。 -
.set(newVal)
: 将selectedChat
属性的值设置为newVal
(也就是当前选中的好友对象)。 这会更新selectedChat
的值,并通知所有监听selectedChat
属性的监听器。
这行代码的作用是:更新
selectedChat
属性,使其指向当前选中的好友。 -
-
ObservableList<TextMessage> history = chatHistoryMap.get(newVal.getUid());
-
chatHistoryMap
: 你需要定义一个Map<String, ObservableList<TextMessage>> chatHistoryMap
,用于存储每个好友的聊天记录。 其中,Key 是好友的Uid
(唯一 ID),Value 是该好友的聊天记录列表 (ObservableList<TextMessage>
)。 -
newVal.getUid()
: 获取当前选中的好友的Uid
(假设你的messageListMessage
类中有一个getUid()
方法来获取好友的 Uid)。 这个 Uid 用于从chatHistoryMap
中查找对应的聊天记录。 -
chatHistoryMap.get(newVal.getUid())
: 从chatHistoryMap
中根据好友的Uid
获取该好友的聊天记录列表。 如果chatHistoryMap
中不存在该好友的聊天记录,则返回null
。 -
ObservableList<TextMessage> history
: 将获取到的聊天记录列表赋值给history
变量。history
的类型是ObservableList<TextMessage>
,表示这是一个可观察的聊天消息列表。
这行代码的作用是:从
chatHistoryMap
中获取当前选中的好友的聊天记录列表,并将其存储在history
变量中。 -
-
chatList.setItems(history);
-
chatList
: 你的聊天消息ListView
,用于显示聊天记录。 -
.setItems(history)
: 将chatList
的数据源设置为history
(也就是当前选中好友的聊天记录列表)。 这会将聊天消息显示在chatList
中。
这行代码的作用是:将聊天消息
ListView
的数据源设置为当前选中好友的聊天记录列表,从而更新聊天界面。 -
-
if (!history.isEmpty()) { chatList.scrollTo(history.size() - 1); }
-
history.isEmpty()
: 判断history
(也就是当前选中好友的聊天记录列表) 是否为空。 -
!history.isEmpty()
: 如果history
不为空 (也就是当前选中好友有聊天记录),则执行chatList.scrollTo(history.size() - 1)
。 -
chatList.scrollTo(history.size() - 1)
: 将chatList
滚动到最后一条消息 (也就是聊天记录列表的最后一个元素)。 这样可以确保用户在切换聊天对象时,总是看到最新的聊天记录。
这行代码的作用是:如果当前选中好友有聊天记录,则将聊天消息
ListView
滚动到最后一条消息。 -
-
chatMemberText.setText(newVal.getName());
-
chatMemberText
: 你的聊天窗口标题,通常是一个Label
组件。 -
newVal.getName()
: 获取当前选中的好友的姓名 (假设你的messageListMessage
类中有一个getName()
方法来获取好友的姓名)。 -
.setText(newVal.getName())
: 将chatMemberText
的文本设置为当前选中好友的姓名。 这样可以在聊天窗口的标题栏显示当前正在聊天的对象。
这行代码的作用是:更新聊天窗口的标题,显示当前正在聊天的对象的姓名。
-
四、改造消息发送功能
@FXML
public void sendingClick(){messageListMessage currentChat = selectedChat.get();if (currentChat == null || InputArea.getText().trim().isEmpty()) return;// 创建消息对象(根据你的实际逻辑调整参数)TextMessage newMessage = new TextMessage(……);// 添加到对应的聊天记录chatHistoryMap.get(currentChat.getUid()).add(newMessage);InputArea.clear();
}