【问题标题】:Java SwingWorker FlickerJava SwingWorker 闪烁
【发布时间】:2013-08-24 17:21:19
【问题描述】:

谁能告诉我为什么在这个使用 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);
            }
        });
    }
}

【问题讨论】:

    标签: java swing swingworker flowlayout


    【解决方案1】:

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

    例如

    例如,

      @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));
      }
    

    【讨论】:

    • FlowLayout 的有趣问题,不是吗 (Java6/7 win7)
    • 谢谢。顺便说一句,我在 Java 7、OS X 上。
    • @Hovercraft:谢谢一百万。现在完美运行。顺便说一句,出于好奇,在这种情况下使用 SwingWorker 是否可以接受,或者考虑到它的性质,我是否必须使用 Timer?
    • @Mahmoud:我自己,我会使用 Swing Timer,这可以让我不必使用 SwingWorker,但我会得到系统时间的时差,而不是 Timer 本身。
    • @Hovercraft:知道了。再次感谢。
    猜你喜欢
    • 2017-01-18
    • 2012-05-13
    • 2013-01-09
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多