【问题标题】:Update JLabel repeatedly with results of long running task使用长时间运行任务的结果重复更新 JLabel
【发布时间】:2023-11-14 10:57:01
【问题描述】:

我正在编写一个不断 ping 服务器的程序。我编写了代码来检查一次,并将 ping 放入 JLabel 并将其放入名为 setPing() 的方法中。

这是我的代码

private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  
    setPing();
}           

这有效,但只做了一次,所以我做了:

private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  
for(;;){
    setPing();
    }
}           

但这甚至不是第一次。

setPing方法我没放,因为太长所以放在这里:

public String setPing(){
Runtime runtime = Runtime.getRuntime(); 
try{
    Process process = runtime.exec("ping lol.garena.com");
InputStream is = process.getInputStream(); 
InputStreamReader isr = new InputStreamReader(is); 
BufferedReader br = new BufferedReader(isr); 
String line; 
while ((line = br.readLine()) != null) {
    int i = 0;
      i = line.indexOf("Average");
    if(i > 0){  
    String finalPing = "";
    line.toCharArray();
    try
    {
        finalPing = "";
        for(int x = i; x < i + 17; x++)
        {
            finalPing = finalPing + (line.charAt(x));
        }
    }catch(IndexOutOfBoundsException e)
    {
        try
        {
            finalPing = "";
            for(int x = i; x < i + 16; x++)
            {
                finalPing = finalPing + (line.charAt(x));
            }
        }catch(IndexOutOfBoundsException f)
        {
            try
            {
                finalPing = "";
                for(int x = i; x < i + 15; x++)
                {
                    finalPing = finalPing + (line.charAt(x));
                }
            }catch(IndexOutOfBoundsException g){}
        }
    }
    String final1Ping = finalPing.replaceAll("[^0-9]", "");
    return final1Ping;
    }
} 
}catch(IOException e){
}
return "";
}

更新 以防万一这很重要,我正在使用 netbeans。我创建了一个表单并将此代码放在 formWindowOpened evt 中,而不是在 main 中调用它:

private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  

    ActionListener timerListener = new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            new PingWorker().execute();
        }
    };
    Timer timer = new Timer(1000, timerListener);


        timer.start();
        jLabel1.setText(label.getText());
        timer.stop();
 // TODO add your handling code here:
}                                 

class PingWorker extends SwingWorker {

    int time;

    @Override
    protected Object doInBackground() throws Exception {
        time = pingTime("lol.garena.com");
        return new Integer(time);
    }

    @Override
    protected void done() {
        label.setText("" + time);
    }
};

public JComponent getUI() {
    return label;
}

public static int pingTime(String hostnameOrIP) {
    Socket socket = null;
    long start = System.currentTimeMillis();
    try {
        socket = new Socket(hostnameOrIP, 80);
    } catch (IOException ex) {
        ex.printStackTrace();
    } finally {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
            }
        }
    }
    long end = System.currentTimeMillis();
    return (int) (end - start);
}

【问题讨论】:

标签: java swing jlabel ping event-dispatch-thread


【解决方案1】:

使用 Swing Timer 执行重复任务,使用 SwingWorker 执行长时间运行的任务。例如。以下两者之一 - 它使用TimerSwingWorker 中重复执行“长时间运行”任务(ping)。

有关事件调度​​线程以及在 GUI 中执行长时间运行或重复任务的更多详细信息,请参阅 Concurrency in Swing

此代码使用基于 Swing 的 Timer 从重复任务(随时间重复更新 JLabel)调用 SwingWorker 组合一个长时间运行的任务(“ping”服务器)。

import java.awt.event.*;
import javax.swing.*;
import java.net.Socket;

public class LabelUpdateUsingTimer {

    static String hostnameOrIP = "*.com";
    int delay = 5000;
    JLabel label = new JLabel("0000");

    LabelUpdateUsingTimer() {
        label.setFont(label.getFont().deriveFont(120f));

        ActionListener timerListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new PingWorker().execute();
            }
        };
        Timer timer = new Timer(delay, timerListener);

        timer.start();
        JOptionPane.showMessageDialog(
                null, label, hostnameOrIP, JOptionPane.INFORMATION_MESSAGE);
        timer.stop();
    }

    class PingWorker extends SwingWorker {

        int time;

        @Override
        protected Object doInBackground() throws Exception {
            time = pingTime();
            return new Integer(time);
        }

        @Override
        protected void done() {
            label.setText("" + time);
        }
    };

    public static int pingTime() {
        Socket socket = null;
        long start = System.currentTimeMillis();
        try {
            socket = new Socket(hostnameOrIP, 80);
        } catch (Exception weTried) {
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (Exception weTried) {}
            }
        }
        long end = System.currentTimeMillis();
        return (int) (end - start);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                new LabelUpdateUsingTimer();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

【讨论】:

  • 我很懒惰。正在等待有人发布这个:-)
  • @peeskillet 需要一定数量的错误或过于复杂的答案才能达到我的“我只是要坐在这里观看 clusterf*ck”的限制。 ;)
  • 我不明白。您能否说明我将如何以及在何处调用我的方法 setPing()?
  • 是的,我确实用setPing() 替换了label.setText("" + rand.nextInt(1000));,但这是一个非静态方法,因为它更新了jLabel
  • 哦等等我想通了!非常感谢!
【解决方案2】:

您可以使用Thread。问题是你阻塞了主线程,从而阻塞了你的程序。要解决此问题,请启动后台Thread 以重复更新组件。

(注意:你need要更新EDT上的GUI组件,所以使用SwingUtilities.invokeLater

(new Thread((new Runnable(){
    @Override
    public void run(){
        while(true){
            SwingUtilities.invokeLater(new Runnable(){
                @Override
                public void run(){
                    refToJLabel.setText(Math.random());
                }
            });
        }
    }
}))).start();

【讨论】:

  • 好的,我做了这个,它有点工作。我将我的 setPing 方法从 public void 更改为 public String,而不是更改 jLabel 的文本,它现在将 ping 作为字符串返回。因此,现在当我在您的代码中将refToJLabel.setText(Math.random()); 替换为System.out.println(setPing()); 时,它会在控制台中连续打印ping。但是当我输入jLabel1.setText(setPing()); 时,它什么也没做
  • “某种作品”在这种情况下意味着“失败”。它应该完美无缺。我注意到这段代码在Thread 循环中没有延迟,所以我猜测标签的大部分更新都会被忽略。
最近更新 更多