当前位置: 首页 > 知识库问答 >
问题:

如何在onMessage事件侦听器中向ObservableList添加项

麻宜春
2023-03-14

我用JavaFx制作了两个简单的JMS应用程序(一个是发送者,另一个是接收者)。

但是,我不能用来自发送方的新消息刷新接收方的GUI。

我使用onMessage事件在internet上查找,并重写了它(向那里的ObservableList添加一个项),但它不起作用。引发事件后,没有向ObservableList添加任何元素

这是我的听筒:

public class Administrator extends Application {
    private ObservableList<String> observableList;
    private final String DESTINATION_TYPE = "queue";
    private final String RECEIVE_CHANNEL = "askDestination";
    private final String SEND_CHANNEL = "answerDestination";
    private MessageConsumer messageConsumer;
    private MessageProducer messageProducer;
    private Session session;
    private Destination destination;
    private Connection connection;

    @FXML
    public TextField tfMessage;

    @FXML
    public ListView<String> lvMessage;

    @FXML
    public Button btnSend;

    @Override
    public void start(Stage stage) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("administratorUI.fxml"));
        stage.setTitle("Administrator");
        stage.setScene(new Scene(root, 640, 480));
        stage.setResizable(false);
        stage.show();
    }

    @Override
    public void init() throws Exception {
        super.init();
        lvMessage = new ListView<>();
        tfMessage = new TextField();
        //questionList = new ArrayList<>();
        observableList = FXCollections.observableArrayList();
        lvMessage.setItems(observableList);
        initService(RECEIVE_CHANNEL, DESTINATION_TYPE);
        getMessage(RECEIVE_CHANNEL);
        //Platform.runLater(this::updateLV);
    }

    public static void main(String[] args) {
        launch();
    }

    public void onButtonAnswerClick() {
        String message = tfMessage.getText();

        if (message.equals("")) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setContentText("Please enter your message!!");
            alert.show();
            return;
        }

        if (replyToQuestion(message, SEND_CHANNEL)) {
            tfMessage.clear();
        } else {
            handleServiceError("Service Error", "Could not send the message to the service");
        }
    }

    private void handleServiceError(String errorTitle, String errorText){
        Alert error = new Alert(Alert.AlertType.ERROR);
        error.setTitle(errorTitle);
        error.setContentText(errorText);
    }

    private void updateLV(){
        lvMessage.getItems().clear();
        lvMessage.setItems(observableList);
    }

    private void initService(String targetDestination, String destinationType){
        try {
            Properties props = new Properties();
            props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                    "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
            props.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");

            // connect to the Destination called “myFirstChannel”
            // queue or topic: “queue.myFirstDestination” or “topic.myFirstDestination”
            props.put((destinationType + "." + targetDestination), targetDestination);
            Context jndiContext = new InitialContext(props);
            ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");

            // to connect to the JMS
            connection = connectionFactory.createConnection();

            // session for creating consumers
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            // connect to the receiver destination
            //reference to a queue/topic destination
            destination = (Destination) jndiContext.lookup(targetDestination);
        } catch (NamingException | JMSException e) {
            e.printStackTrace();
        }
    }

    private boolean replyToQuestion(String message, String sendDestination) {
        try {
            initService(sendDestination, DESTINATION_TYPE);

            // for sending messages
            messageProducer = session.createProducer(destination);

            // create a text message
            Message msg = session.createTextMessage(message);

            msg.setJMSMessageID("222");
            System.out.println(msg.getJMSMessageID());

            // send the message
            messageProducer.send(msg);

            //questionList.add(message);
            updateLV();
            return true;
        } catch (JMSException e) {
            e.printStackTrace();
            return false;
        }
    }

    private void getMessage(String receiveDestination) {
        try {
            initService(receiveDestination, DESTINATION_TYPE);

            // this is needed to start receiving messages
            connection.start();

            // for receiving messages
            messageConsumer = session.createConsumer(destination);
            MessageListener listener = message -> {
                try {
                    observableList.add(((TextMessage)message).getText());
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            };

            messageConsumer.setMessageListener(listener);
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

我的发件人:

    public class User extends Application implements MessageListener {
    private static List<String> questions;
    private final String DESTINATION_TYPE = "queue";
    private final String RECEIVE_CHANNEL = "answerDestination";
    private final String SEND_CHANNEL = "askDestination";
    private String requestId;
    private MessageConsumer messageConsumer;
    private MessageProducer messageProducer;
    private Session session;
    private Destination destination;
    private Connection connection;

    @FXML
    public Button btnSend;

    @FXML
    public TextField tfMessage;

    @FXML
    public ListView lvMessage;

    @Override
    public void start(Stage stage) throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("userUI.fxml"));
        stage.setTitle("Sender");
        stage.setScene(new Scene(root, 640, 480));
        stage.setResizable(false);
        stage.show();
    }

    @Override
    public void init() throws Exception {
        super.init();
        btnSend = new Button();
        tfMessage = new TextField();
        lvMessage = new ListView();
        questions = new ArrayList<>();
        initService(RECEIVE_CHANNEL, DESTINATION_TYPE);
        getAnswer(RECEIVE_CHANNEL);
    }

    public static void main(String[] args){
        launch(args);
    }

    public void onButtonSendClick(javafx.event.ActionEvent actionEvent) {
        String message = tfMessage.getText();

        if (message.equals("")) {
            Alert alert = new Alert(Alert.AlertType.ERROR);
            alert.setContentText("Please enter your question!!");
            alert.show();
            return;
        }

        if (sendQuestion(message, SEND_CHANNEL)) {
            tfMessage.clear();
        } else {
            handleServiceError("Service Error", "Could not send the message tot the service");
        }
    }

    private void handleServiceError(String errorTitle, String errorText){
        Alert error = new Alert(Alert.AlertType.ERROR);
        error.setTitle(errorTitle);
        error.setContentText(errorText);
    }

    private void updateLV(){
        lvMessage.getItems().clear();
        lvMessage.getItems().addAll(questions);
    }

    private void initService(String targetDestination, String destinationType){
        try {
            Properties props = new Properties();
            props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                    "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
            props.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");

            // connect to the Destination called “myFirstChannel”
            // queue or topic: “queue.myFirstDestination” or “topic.myFirstDestination”
            props.put((destinationType + "." + targetDestination), targetDestination);
            Context jndiContext = new InitialContext(props);
            ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup("ConnectionFactory");

            // to connect to the JMS
            connection = connectionFactory.createConnection();
            // session for creating consumers
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            // connect to the receiver destination
            //reference to a queue/topic destination
            destination = (Destination) jndiContext.lookup(targetDestination);
        } catch (NamingException | JMSException e) {
            e.printStackTrace();
        }
    }

    private boolean sendQuestion(String message, String sendDestination) {
        try {
            initService(sendDestination, DESTINATION_TYPE);

            // for sending messages
            messageProducer = session.createProducer(destination);

            // create a text message
            Message msg = session.createTextMessage(message);

            msg.setJMSMessageID("111");
            System.out.println(msg.getJMSMessageID());

            // send the message
            messageProducer.send(msg);

            //questionList.add(message);
            updateLV();
            return true;
        } catch (JMSException e) {
            e.printStackTrace();
            return false;
        }
    }

    private void getAnswer(String receiveDestination) {
        try {
            initService(receiveDestination, DESTINATION_TYPE);

            // for receiving messages
            messageConsumer = session.createConsumer(destination);
            messageConsumer.setMessageListener(this);


            // this is needed to start receiving messages
            connection.start();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onMessage(Message message) {
        try {
            questions.add(((TextMessage)message).getText());
            requestId = message.getJMSMessageID();
            System.out.println(requestId);
            updateLV();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}
    <GridPane hgap="10" prefHeight="400.0" prefWidth="600.0" vgap="10" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Administrator">
    <padding>
        <Insets bottom="10" left="10" right="10" top="10" />
    </padding>
    <Label text="Current question:" textFill="cornflowerblue" GridPane.columnIndex="0" GridPane.rowIndex="0">
        <font>
            <Font name="System Bold" size="15.0" />
        </font>
    </Label>
    <ListView fx:id="lvMessage" prefWidth="600" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="1">

    </ListView>

    <HBox spacing="10" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2">
        <TextField fx:id="tfMessage" prefHeight="61.0" prefWidth="504.0" promptText="Type your answer here...">
            <font>
                <Font size="15.0" />
            </font>
        </TextField>
        <Button fx:id="btnSend" onAction="#onButtonAnswerClick" prefHeight="61.0" prefWidth="88.0" text="Send">
        </Button>
    </HBox>
   <columnConstraints>
      <ColumnConstraints />
      <ColumnConstraints />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints />
      <RowConstraints />
      <RowConstraints />
   </rowConstraints>
</GridPane>

共有1个答案

楮法
2023-03-14

结果是我在错误的线程上更新了ListView。对于那些仍然对答案感兴趣的人,我使用了:platform.runlater()并在start方法中注册了事件侦听器(在stage.show()之前)

 类似资料:
  • 我的代码使用jQuery。我有一个密码输入框,我想要得到输入的密码任何时候。 下面是我的代码: 我确信这是一个正确的代码,因为当我在浏览器的控制台中输入它时,它可以工作,但当我重新加载页面时,它就不工作了 我能做什么?

  • 我可以在下面的代码中为添加事件侦听器,但不能添加到。 是不是因为twitter做了一些事情不让我这么做?有办法绕过它吗?

  • 将事件侦听器添加到可以使用事件委派的元素。 使用 EventTarget.addEventListener() 将一个事件监听器添加到一个元素。 如果提供了 选项对象(opts) 的 target 属性,确保事件目标匹配指定的目标元素,然后通过提供正确的 this 上下文来调用回调。 返回一个对自定义委派函数的引用,以便与 off 一起使用。 忽略 opts ,则默认为非委派行为,并且事件冒泡。

  • 我想在Java中添加一个按钮侦听器,这样当用户只需按下按钮时,按钮就会被按下。 我尝试将此操作监听器添加到我创建的按钮: 这就是整个功能: 然而,当我的gui出现时,我在输入输入后按“回车”键,什么也没有发生。我必须亲自点击按钮,这正是我试图避免的! 这是我创建的窗口: 我希望用户输入一个数字,然后按enter键,然后单击按钮。帮助我做错了什么?

  • 我正在用canvas构建一个新的Javascript游戏,我想为每个对象添加一个事件监听器。我想画一个有用的操纵杆(箭头),当游戏从智能手机/平板电脑打开。所以,玩家可以通过点击每个箭头来移动角色。 这就是我所拥有的: game.js:

  • 问题内容: 我有一个类似的反应成分: 这里,事件列表器已添加到组件。当我刷新页面时,它弹出窗口要求离开页面。 但是当我转到另一个页面并刷新时,它再次显示相同的弹出窗口。 我正在从中删除组件。那为什么不将其删除呢? 如何删除其他页面上的事件? 问题答案: 本应该得到的引用到在分配相同的回调。重新创建该功能将无效。解决方案是在其他地方(在本示例中)创建回调,并将其作为对和的引用传递: 反应钩子 您可以