如何点击按钮向Rex ScrollablePanel添加面板实现聊天对话框?
问题:基于Rex ScrollablePanel实现聊天消息动态展示
我需要实现一个迷你聊天对话框,要求输入内容点击发送按钮后,消息能显示在Rex ScrollablePanel(滚动面板)中。目前已编写了点击事件监听和滚动面板创建代码,但将滚动面板代码移入点击事件内无法正常工作,求可行的解决建议。
现有代码
点击事件监听
this.dialogChatInput.addListener("click"); this.dialogChatInput.on("click", (event) => { if (event.target.id === "sendButton") { var inputChat = this.dialogChatInput.getChildByName("nameFieldChat"); if (inputChat.value !== "") { console.log(`Chat : ${inputChat.value}`); } } });
滚动面板创建代码
var panel = this.rexUI.add .scrollablePanel({ x: this.dialogKhungHienThi.x + 225, y: this.dialogKhungHienThi.y, height: 1200, scrollMode: 0, background: this.rexUI.add.roundRectangle({ // strokeColor: transparent, strokeWidth: 2, }), panel: { child: CreatePanel(this), }, slider: { track: this.rexUI.add.roundRectangle({ width: 20, height: 20, radius: 40, color: COLOR_TRACK, }), thumb: this.rexUI.add.roundRectangle({ radius: 50, color: COLOR_THUMB, }), }, space: { panel: 4 }, }) .layout();
面板生成函数(定义在Create()外)
var CreatePanel = function (scene, data) { var panel = scene.rexUI.add.sizer({ width: 100, orientation: "y", space: { item: 4 }, }); if (ngu) { var name = `item-${i}`; var label = scene.rexUI.add.label( { height: 350, width: 1000, background: scene.rexUI.add.roundRectangle({ // color: COLOR_PRIMARY, }), icon: scene.add.image(0, 0, "avatarDemo").setScale(2), text: scene.add .text(10, 10, ` ${hour} : ${minute}: ${second} `, { font: "70px Arial", fill: "#ffffff", stroke: "black", strokeThickness: 15, }) .setFontSize("70px"), wrapText: true, name: name, }, this ); panel.add(label, { expand: true }); } return panel; };
解决方案
1. 提前初始化滚动面板,避免重复创建
滚动面板只需在场景初始化时创建一次,不要放在点击事件里重复生成。将面板实例作为场景全局变量保存:
// 在场景类中声明全局变量 this.scrollPanel; // 在create()方法中初始化滚动面板 this.scrollPanel = this.rexUI.add .scrollablePanel({ x: this.dialogKhungHienThi.x + 225, y: this.dialogKhungHienThi.y, height: 1200, scrollMode: 0, background: this.rexUI.add.roundRectangle({ strokeWidth: 2, }), panel: { child: this.rexUI.add.sizer({ width: 100, orientation: "y", space: { item: 4 }, }), }, slider: { track: this.rexUI.add.roundRectangle({ width: 20, height: 20, radius: 40, color: COLOR_TRACK, }), thumb: this.rexUI.add.roundRectangle({ radius: 50, color: COLOR_THUMB, }), }, space: { panel: 4 }, }) .layout();
2. 修改点击事件,动态添加消息到滚动面板
点击发送按钮时,直接生成新消息元素并添加到滚动面板的内部sizer,然后更新布局并自动滚动到底部:
this.dialogChatInput.on("click", (event) => { if (event.target.id === "sendButton") { var inputChat = this.dialogChatInput.getChildByName("nameFieldChat"); if (inputChat.value !== "") { // 获取当前时间 const now = new Date(); const timeStr = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`; // 创建新消息标签 const messageLabel = this.rexUI.add.label({ height: 350, width: 1000, background: this.rexUI.add.roundRectangle(), icon: this.add.image(0, 0, "avatarDemo").setScale(2), text: this.add.text(10, 10, `${timeStr} - ${inputChat.value}`, { font: "70px Arial", fill: "#ffffff", stroke: "black", strokeThickness: 15, }).setFontSize(70), wrapText: true, name: `item-${Date.now()}` }); // 获取滚动面板内部的sizer容器 const innerSizer = this.scrollPanel.getElement("panel").child; // 添加新消息到容器 innerSizer.add(messageLabel, { expand: true }); // 重新布局滚动面板 this.scrollPanel.layout(); // 自动滚动到最新消息位置 this.scrollPanel.scrollToBottom(100); // 清空输入框 inputChat.value = ""; } } });
3. 修复CreatePanel函数的复用问题
原CreatePanel函数存在未定义变量(ngu、i等),如果需要复用消息创建逻辑,可拆分为初始化容器和创建单条消息的独立函数:
// 初始化滚动面板内部的sizer容器 function createMessageContainer(scene) { return scene.rexUI.add.sizer({ width: 100, orientation: "y", space: { item: 4 }, }); } // 创建单条消息标签的函数 function createSingleMessage(scene, content, timeStr) { return scene.rexUI.add.label({ height: 350, width: 1000, background: scene.rexUI.add.roundRectangle(), icon: scene.add.image(0, 0, "avatarDemo").setScale(2), text: scene.add.text(10, 10, `${timeStr} - ${content}`, { font: "70px Arial", fill: "#ffffff", stroke: "black", strokeThickness: 15, }).setFontSize(70), wrapText: true, name: `item-${Date.now()}` }); }
关键注意事项
- 滚动面板仅需初始化一次,重复创建会导致DOM冗余和功能异常
- 添加新消息后必须调用
layout()方法更新面板布局,否则新元素不会显示 - 使用
scrollToBottom()实现自动滚动,优化用户查看最新消息的体验 - 发送后清空输入框,避免重复发送相同内容
内容的提问来源于stack exchange,提问作者Nguyễn Hải Long
相关产品推荐
相关产品推荐

