我想用一个简单的Ping生成的每个新字符串动态地更改一个JLabel但是无法弄清楚如何在执行Ping时将每个新字符串替换为JLabel上的现有字符串。以下是我到目前为止的情况。到目前为止,它只替换了JLabel的文本,但只有在Ping完成后才会替换。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import java.io.*;
public class Ping extends JFrame implements ActionListener{
private JButton runButton = new JButton("Run");
private JLabel pingResult = new JLabel("Result");
private String results;
public Ping(){
runButton.addActionListener(this);
add(pingResult, BorderLayout.CENTER);
add(runButton, BorderLayout.NORTH);
}
//Action Listener
public void actionPerformed(ActionEvent e)
{
String buttonString = e.getActionCommand( );
if (buttonString.equals("Run"))
{
//Execute Ping
try {
String line;
Process p = Runtime.getRuntime().exec("/sbin/ping -c 4 www.google.com");
BufferedReader input = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
results += line + "\n";
pingResult.setText(results);
//System.out.println(line);
}
input.close();
}catch (Exception err){
err.printStackTrace();
}
}else{
System.exit(0);
}
}
public static void main(String[] args) {
Ping sp = new Ping();
sp.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
sp.setSize(400, 400);
sp.setVisible(true);
sp.setLayout(new BorderLayout());
}
}
答案 0 :(得分:3)
在事件派发线程上调用setText。使用SwingUtils.invokeLater。不要从EDT执行持久的操作。这将导致您的应用冻结,正如您所遇到的那样。
答案 1 :(得分:1)
您的代码冻结了EDT(事件调度线程)。这就是ping完成后更新JLabel文本的原因。你应该避免这样做。在不同的线程中运行持久的操作并使用SwingUtils.invokeLater更新它是一种解决方案。另一种是使用SwingWorker类。你可以在这里找到tutorial。
以下是第一个选项的示例。我使用JTextArea而不是JLabel。
还有一件事你应该使用ProcessBuilder而不是Runtime.exec(),here是很好的文章原因。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class PingExample {
private static final Logger logger = Logger.getLogger(PingExample.class.getName());
public static void main(String[] args) {
PingExample p = new PingExample();
p.run();
}
private void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new PingFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
private class PingFrame extends JFrame {
private static final long serialVersionUID = 1L;
private JTextArea textArea;
private PingFrame() {
super.setName("Ping Frame");
this.addComponents();
super.setSize(400, 240);
}
private void addComponents() {
super.setLayout(new BorderLayout());
this.textArea = new JTextArea(10, 0);
JScrollPane scrollPane = new JScrollPane(this.textArea);
super.add(scrollPane, BorderLayout.NORTH);
JButton button = new JButton("Run");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Thread(new Ping(PingFrame.this.textArea)).start();
}
});
super.add(button, BorderLayout.SOUTH);
}
private class Ping implements Runnable {
private JTextArea textArea;
private Ping(JTextArea textArea) {
this.textArea = textArea;
}
@Override
public void run() {
try {
List<String> commands = new ArrayList<>(10);
commands.add("ping");
commands.add("www.google.com");
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
Process process = builder.start();
try (
BufferedReader br = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.defaultCharset()))) {
String line = br.readLine();
while (null != line) {
final String text = line;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Ping.this.textArea.append(text);
Ping.this.textArea.append("\n");
}
});
line = br.readLine();
}
}
process.waitFor();
process.destroy();
} catch (IOException | InterruptedException x) {
logger.log(Level.SEVERE, "Error", x);
}
}
}
}
}
答案 2 :(得分:0)
确切地说,只有在ping完成后才会更新它。如果你想在它完成之前完成它,你需要使用不同的线程。