You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX中如何通知所有监听指定事件的组件?

全局通知ChatEvent监听器组件的解决方案

现有代码

事件定义

/**
 * 消息事件
 */
public class ChatEvent extends Event {
    public static final EventType<ChatEvent> CHAT_ANY = new EventType<>(Event.ANY, "CHAT");

    public static final EventType<ChatEvent> RECEIVE_CHAT = new EventType<>(CHAT_ANY, "CHAT_RECEIVE");

    private final Chat.ChatMessage chatMessage ;

    public ChatEvent(EventType<? extends Event> eventType, Chat.ChatMessage chatMessage ) {
        super(eventType);
        this.chatMessage = chatMessage ;
    }

    @Override
    public Object getSource() {
        return chatMessage;
    }

    public Chat.ChatMessage getChatMessage(){
        return chatMessage;
    }

    public ChatEvent(Object source, EventTarget target, EventType<? extends Event> eventType,Chat.ChatMessage chatMessage) {
        super(source, target, eventType);
        this.chatMessage = chatMessage;
    }
}

组件事件处理器

receiveMessage.addEventHandler(ChatEvent.RECEIVE_CHAT , (chat)-> {
            log.info("client receive message");
            Chat.ChatMessage chatMessage = chat.getChatMessage();
            MessagePane msgPane = new MessagePane(chatMessage);
            vBox.getChildren().add(msgPane);
            receiveMessage.setText(chatMessage.getContent());
        });

当前事件触发方式

Runnable fireEvent = () -> EventUtil.fireEvent( receiveMessage,chatEvent );
if (!Platform.isFxApplicationThread()){
    Platform.runLater(fireEvent);
}
else {
    fireEvent.run();
}

核心问题

当前EventUtil.fireEvent仅能触发指定组件的监听器,无法通知所有注册了ChatEvent.RECEIVE_CHAT的组件。

解决方案

要实现全局通知所有注册监听器的组件,推荐使用**事件总线(Event Bus)**模式,具体实现如下:

1. 实现全局事件总线

创建单例事件总线类,统一管理ChatEvent监听器并负责事件分发:

import javafx.application.Platform;
import javafx.event.EventHandler;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.List;

public class ChatEventBus {
    // 用CopyOnWriteArrayList避免并发修改异常
    private final List<EventHandler<ChatEvent>> listeners = new CopyOnWriteArrayList<>();
    // 单例实例
    private static final ChatEventBus INSTANCE = new ChatEventBus();

    private ChatEventBus() {}

    public static ChatEventBus getInstance() {
        return INSTANCE;
    }

    // 注册监听器
    public void registerListener(EventHandler<ChatEvent> listener) {
        if (listener != null && !listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    // 移除监听器,避免内存泄漏
    public void unregisterListener(EventHandler<ChatEvent> listener) {
        listeners.remove(listener);
    }

    // 触发事件,确保在FX应用线程执行
    public void fireEvent(ChatEvent event) {
        if (Platform.isFxApplicationThread()) {
            dispatchEvent(event);
        } else {
            Platform.runLater(() -> dispatchEvent(event));
        }
    }

    private void dispatchEvent(ChatEvent event) {
        for (EventHandler<ChatEvent> listener : listeners) {
            listener.handle(event);
        }
    }
}

2. 修改组件监听器注册方式

不再向单个组件注册,改为向事件总线注册:

// 替换原有的receiveMessage.addEventHandler方式
ChatEventBus.getInstance().registerListener((chat)-> {
            log.info("client receive message");
            Chat.ChatMessage chatMessage = chat.getChatMessage();
            MessagePane msgPane = new MessagePane(chatMessage);
            vBox.getChildren().add(msgPane);
            receiveMessage.setText(chatMessage.getContent());
        });

3. 修改事件触发逻辑

直接调用事件总线的fireEvent方法,无需指定目标组件:

ChatEventBus.getInstance().fireEvent(chatEvent);

注意事项

  • 组件销毁时务必调用ChatEventBus.getInstance().unregisterListener(listener),避免内存泄漏
  • 若后续扩展多种ChatEvent类型,可在事件总线中按EventType分类维护监听器列表

内容的提问来源于stack exchange,提问作者Peng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 06:55:10