Java SwingWorker Flicker



有人能告诉我为什么在这个使用SwingWorker的简单演示中,屏幕会闪烁,就好像按钮在不断跳跃一样?(关于改进多线程部分的反馈也值得赞赏)。

import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;
public class SwingWorkerStopWatch extends JFrame{
    JButton jbStart,jbStop;
    JLabel jlStatus;
    Long startTime;
    SwingWorker<Double, Double> SW;
    public SwingWorkerStopWatch() {
        setLayout(new FlowLayout());
        setSize(240, 100);
        jlStatus = new JLabel("Press Start");
        jbStart = new JButton("Start");
        jbStop = new JButton("Stop");
        jbStop.setEnabled(false);
        jbStart.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startTime = Calendar.getInstance().getTimeInMillis();
                jbStart.setEnabled(false);
                jbStop.setEnabled(true);
                SW = new StopWatchSwingWorker();
                SW.execute();
            }
        });
        jbStop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                SW.cancel(true);
                Long stopTime = Calendar.getInstance().getTimeInMillis();
                Double elapsedTime = (double)(stopTime-startTime)/1000;
                jlStatus.setText("Elapsed time is: " + elapsedTime);
                jbStart.setEnabled(true);
                jbStop.setEnabled(false);
            }
        });
        add(jbStart);
        add(jbStop);
        add(jlStatus);
        //pack();
    }
    private class StopWatchSwingWorker extends SwingWorker<Double, Double>{
        @Override
        protected Double doInBackground() throws Exception {
            Long tempTime;
            while (true) {
                tempTime = Calendar.getInstance().getTimeInMillis();
                Double elapsedTime = (double)(tempTime-startTime)/1000;
                publish(elapsedTime);
            }
        }
        @Override
        protected void process(List<Double> chunks) {
            if (isCancelled()) {
                return;
            }
            jlStatus.setText("" + chunks.get(chunks.size()-1));
        }
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame stopWatchFrame = new SwingWorkerStopWatch();
                stopWatchFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                stopWatchFrame.setVisible(true);
            }
        });
    }
}

它与SwingWorker无关,而是与组件如何响应其布局有关。如果后面有0,则数字String的宽度会发生变化,这会导致JLabel更改宽度,从而导致跳跃,因此您应该使用String.format(...)或DecimalFormat对象格式化数字String,使其具有恒定宽度。

例如

例如

  @Override
  protected void process(List<Double> chunks) {
     if (isCancelled()) {
        return;
     } else {
        String numberTxt = String.format("%5.3f",
              chunks.get(chunks.size() - 1));
        jlStatus.setText(numberTxt);
     }
     // jlStatus.setText("" + chunks.get(chunks.size() - 1));
     // System.out.println(chunks.get(chunks.size() - 1));
  }

相关内容

  • 没有找到相关文章

最新更新