Java ActionListener调用while循环方法

Java ActionListener调用while循环方法,java,swing,jbutton,chat,actionlistener,Java,Swing,Jbutton,Chat,Actionlistener,我添加了一个ActionListener,它创建了一个新的聊天框架,可以从服务器发送和接收消息。这是ActionPerformed()方法中的代码 所以它创建了一个新的聊天框,如果我没有调用chat.chatting()方法,我可以正常地将消息发送到服务器,但无法从服务器接收消息。所以我必须调用这个方法,因为如果服务器确实发送消息,我需要一直监听来自服务器的消息 这是聊天的代码() 这是while循环。 如果我创建聊天框并在主方法中调用此方法,它可以工作,但如果我在ActionListener中

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

所以它创建了一个新的聊天框,如果我没有调用chat.chatting()方法,我可以正常地将消息发送到服务器,但无法从服务器接收消息。所以我必须调用这个方法,因为如果服务器确实发送消息,我需要一直监听来自服务器的消息

这是聊天的代码()

这是while循环。 如果我创建聊天框并在主方法中调用此方法,它可以工作,但如果我在ActionListener中创建聊天框,它将被卡住。ActionListener似乎不能有一个完全不结束的while循环

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

正如前面所建议的,在后台线程中运行聊天代码可能是一个好主意-例如使用
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);
    }
}
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;
    }
}
import java.util.List;
导入java.util.Random;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.SwingWorker;
公共类BananaChat扩展了JFrame{
私有最终字符串用户名;
私有最终字符串密码;
私有最终字符串IP;
专用最终字符串端口;
私有最终字符串状态;
私有最终随机消息;
私有最终JTextArea消息stextarea;
公共BananaChat(最终字符串用户名、最终字符串密码、最终字符串IP、,
最终字符串端口,最终字符串状态){
超级(“与“+IP+”聊天:“+port”);
this.userName=用户名;
this.password=密码;
this.IP=IP;
this.port=端口;
这个状态=状态;
dummyServerMessages=新随机(123456);
messagesTextArea=newjtextarea();
添加(新的JScrollPane(messagesTextArea));
挫折(1000、100、400、200);
setVisible(真);
}
公共无效起始图案(){
最终SwingWorker chatWorker=新SwingWorker(){
@凌驾
受保护的Void doInBackground(){
while(!iscanceled()){
final String message=getMessageFromServer();
发布(消息+“\n”);
暂停(1000);
}
返回null;
}
@凌驾
受保护的无效进程(最终列表消息){
messages.forEach(messagesTextArea::append);
}
};
chatWorker.execute();
}
//生成愚蠢的随机消息。可由调用in.readLine()替换。
私有字符串getMessageFromServer(){
最终字符串消息;
if(dummyServerMessages.nextInt(6)<2)
message=“你好”;
其他的
message=“沉默”;
从“+用户名+”@“+IP+”:“+端口返回消息+”;
}
专用无效暂停(最终整数毫秒){
试一试{
睡眠(毫秒);
}捕获(最终中断异常e){
e、 printStackTrace();
}
}
公共字符串getPassword(){
返回密码;
}
公共字符串getStatus(){
返回状态;
}
}

1)有关更好的帮助,请尽快发布(最小完整可验证示例)或(短、自包含、正确的示例)。不要在事件分派线程中运行阻塞代码。你需要在后台线程中运行这样的代码——通常这是使用a最方便的。你能为问题添加更多的代码吗,比如
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);
    }
}
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;
    }
}