Java Swing Worker导致GUI冻结

时间:2015-03-10 14:58:18

标签: java swing

您好,我正在尝试使用RMI实现聊天。该算法如下:共享RMI对象和客户端都有一个String变量用于最后输入的消息。每当客户端键入消息时,来自共享RMI对象的消息都会更新(messageRMI = messageClient)。如果客户端的最后一条消息没有与RMI对象中的消息相同,则最后一条消息将自动输入到jTextPane中。

这是摇摆工作者:

    SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
        @Override
        protected Void doInBackground()
            throws Exception {
            byte[] the_image;
            while (true) {
                Thread.sleep(1000);
                if (connected) {
                    try {
                        remote = (I) Naming.lookup("rmi://" + jTextFieldAddress.getText() + "/Niemand23");
                        switch (remote.refresh_chat(last_message)) {
                            case 0:
                                last_message = remote.last_message();
                                jTextPane1.getStyledDocument().insertString(jTextPane1.getDocument().getLength(), "\n ", null);
                                if (remote.hasImage()) {
                                    the_image = remote.client_image();
                                    formatC = new ImageIcon(the_image);
                                    jTextPane1.insertIcon(formatC);
                                } else {
                                    jTextPane1.insertIcon(noImageIcon);
                                }
                                jTextPane1.getStyledDocument()
                                    .insertString(jTextPane1.getDocument().getLength(), "\n " + remote.last_message(), style);
                                jTextPane1.getStyledDocument().insertString(jTextPane1.getDocument().getLength(), "\n", null);
                        }
                    } catch (NotBoundException | MalformedURLException | RemoteException | BadLocationException ex) {
                        Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    };

工人应该每秒检查一下情况。最大的问题是,无论何时客户端键入消息,第二个GUI都会冻结。我已经尝试了一切但没有结果。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

如果您阅读了SwingWorker javadocs,则表示您不应该在doInBackground()方法中直接更改Swing组件。

相反,您应该实施process()方法并使用publish()中的doInBackground()方法。有关具体信息,请查看publish method

在您的情况下,这需要在收到时将SwingWorker<Void, Void>切换为SwingWorker<Void,String>publish()每条消息。然后,您的process(String...s)方法会使用传入的消息填充jTextPane1

尝试一下,看看它是如何工作的。

ETA :此外,您是否需要在循环的每个粗体中执行命名查找?地址不变,是吗?