25.4.20学习总结

打印 上一主题 下一主题

主题 1715|帖子 1715|积分 5145

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
怎样使用listView组件来做聊天界面

1. 什么是CellFactory?

在JavaFX中,控件(比如ListView、TableView等)用Cell来表现每一条数据。


  • Cell:代表这个单元格(即每个列表项)中表现的内容和样式。
  • CellFactory:是一个工厂接口,负责创建和设置每个Cell。
简朴来说,
   CellFactory用于定义怎样将数据对象(比如挚友信息)转化为界面表现的单元格(Cell)。
  
2. 为什么要自定义CellFactory?

默认的Cell只表现数据的toString()方法的内容,
假如你必要自定义界面结构(比如表现头像、名字、状态指示等),
就必要自定义Cell,通过实现本身的CellFactory。
3. 怎样自定义CellFactory?



  • 自定义CellFactory的步骤:

    • 调用listView.setCellFactory();
    • 在call()中返回一个自定义的ListCell<T>;
    • 重写updateItem(),设置每个单元格的内容。

详细的步骤:

 1.创建一个消息属性类;

例如,以聊天室的聊天界面为例
  1. import javafx.scene.image.Image;
  2. public class TextMessage {
  3.     private final String content;
  4.     private final int MessageType;
  5.     private final String userName;
  6.     private final Image  profilePicture;
  7.     private final boolean isSender;
  8.     public TextMessage(String content, int MessageType, String userName, Image profilePicture, boolean isSender) {
  9.         this.content = content;
  10.         this.MessageType = MessageType;
  11.         this.userName = userName;
  12.         this.profilePicture = profilePicture;
  13.         this.isSender = isSender;
  14.     }
  15.     public String getContent() {
  16.         return content;
  17.     }
  18.     public int getMessageType() {
  19.         return MessageType;
  20.     }
  21.     public String getUserName() {
  22.         return userName;
  23.     }
  24.     public Image getProfilePicture() {
  25.         return profilePicture;
  26.     }
  27.     public boolean getIsSender() {
  28.         return isSender;
  29.     }
  30. }
复制代码
2.创建Cell类(稍后写详细代码)

其中,ListCell后跟着的是你创建的属性类。重写方法后,我们将在else里写具体代码。 
  1. public class ChatTextMessageCell extends ListCell<TextMessage> {
  2.     @Override
  3.     protected void updateItem(TextMessage item, boolean empty) {
  4.     super.updateItem(item, empty);
  5.         if (empty || item == null) {
  6.             setText(null);
  7.             setGraphic(null);
  8.         } else {
  9.         }
  10.     }
  11. }
复制代码
3.在控制器类里初始化

起首,在类里添加如下代码:
  1. private ObservableList<TextMessage> messages;
复制代码
其中,ObservableList是 JavaFX 中用于实现数据绑定的紧张接口。它答应 UI 控件主动相应数据变化。
将你的listView组件声明一下,如下,
  1. @FXML public ListView<TextMessage> chatList;
复制代码
初始化方法(注意:以initialize为名的无参方法无论加不加注解都会在应用启动时执行):
  1. @FXML public void initialize(){
  2.         messages = FXCollections.observableArrayList();
  3.         chatList.setItems(messages);
  4.         chatList.setCellFactory(param -> new ChatTextMessageCell());
  5.     }
复制代码
 4.具体写Cell类

注意:这个类对于初学者来说并不好写,可能需调解多次才华达到预期。
 对于javaFX有过了解的知道,VBox和HBox的区别,我们将在下面可能频繁使用这两个容器。
我们必要聊天界面表现的每条消息由头像,昵称,发出的消息等组成,其中,头像位于最左端或者最右端,昵称和发出的消息共同组成上下结构位于头像的另一端。也就是说,根容器,是必要展示左右两端的,我们使用HBox作为根容器,如下:
  1. HBox root = new HBox();
复制代码
之后,我们分别声明头像的组件和另一端的容器,又因为另一端是上下结构,我们使用VBox作为容器。如下:
  1. ImageView imageView = new ImageView(item.getProfilePicture());
  2. VBox messageBox = new VBox();
复制代码
之后,我们将两者放入根容器中,如下:
  1. root.getChildren().addAll(imageView, messageBox);
复制代码
 之后便是相同的操作了,依次处理上下结构即可。
显然,如许的结果不符合要求,我们还行对组件进行设置。在这便必要各位查阅官方文档了。
记得在末了加上setGraphic(root);应用设置!!!
完备代码引用:

  1. import javafx.geometry.Pos;
  2. import javafx.scene.control.Label;
  3. import javafx.scene.control.ListCell;
  4. import javafx.scene.image.ImageView;
  5. import javafx.scene.layout.HBox;
  6. import javafx.scene.layout.VBox;
  7. import javafx.scene.shape.Circle;
  8. public class ChatTextMessageCell extends ListCell<TextMessage> {
  9.     @Override
  10.     protected void updateItem(TextMessage item, boolean empty) {
  11.         super.updateItem(item, empty);
  12.         if (empty || item == null) {
  13.             setText(null);
  14.             setGraphic(null);
  15.         } else {
  16.             HBox root = new HBox();
  17.             if (item.getMessageType() == 1) {
  18.                 // 时间消息样式保持不变
  19.                 Label timeLabel = new Label(item.getContent());
  20.                 timeLabel.setStyle("-fx-font-size: 10px; -fx-text-fill: gray;");
  21.                 root.getChildren().add(timeLabel);
  22.                 root.setAlignment(Pos.CENTER);
  23.             } else {
  24.                 // ================== 头像区域 ==================
  25.                 ImageView imageView = new ImageView(item.getProfilePicture());
  26.                 imageView.setFitHeight(40);
  27.                 imageView.setFitWidth(40);
  28.                 imageView.setPreserveRatio(false);
  29.                 imageView.setClip(new Circle(20, 20, 15));
  30.                 // ================== 消息内容区域 ==================
  31.                 VBox messageBox = new VBox();
  32.                 // 昵称标签(添加左外边距贴近头像)
  33.                 Label nameLabel = new Label(item.getUserName());
  34.                 nameLabel.setStyle("-fx-font-size: 12px; -fx-text-fill: #666; /*-fx-padding: 0 0 2px 8px;*/");
  35.                 // 消息气泡
  36.                 if(item.getMessageType()==2){
  37.                     HBox bubble = new HBox();
  38.                     bubble.setMaxWidth(200);
  39.                     bubble.setStyle(
  40.                             "-fx-background-radius: 15px; " +
  41.                                     "-fx-padding: 8px 12px; " +
  42.                                     "-fx-background-color: " + (item.getIsSender() ? "#f5f5f5" : "#0099ff") + ";"
  43.                     );
  44.                     // 消息文本
  45.                     Label messageLabel = new Label(item.getContent());
  46.                     messageLabel.setStyle(
  47.                             "-fx-font-size: 14px; " +
  48.                                     "-fx-text-fill: " + (item.getIsSender() ? "black" : "white") + ";"
  49.                     );
  50.                     messageLabel.setWrapText(true);
  51.                     // ================== 布局组装 ==================
  52.                     bubble.getChildren().add(messageLabel);
  53.                     messageBox.getChildren().addAll(nameLabel, bubble);
  54.                     // 根容器设置
  55.                     root.setSpacing(5);
  56.                     if (item.getIsSender()) {
  57.                         messageBox.setAlignment(Pos.CENTER_LEFT);
  58.                         root.setAlignment(Pos.CENTER_LEFT);
  59.                         root.getChildren().addAll(imageView, messageBox);
  60.                     } else {
  61.                         messageBox.setAlignment(Pos.CENTER_RIGHT);
  62.                         root.setAlignment(Pos.CENTER_RIGHT);
  63.                         root.getChildren().addAll(messageBox, imageView);
  64.                     }
  65.                 }
  66.             }
  67.             setGraphic(root);
  68.         }
  69.     }
  70. }
复制代码
5.将listView的默认样式去除

在你的resources文件中,创建css文件,内容如下:
  1. .list-view { /* 应用于整个ListView */
  2.     -fx-background-color: WHITE; /* ListView 背景透明 */
  3. }
  4. .list-cell {
  5.     -fx-background-color: transparent; /* 单元格背景透明 */
  6.     -fx-padding: 0;                  /* 移除默认内边距 */
  7.     -fx-border: none;                /* 移除边框 */
  8.     -fx-focus-color: transparent;     /* 移除焦点效果 */
  9.     -fx-control-inner-background: transparent; /* 解决部分主题背景问题 */
  10.     -fx-text-fill: black;           /* 默认文本颜色,并保持 */
  11. }
  12. .list-cell:hover {
  13.     -fx-background-color: transparent; /* 悬停时透明 */
  14. }
  15. .list-cell:selected {
  16.     -fx-background-color: transparent; /* 选中时透明 */
  17. }
  18. .list-cell:selected:focused {
  19.     -fx-background-color: transparent; /* 选中并聚焦时透明 */
  20. }
  21. .list-cell:pressed {
  22.     -fx-background-color: transparent; /* 按下时透明 */
  23. }
复制代码
将此css文件导入即可。
  1. FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
  2. Scene scene = new Scene(fxmlLoader.load(), 900, 618);
  3. // 加载 CSS 文件
  4. scene.getStylesheets().add(Objects.requireNonNull(getClass().getResource("style.css")).toExternalForm());
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曂沅仴駦

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表