【问题标题】:Why does my GUI Send Button freeze when Action Listener is run?为什么我的 GUI 发送按钮在 Action Listener 运行时冻结?
【发布时间】:2018-01-10 19:07:38
【问题描述】:

我正在制作一个带有与客户端连接的 GUI 的聊天服务器

GUI 由两个文本框组成,一个用于接收文本,一个用于发送文本。最后一件事是发送按钮,我现在遇到了问题。

发送按钮在被按下且消息未发送时冻结(GUI 仍然有效,它只是冻结的按钮)。

我不知道在这里做什么,希望你们能帮助我。任何帮助表示赞赏,谢谢!

代码:

class UdpServer
{
PrintWriter out;
ButtonHandler txButtonHandler;
BufferedReader in;
    DatagramSocket socket;
    InetAddress ip = null;
int port;

    UdpServer (String gport) throws IOException
    {
        int i = 0;
        socket = new DatagramSocket (Integer.parseInt (gport));

  txButtonHandler = new ButtonHandler ();
  sendButton.addActionListener (txButtonHandler);
        new Thread ()
        {
            public void run ()
            {
                try
                {
                    rx ();
                }
                catch (IOException e)
                {
                }
            }

        }.start ();
        tx ();
        System.exit (1);
    }

    void tx () throws IOException
    {
        byte[] buf = new byte[256];
        BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
        String toServer;

        do
        {
            toServer = in.readLine();
            toServer = toServer + "\n";
            buf = toServer.getBytes ();
            DatagramPacket packet = new DatagramPacket (buf, toServer.length(), ip, port);
            if (ip != null) socket.send(packet);
        }
        while (toServer != null);
        socket.close ();
        System.exit (1);
    }

private class ButtonHandler implements ActionListener
{
    public void actionPerformed (ActionEvent event) //throws IOException
    {
        try{tx ();} catch (IOException e){}
    }
}

    void rx () throws IOException
    {
        byte[] buf = new byte[256];
        String fromServer;
        do
        {
            for (int i = 0; i < 256; i ++) buf[i] = 0;
            DatagramPacket packet = new DatagramPacket (buf, buf.length);
            socket.receive (packet);
            fromServer = new String (packet.getData());
            ip = packet.getAddress ();
            port = packet.getPort ();
            //System.out.println (port + ":" + ip);
            if (fromServer != null) System.out.print (fromServer);
        }
        while (fromServer != null);
        socket.close ();
        System.exit (1);
    }
}

【问题讨论】:

标签: java button handler actionlistener


【解决方案1】:

Swing 有一个特殊的线程负责更改 GUI。事件调度线程。来自 ActionListener 的方法在此线程上执行,这意味着如果它们花费很长时间,UI 就会冻结。所以你必须在自己的线程中完成工作。不幸的是,如果您在自己的线程中并且想要更改 UI,则必须在事件调度线程中执行此操作。您可以使用 SwingUtilities.invokeLater 来做到这一点。

这是一个例子:

import javax.swing.*;

public class Example extends JFrame {
    public static void main(String[] args) {
        Example example = new Example();
        example.setSize(200, 200);
        JButton button = new JButton("Do it");
        JTextField textField = new JTextField();
        button.addActionListener(e -> 
                new Thread(() -> {
                    doLongTask();
                    SwingUtilities.invokeLater(() -> textField.setText("Did it"));
        }).start());
        example.add(button);
        example.add(textField);
        example.pack();
        example.setVisible(true);
        example.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private static void doLongTask() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 2012-10-20
    • 2021-06-03
    • 2015-12-29
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多