本文是仿微信聊天程序专栏的第八篇文章,主要记录了【聊天窗口】的界面实现。

界面设计

聊天窗口是整个聊天程序的核心控件,比较复杂,大致可以分为上中下三个部分,上面显示用户昵称以及一些操作菜单,中间是聊天内容显示区域,下面的信息发送的区域,总体界面设计如下:

界面布局

根据界面设计的划分,将整个聊天窗口布局划分为上中下三个部分,中间使用WebView用于显示聊天内容,完整的fxml布局代码如下:

<StackPane prefHeight="610.0"
           prefWidth="546.0" stylesheets="@ChatMainController.css"
           xmlns:fx="http://javafx.com/fxml"
           fx:controller="michong.javafx.wx.view.chat.ChatMainController">
    <SplitPane dividerPositions="0.65" orientation="VERTICAL" styleClass="chat-main-pane">
        <items>
            <VBox>
                <children>
                    <HBox alignment="CENTER" prefHeight="40.0" styleClass="chat-main-menu">
                        <children>
                            <Label fx:id="nicknameLabel" styleClass="name-label"/>
                            <Pane HBox.hgrow="ALWAYS"/>
                            <MenuButton styleClass="chat-main-menu-more">
                                <items>
                                    <MenuItem text="清空" styleClass="chat-main-menu-item" onAction="#onClearClick"/>
                                    <MenuItem text="关闭" styleClass="chat-main-menu-item" onAction="#onCloseClick"/>
                                </items>
                            </MenuButton>
                        </children>
                        <padding>
                            <Insets left="20.0" right="5.0"/>
                        </padding>
                    </HBox>
                    <Separator styleClass="wx-separator"/>
                    <!--<Pane VBox.vgrow="ALWAYS"/>-->
                    <WebView fx:id="chatWebView" VBox.vgrow="ALWAYS"/>
                </children>
            </VBox>
            <VBox alignment="TOP_RIGHT" styleClass="chat-main-input">
                <children>
                    <HBox spacing="10.0">
                        <children>
                            <Button styleClass="face-button"/>
                            <Button styleClass="message-button"/>
                            <Pane HBox.hgrow="ALWAYS"/>
                            <Button styleClass="audio-button"/>
                            <Button styleClass="video-button"/>
                        </children>
                        <padding>
                            <Insets bottom="5.0" left="20.0" right="20.0" top="5.0"/>
                        </padding>
                    </HBox>
                    <StackPane VBox.vgrow="ALWAYS">
                        <children>
                            <TextArea fx:id="messageTextArea" wrapText="true"/>
                        </children>
                        <padding>
                            <Insets bottom="5.0" left="20.0" right="20.0" top="5.0"/>
                        </padding>
                    </StackPane>
                    <ButtonBar prefHeight="80.0">
                        <buttons>
                            <Button styleClass="wx-btn-send" text="发送(S)" onAction="#onSendClick"/>
                        </buttons>
                        <padding>
                            <Insets bottom="5.0" right="20.0" top="5.0"/>
                        </padding>
                    </ButtonBar>
                </children>
            </VBox>
        </items>
    </SplitPane>
</StackPane>

样式美化

跟其他界面一样,JavaFX默认提供的控件样式风格跟聊天程序并不搭,所以聊天窗口仍需要进行样式美化,完整的CSS代码如下:

.chat-main-pane {
  -fx-background-color: #fafafa;
  -fx-border-color: transparent;
}

.chat-main-pane .button {
  -fx-cursor: hand;
  -fx-background-color: transparent;
  -fx-border-color: transparent;
  -fx-pref-width: 30px;
  -fx-pref-height: 30px;
  -fx-background-size: 30px 30px;
}

.chat-main-menu {
  -fx-background-color: #fafafa;
}

.name-label {
  -fx-font-size: 20px;
  -fx-text-fill: black;
}

.chat-main-menu-more {
  -fx-cursor: hand;
  -fx-background-color: transparent;
  -fx-border-color: transparent;
  -fx-pref-width: 44px;
  -fx-pref-height: 30px;
  -fx-background-size: 44px 30px;
  -fx-background-image: url("/icon/more.png");
}
.chat-main-menu-item {
  -fx-padding: 5 0 5 5;
}
.chat-main-menu-item:hover,
.chat-main-menu-item:focused {
  -fx-cursor: hand;
  -fx-background-color: #dbd9d8;
}
.chat-main-menu-item:hover .label,
.chat-main-menu-item:focused .label {
  -fx-text-fill: black;
}

.separator .line {
  -fx-border-color: derive(#eee9e9, 20%);
  -fx-border-width: 1;
}

.chat-main-input > * {
  -fx-background-color: #ffffff;
}

.face-button {
  -fx-background-image: url("/icon/face_0.png");
}
.face-button:hover {
  -fx-background-image: url("/icon/face_1.png");
}
.message-button {
  -fx-background-image: url("/icon/message_0.png");
}
.message-button:hover {
  -fx-background-image: url("/icon/message_1.png");
}
.audio-button {
  -fx-background-image: url("/icon/audio_0.png");
}
.audio-button:hover {
  -fx-background-image: url("/icon/audio_0.png");
}
.video-button {
  -fx-background-image: url("/icon/video_0.png");
}
.video-button:hover {
  -fx-background-image: url("/icon/video_0.png");
}

.send-button {
  -fx-padding: 5px 10px;
  -fx-font-size: 12px;
  -fx-background-color: #f5f5f5;
}
.send-button:hover {
  -fx-cursor: hand;
  -fx-text-fill: #ffffff;
  -fx-background-color: #5cb85c;
  -fx-border-color: #4cae4c;
}
.text-area {
  -fx-font-size: 14px;
  -fx-padding: 0;
  -fx-cursor: default;
  -fx-background-color: #ffffff;
}
.text-area .content {
  -fx-cursor: text;
  -fx-background-color: #ffffff;
}
.text-area:focused .content {
  -fx-background-color: #ffffff;
}

逻辑控制

调整原来聊天列表的事件控制逻辑,当单击聊天列表项时显示聊天信息界面,这里只是静态显示,动态拉取聊天信息后续功能将继续完善,控制代码如下:

void initializeEvent() {
    chatListView.getSelectionModel().selectedItemProperty().addListener((obj, ov, nv) -> {
        if (Objects.nonNull(nv)) {
            Pane main = FXComponent.mainComponent();
            main.getChildren().clear();
            main.getChildren().add(FXComponent.chatMainComponent(nv.getId()));
        }
    });
}

数据填充

跟好友信息的处理方式类似,这里直接给出Controller的代码:

/**
 * @author michong
 */
public class ChatMainController implements UserDataController {
    public Label nicknameLabel;
    public WebView chatWebView;
    public TextArea messageTextArea;

    private Long contactsId;

    @Override
    public void initialize(Object data) {
        contactsId = (Long) data;
        initializeUI();
        initializeEvent();
        renderDebugData();
    }

    void initializeUI() {
    }

    void initializeEvent() {
    }

    void renderDebugData() {
        nicknameLabel.setText("WxID: " + contactsId);
    }

    public void onClearClick(ActionEvent actionEvent) {
    }

    public void onCloseClick(ActionEvent actionEvent) {
    }

    public void onSendClick(ActionEvent actionEvent) {
    }
}

更多细节,可以查看第7节【好友信息】的实现。

posted on 2023-07-16 13:37  ql1710  阅读(87)  评论(0编辑  收藏  举报