要解决这个问题,您可以将网络请求放在一个单独的线程中进行,以避免阻塞Swing的事件调度线程。
以下是一个示例代码,演示如何使用线程来执行网络请求,并在收到响应后更新Swing界面:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Example {
private JButton button;
private JTextArea textArea;
public Example() {
JFrame frame = new JFrame("Example");
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
button = new JButton("Send Request");
textArea = new JTextArea();
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 创建一个线程池
ExecutorService executor = Executors.newSingleThreadExecutor();
// 在线程池中执行网络请求
executor.submit(new Runnable() {
@Override
public void run() {
try {
// 发送网络请求
URL url = new URL("http://example.com/api");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
String response = reader.readLine();
// 更新Swing界面
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
textArea.setText(response);
}
});
// 关闭读取器
reader.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
// 关闭线程池
executor.shutdown();
}
});
frame.add(button, BorderLayout.NORTH);
frame.add(new JScrollPane(textArea), BorderLayout.CENTER);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Example();
}
});
}
}
在上面的代码中,我们使用ExecutorService
创建一个单线程的线程池,以便在其中执行网络请求。当用户点击按钮时,我们将一个Runnable
对象提交给线程池,该对象执行网络请求,并在收到响应后更新Swing界面。
注意,我们使用SwingUtilities.invokeLater
在Swing事件调度线程上更新界面,以确保界面更新的线程安全性。
请注意,此示例仅为了演示目的,可能不会处理其他网络错误或异常情况。在实际应用中,您可能需要添加适当的异常处理和错误检查来处理这些情况。