找到你要的答案

Q:ActionListener invoke while loop method

Q:功能调用while循环的方法

I add a ActionListener which create a new chat JFrame that can send and receive message from the Server. this is the code in the ActionPerformed() method

BananaChat chat = new BananaChat(name, password, IP, port, status);
    try {
        chat.chatting();
    } catch (Exception e) {
        showInfo("fail");
    }

so it create a new chat frame, if I didn't invoke the chat.chatting() method, I can send the message to Server normally, But cannot receive the message from server. So I have to invoke this method because I need to keeping listening the message from server if it does send the message.

here is the code of chatting()

String line = null;

    try {
        while ((line = in.readLine()) != null) {
            if (line.equals("your user name is already registered") || line.equals("user name doesn't exist") || line.equals("wrong password")) {
                showMessage(line);
                break;
            }

            showMessage(line);
        }

    } catch (IOException e) {
        showMessage("can not receive the message");
    }

It is the while loop. If I create my chat frame and invoke this method in the main method, it can work, but if I create the chat frame in ActionListener, it is stuck. it seems that the ActionListener cannot have a while Loop which doesn't end at all.

I don't know how to solve it, is there a better way to create a new chat interface from the login interface?

我添加了一个功能,创建一个新的聊天功能,可以从服务器发送和接收消息。这是代码中的actionperformed()方法

BananaChat chat = new BananaChat(name, password, IP, port, status);
    try {
        chat.chatting();
    } catch (Exception e) {
        showInfo("fail");
    }

因此,创建一个新的聊天框,如果我不调用聊天。chatting()方法,我可以发送消息到服务器正常,但不能接收邮件服务器。所以我必须调用这个方法,因为我需要继续从服务器监听消息,如果它发送消息的话。

这里是chatting()代码

String line = null;

    try {
        while ((line = in.readLine()) != null) {
            if (line.equals("your user name is already registered") || line.equals("user name doesn't exist") || line.equals("wrong password")) {
                showMessage(line);
                break;
            }

            showMessage(line);
        }

    } catch (IOException e) {
        showMessage("can not receive the message");
    }

It is the while loop. If I create my chat frame and invoke this method in the main method, it can work, but if I create the chat frame in ActionListener, it is stuck. it seems that the ActionListener cannot have a while Loop which doesn't end at all.

我不知道如何解决它,有一个更好的方法来创建一个新的聊天界面从登录界面?

answer1: 回答1:

As already suggested by kiheru, it is probably a good idea to run your chatting code in a background thread - for example using a SwingWorker (which is made especially for use with Swing GUIs). With some guess work regarding the BananaChat class, a very simple (one directional) chat program could look like this:

A main class:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class Chat {
    private int nextPort = 80;

    public static void main(final String[] args) {
        new Chat().launchGui();
    }

    private void launchGui() {
        final JFrame frame = new JFrame("Stack Overflow: chat with multiple servers");
        frame.setBounds(100, 100, 800, 600);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        final JButton startChatButton = new JButton("Start a new chat");
        startChatButton.addActionListener(actionEvent -> {
            final BananaChat bananaChat = new BananaChat("user name", "password",
                "192.0.0.1", String.valueOf(nextPort), "???");
            nextPort++;
            bananaChat.startChatting();
        });
        panel.add(startChatButton);
        frame.getContentPane().add(panel);
        frame.setVisible(true);
    }
}

A BananaChat class:

import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class BananaChat extends JFrame {
    private final String userName;
    private final String password;
    private final String IP;
    private final String port;
    private final String status;
    private final Random dummyServerMessages;
    private final JTextArea messagesTextArea;

    public BananaChat(final String userName, final String password, final String IP,
                      final String port, final String status) {
        super("Chat with " + IP + ":" + port);
        this.userName = userName;
        this.password = password;
        this.IP = IP;
        this.port = port;
        this.status = status;
        dummyServerMessages = new Random(123456);
        messagesTextArea = new JTextArea();
        add(new JScrollPane(messagesTextArea));
        setBounds(1000, 100, 400, 200);
        setVisible(true);
    }

    public void startChatting() {
        final SwingWorker chatWorker = new SwingWorker<Void, String>() {
            @Override
            protected Void doInBackground() {
                while (!isCancelled()) {
                    final String message = getMessageFromServer();
                    publish(message + "\n");
                    pause(1000);
                }
                return null;
            }

            @Override
            protected void process(final List<String> messages) {
                messages.forEach(messagesTextArea::append);
            }
        };

        chatWorker.execute();
    }

    // Generate silly random messages. Can be replaced by a call to in.readLine().
    private String getMessageFromServer() {
        final String message;
        if (dummyServerMessages.nextInt(6) < 2)
            message = "Hello";
        else
            message = "Silence";
        return message + " from " + userName + "@" + IP + ":" + port;
    }

    private void pause(final int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getPassword() {
        return password;
    }

    public String getStatus() {
        return status;
    }
}

正如已经指出的kiheru,它在使用SwingWorker例如后台线程运行你的聊天代码可能是一个好主意(这是特别为使用Swing GUI)。一些想工作对于bananachat类,一个很简单的(一个方向)的聊天程序可能看起来像这样:

主类:

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class Chat {
    private int nextPort = 80;

    public static void main(final String[] args) {
        new Chat().launchGui();
    }

    private void launchGui() {
        final JFrame frame = new JFrame("Stack Overflow: chat with multiple servers");
        frame.setBounds(100, 100, 800, 600);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        final JButton startChatButton = new JButton("Start a new chat");
        startChatButton.addActionListener(actionEvent -> {
            final BananaChat bananaChat = new BananaChat("user name", "password",
                "192.0.0.1", String.valueOf(nextPort), "???");
            nextPort++;
            bananaChat.startChatting();
        });
        panel.add(startChatButton);
        frame.getContentPane().add(panel);
        frame.setVisible(true);
    }
}

一个bananachat类:

import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class BananaChat extends JFrame {
    private final String userName;
    private final String password;
    private final String IP;
    private final String port;
    private final String status;
    private final Random dummyServerMessages;
    private final JTextArea messagesTextArea;

    public BananaChat(final String userName, final String password, final String IP,
                      final String port, final String status) {
        super("Chat with " + IP + ":" + port);
        this.userName = userName;
        this.password = password;
        this.IP = IP;
        this.port = port;
        this.status = status;
        dummyServerMessages = new Random(123456);
        messagesTextArea = new JTextArea();
        add(new JScrollPane(messagesTextArea));
        setBounds(1000, 100, 400, 200);
        setVisible(true);
    }

    public void startChatting() {
        final SwingWorker chatWorker = new SwingWorker<Void, String>() {
            @Override
            protected Void doInBackground() {
                while (!isCancelled()) {
                    final String message = getMessageFromServer();
                    publish(message + "\n");
                    pause(1000);
                }
                return null;
            }

            @Override
            protected void process(final List<String> messages) {
                messages.forEach(messagesTextArea::append);
            }
        };

        chatWorker.execute();
    }

    // Generate silly random messages. Can be replaced by a call to in.readLine().
    private String getMessageFromServer() {
        final String message;
        if (dummyServerMessages.nextInt(6) < 2)
            message = "Hello";
        else
            message = "Silence";
        return message + " from " + userName + "@" + IP + ":" + port;
    }

    private void pause(final int milliseconds) {
        try {
            Thread.sleep(milliseconds);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getPassword() {
        return password;
    }

    public String getStatus() {
        return status;
    }
}
java  swing  jbutton  chat  actionlistener