2011-05-10 61 views
1

这是完整的代码:我怎样才能解决这个错误

import javax.swing.*; 
    import java.awt.*; 
    import java.awt.event.*; 
    import java.lang.Thread; 

    class jProgressBar { 
    JProgressBar pb; 
    JButton start; 
    int i; 


    jProgressBar() { 
    buildGUI(); 
    hookUpEvents(); 
    } 
    public void buildGUI() { 
    JFrame fr=new JFrame("Progress Bar"); 
    JPanel p=new JPanel(); 
    p.setLayout(new FlowLayout(FlowLayout.CENTER)); 
    JPanel barPanel=new JPanel(); 
    barPanel.setLayout(new GridLayout(2,0,50,50)); 
    pb=new JProgressBar(0,10); 
    start=new JButton("Start Demo"); 
    fr.add(p); 
    barPanel.add(start); 
    barPanel.add(pb); 
    p.add(barPanel); 
    fr.setSize(500,500); 
    fr.setVisible(true); 
    } 

    public void hookUpEvents() { 
    start.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent ae) { 
     try { 
      Runnable r=new Runnable() { 
      public void run() { 
       action(ae);   // LINE 39 
      } 
      }; 
      Thread th=new Thread(r); 
      th.start(); 
     } catch(Exception exc) { 
      System.out.println(exc); 
      } 
     } 
    }); 
    } 

    public void action(ActionEvent ae) { 
     start.setVisible(false); 
     try { 
     Runnable rp=new Runnable() { 
      public void run() { 
      i++; 
      pb.setValue(i); 
      try { 
       Thread.sleep(2000); 
      } catch(Exception exc) { 
        System.out.println(exc); 
       } 
      if(i==5) { 
      pb.setString("Half Done!"); 
      } 
      else if(i==10) { 
       pb.setString("Completed!"); 
      } 
      } 
     }; 
     Thread th=new Thread(rp); 
     th.start(); 
     } catch(Exception exc) { 
      System.out.println(exc); 
     } 
    } 

    public static void main(String args[]) { 
    new jProgressBar(); 
    } 
    } 

这是CMD产生的误差: d:\UnderTest>javac jProgressBar.java jProgressBar.java:39: local variable ae is accessed from within inner class; needs to be declared fina l action(ae); ^ 1 error

这是什么错误,我怎么能解决这个错误?

+5

'需要声明final'做什么它说的事情! 'final ActionEvent ae' – MeBigFatGuy 2011-05-10 19:22:21

回答

4

声明变量ae作为final

public void actionPerformed(final ActionEvent ae) { 

这意味着它不能被分配一个新的值,这要根据当前的代码被罚款。

+1

编译器要求在内部类中访问的变量是最终的。这样分配给引用的值不会改变,并且可以进行各种优化,包括丢弃堆栈帧。 – sblundy 2011-05-10 19:27:29

+0

但这里的进度条没有进展..我该怎么做? – 2011-05-10 19:35:13

+0

可能需要在事件分派器线程上运行'pb.setValue(i)';你可以使用SwingUtilities.invokeLater() – 2011-05-10 19:39:37

1

存在一些适得其反的问题。

Swing是基于单线程的,所有操作都必须在EDT上完成。因此,您的JProgressBar不能正确更新。另见Concurrency in Swing

不要在Swing中使用Thread.sleep(int),当然不能在动作侦听器中使用。

通过使用Runnable,可以更新JProgressBar;但是作为mentioned,该方法必须从invokeLater()运行。

对此,SwingWorker会更好,如下所示,here

import java.awt.Dimension; 
import java.awt.Toolkit; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class TestProgressBar { 

    private static void createAndShowUI() { 
     JFrame frame = new JFrame("TestProgressBar"); 
     frame.getContentPane().add(new TestPBGui().getMainPanel()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 

    private TestProgressBar() { 
    } 
} 

class TestPBGui { 

    private JPanel mainPanel = new JPanel(); 

    public TestPBGui() { 
     JButton yourAttempt = new JButton("Your attempt to show Progress Bar"); 
     JButton myAttempt = new JButton("My attempt to show Progress Bar"); 
     yourAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       yourAttemptActionPerformed(); 
      } 
     }); 
     myAttempt.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       myAttemptActionPerformed(); 
      } 
     }); 
     mainPanel.add(yourAttempt); 
     mainPanel.add(myAttempt); 
    } 

    private void yourAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     Task task = new Task("Your attempt"); 
     task.execute(); 
     progressDialog.setVisible(true); 
     while (!task.isDone()) { 
     } 
     progressDialog.dispose(); 
    } 

    private void myAttemptActionPerformed() { 
     Window thisWin = SwingUtilities.getWindowAncestor(mainPanel); 
     final JDialog progressDialog = new JDialog(thisWin, "Uploading..."); 
     JPanel contentPane = new JPanel(); 
     contentPane.setPreferredSize(new Dimension(300, 100)); 
     final JProgressBar bar = new JProgressBar(0, 100); 
     bar.setIndeterminate(true); 
     contentPane.add(bar); 
     progressDialog.setContentPane(contentPane); 
     progressDialog.pack(); 
     progressDialog.setLocationRelativeTo(null); 
     final Task task = new Task("My attempt"); 
     task.addPropertyChangeListener(new PropertyChangeListener() { 

      @Override 
      public void propertyChange(PropertyChangeEvent evt) { 
       if (evt.getPropertyName().equalsIgnoreCase("progress")) { 
        int progress = task.getProgress(); 
        if (progress == 0) { 
         bar.setIndeterminate(true); 
        } else { 
         bar.setIndeterminate(false); 
         bar.setValue(progress); 
         progressDialog.dispose(); 
        } 
       } 
      } 
     }); 
     task.execute(); 
     progressDialog.setVisible(true); 
    } 

    public JPanel getMainPanel() { 
     return mainPanel; 
    } 
} 

class Task extends SwingWorker<Void, Void> { 

    private static final long SLEEP_TIME = 4000; 
    private String text; 

    public Task(String text) { 
     this.text = text; 
    } 

    @Override 
    public Void doInBackground() { 
     setProgress(0); 
     try { 
      Thread.sleep(SLEEP_TIME);// imitate a long-running task 
     } catch (InterruptedException e) { 
     } 
     setProgress(100); 
     return null; 
    } 

    @Override 
    public void done() { 
     System.out.println(text + " is done"); 
     Toolkit.getDefaultToolkit().beep(); 
    } 
} 
+0

我冒昧编辑你非常有用的回应。如果不正确,请回复,并且毫不犹豫地说,如果您希望我偶尔不这样做。 – trashgod 2011-05-17 15:26:25

1

一个非常好的例子为SwingWorker的

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
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 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 
     } 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(); 
      } 
     }); 
    } 
} 
相关问题