2012-08-24 31 views
5

Tôi có ProgressMonitor pm và một SwingWorker sw. Tôi muốn hủy SwingWorker khi tôi nhấn nút cancel trên pm. Tôi đoán điều này không nên quá khó khăn, và tôi đọc một số hướng dẫn về SwingWorker và ProgressMonitor, nhưng tôi không thể làm điều này để làm việc.nhận sự kiện hủy của Java ProgressMonitor

final ProgressMonitor pm = new ProgressMonitor(frame, "checking", "...", 0, 100); 
final SwingWorker sw = new SwingWorker() 
{ 
    protected Object doInBackground() throws Exception 
    { 
     doSomethingAndUpdateProgress(); 
    } 
}; 

sw.addPropertyChangeListener(new PropertyChangeListener() 
{ 
    public void propertyChange(PropertyChangeEvent evt) 
    { 
     if(evt.getPropertyName().equals("progress")) 
     { 
      updateProgress(); 
     } 
     if(pm.isCanceled()) 
     { 
      cancelAction(); 
     } 
     if(pm.isDone()) 
     { 
      doneAction(); 
     } 
    } 
}); 

sw.execute(); 

Cập nhật tiến trình đang hoạt động tốt, nhưng pm.isCanceled() không bao giờ là true. Tôi cho rằng tôi cần một propertyChangeListener cho ProgressMonitor, nhưng tôi không biết làm thế nào tôi sẽ thêm một cái ở đó.

Trả lời

4

Trong việc thực hiện các nhiệm vụ chạy dài của bạn, bạn muốn kiểm tra định kỳ nếu ProgressMonitor đã bị hủy bỏ. Đó là công việc của bạn để kiểm tra xem tại điểm mà nó có ý nghĩa để hủy bỏ nhiệm vụ - nếu không ai biết những gì tài nguyên bạn có thể để lại treo.

Vì vậy, về cơ bản, bạn muốn thay đổi phương thức doSomethingAndUpdateProgress() của mình để nó cũng kiểm tra xem ProgressMonitor đã bị hủy hay chưa.

Dưới đây là một bản demo cho thấy cách làm việc này:

import java.awt.*; 
import javax.swing.*; 

public class TempProject extends Box{ 

    public TempProject(){ 
     super(BoxLayout.Y_AXIS); 
     final ProgressMonitor pm = new ProgressMonitor(this, "checking", "...", 0, 100); 
     final SwingWorker sw = new SwingWorker<Integer, Integer>() 
     { 
      protected Integer doInBackground() throws Exception 
      { 
       int i = 0; 
       //While still doing work and progress monitor wasn't canceled 
       while (i++ < 100 && !pm.isCanceled()) { 
        System.out.println(i); 
        publish(i); 
        Thread.sleep(100); 
       } 
       return null; 
      } 


      @Override 
      protected void process(java.util.List<Integer> chunks) { 
       for (int number : chunks) { 
        pm.setProgress(number); 
       } 
      } 

     }; 

     sw.execute(); 
    } 


    public static void main(String args[]) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setContentPane(new TempProject());  
       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 


} 
+0

câu trả lời allthough mKorbel là rất thông tin nó thiếu ProgressMonitor tôi đã thực sự hỏi về - vì vậy tôi đã chọn điều này như là câu trả lời. – AntiZamba

4

và tôi đã đọc một số hướng dẫn về SwingWorker và ProgressMonitor, nhưng tôi không thể làm việc này được.

hủy luôn viện dẫn một InteruptedExeption,

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 
import java.util.ArrayList; 

public class SwingWorkerExample extends JFrame implements ActionListener { 

    private static final long serialVersionUID = 1L; 
    private final JButton startButton, stopButton; 
    private JScrollPane scrollPane = new JScrollPane(); 
    private JList listBox = null; 
    private DefaultListModel listModel = new DefaultListModel(); 
    private final JProgressBar progressBar; 
    private mySwingWorker swingWorker; 

    public SwingWorkerExample() { 
     super("SwingWorkerExample"); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     getContentPane().setLayout(new GridLayout(2, 2)); 
     startButton = makeButton("Start"); 
     stopButton = makeButton("Stop"); 
     stopButton.setEnabled(false); 
     progressBar = makeProgressBar(0, 99); 
     listBox = new JList(listModel); 
     scrollPane.setViewportView(listBox); 
     getContentPane().add(scrollPane); 
     //Display the window. 
     pack(); 
     setVisible(true); 
    } 
//Class SwingWorker<T,V> T - the result type returned by this SwingWorker's doInBackground 
//and get methods V - the type used for carrying out intermediate results by this SwingWorker's 
//publish and process methods 

    private class mySwingWorker extends javax.swing.SwingWorker<ArrayList<Integer>, Integer> { 
//The first template argument, in this case, ArrayList<Integer>, is what s returned by doInBackground(), 
//and by get(). The second template argument, in this case, Integer, is what is published with the 
//publish method. It is also the data type which is stored by the java.util.List that is the parameter 
//for the process method, which recieves the information published by the publish method. 

     @Override 
     protected ArrayList<Integer> doInBackground() { 
//Returns items of the type given as the first template argument to the SwingWorker class. 
      if (javax.swing.SwingUtilities.isEventDispatchThread()) { 
       System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() returned true."); 
      } 
      Integer tmpValue = new Integer(1); 
      ArrayList<Integer> list = new ArrayList<Integer>(); 
      for (int i = 0; i < 100; i++) { 
       for (int j = 0; j < 100; j++) { //find every 100th prime, just to make it slower 
        tmpValue = FindNextPrime(tmpValue.intValue()); 
//isCancelled() returns true if the cancel() method is invoked on this class. That is the proper way 
//to stop this thread. See the actionPerformed method. 
        if (isCancelled()) { 
         System.out.println("SwingWorker - isCancelled"); 
         return list; 
        } 
       } 
//Successive calls to publish are coalesced into a java.util.List, which is what is received by process, 
//which in this case, isused to update the JProgressBar. Thus, the values passed to publish range from 
//1 to 100. 
       publish(new Integer(i)); 
       list.add(tmpValue); 
      } 
      return list; 
     }//Note, always use java.util.List here, or it will use the wrong list. 

     @Override 
     protected void process(java.util.List<Integer> progressList) { 
//This method is processing a java.util.List of items given as successive arguments to the publish method. 
//Note that these calls are coalesced into a java.util.List. This list holds items of the type given as the 
//second template parameter type to SwingWorker. Note that the get method below has nothing to do with the 
//SwingWorker get method; it is the List's get method. This would be a good place to update a progress bar. 
      if (!javax.swing.SwingUtilities.isEventDispatchThread()) { 
       System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false."); 
      } 
      Integer percentComplete = progressList.get(progressList.size() - 1); 
      progressBar.setValue(percentComplete.intValue()); 
     } 

     @Override 
     protected void done() { 
      System.out.println("doInBackground is complete"); 
      if (!javax.swing.SwingUtilities.isEventDispatchThread()) { 
       System.out.println("javax.swing.SwingUtilities.isEventDispatchThread() + returned false."); 
      } 
      try { 
//Here, the SwingWorker's get method returns an item of the same type as specified as the first type parameter 
//given to the SwingWorker class. 
       ArrayList<Integer> results = get(); 
       for (Integer i : results) { 
        listModel.addElement(i.toString()); 
       } 
      } catch (Exception e) { 
       System.out.println("Caught an exception: " + e); 
      } 
      startButton(); 
     } 

     boolean IsPrime(int num) { //Checks whether a number is prime 
      int i; 
      for (i = 2; i <= num/2; i++) { 
       if (num % i == 0) { 
        return false; 
       } 
      } 
      return true; 
     } 

     protected Integer FindNextPrime(int num) { //Returns next prime number from passed arg. 
      do { 
       if (num % 2 == 0) { 
        num++; 
       } else { 
        num += 2; 
       } 
      } while (!IsPrime(num)); 
      return new Integer(num); 
     } 
    } 

    private class TaskListener implements PropertyChangeListener { 

     private String name; 

     TaskListener(String name) { 
      this.name = name; 
     } 

     @Override 
     public void propertyChange(PropertyChangeEvent e) { 
      System.out.println(name + ": " 
        + e.getOldValue() + " -> " + e.getNewValue()); 
     } 
    } 

    private JButton makeButton(String caption) { 
     JButton b = new JButton(caption); 
     b.setActionCommand(caption); 
     b.addActionListener(this); 
     getContentPane().add(b); 
     return b; 
    } 

    private JProgressBar makeProgressBar(int min, int max) { 
     JProgressBar progressBar1 = new JProgressBar(); 
     progressBar1.setMinimum(min); 
     progressBar1.setMaximum(max); 
     progressBar1.setStringPainted(true); 
     progressBar1.setBorderPainted(true); 
     getContentPane().add(progressBar1); 
     return progressBar1; 
    } 

    private void startButton() { 
     startButton.setEnabled(true); 
     stopButton.setEnabled(false); 
     System.out.println("SwingWorker - Done"); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     if ("Start" == null ? e.getActionCommand() == null : "Start".equals(e.getActionCommand())) { 
      startButton.setEnabled(false); 
      stopButton.setEnabled(true); 
// Note that it creates a new instance of the SwingWorker-derived class. Never reuse an old one. 
      (swingWorker = new mySwingWorker()).execute(); // new instance 
      swingWorker.addPropertyChangeListener(new TaskListener("Task")); 

     } else if ("Stop" == null ? e.getActionCommand() == null : "Stop".equals(e.getActionCommand())) { 
      startButton.setEnabled(true); 
      stopButton.setEnabled(false); 
      swingWorker.cancel(true); // causes isCancelled to return true in doInBackground 
      swingWorker = null; 
     } 
    } 

    public static void main(String[] args) { 
// Notice that it kicks it off on the event-dispatching thread, not the main thread. 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       SwingWorkerExample swingWorkerExample = new SwingWorkerExample(); 
      } 
     }); 
    } 
} 
+0

@ Andrew Thompson những ý kiến ​​bởi 'aterai' hoặc' darryl' cho câu hỏi của tôi từ 'sun.forum.57' – mKorbel