2013-08-24 114 views
2

有人能告訴我爲什麼在這個使用SwingWorker的簡單演示中,屏幕閃爍,好像按鈕不斷跳動一樣? (對改進多線程部分的反饋也很讚賞)。Java 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); 
      } 
     }); 
    } 
} 

回答

3

它與SwingWorker無關,並且與您的組件如何響應其佈局無關。數字字符串的寬度因寬度而異,如果它尾隨0,則會導致JLabel更改寬度,導致跳轉,因此您應該格式化數字String,以便使用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)); 
    } 
+0

具有FlowLayout有趣的問題,是不是(的Java6/7 WIN7) – mKorbel

+0

感謝。順便說一下,我在Java 7,OS X上。 – Mahmoud

+0

@Hovercraft:謝謝!現在完美運作。順便說一句,出於好奇,在這種情況下使用SwingWorker或給定其性質,我必須使用Timer嗎? – Mahmoud