簡體   English   中英

運行Action Listener時,為什么我的GUI Send Button會凍結?

[英]Why does my GUI Send Button freeze when Action Listener is run?

我正在使用帶有與客戶端連接的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);
    }
}

Swing具有負責更改GUI的特殊線程。 事件調度線程。 來自ActionListeners的方法是在此Thread上執行的,這意味着如果它們花費很長時間,則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();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM