Domanda

Could someone tell me why in this simple demo of using a SwingWorker, the screen flickers as if the buttons are jumping constantly? (feedback on improving the multithreading portion is appreciated too).

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);
            }
        });
    }
}
È stato utile?

Soluzione

It has nothing to do with the SwingWorker and all to do with how your components respond to their layout. The number String varies in width if it has trailing 0's causing the JLabel to change widths, causing the jumping, and so you should format the number String so that has constant width by using String.format(...) or a DecimalFormat object.

For instance

e.g.,

  @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));
  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top