2013-12-14 42 views
0

基本上,我有2个类:1,JProgressBar被添加到JPanel的GUI,另一个是具有JProgressBar应该更新的进程的类。JProgressBar作为参数传递给其他类中的方法&将不会更新?

我的问题是进度条不会定期更新,只会在处理完成后才会更新。我尝试过使用SwingUtilities.invokeLater(),但不知怎的,事后证明处理任务已完成,并且在处理甚至执行之前所有已完成的消息都已经打印出来,所以我正在尝试invokeAndWait()。

我搜索了周围的答案,但其中大多数只是举例JProgressBar GUI和更新在同一类中完成,而在我的情况下,2是分开的。我也考虑过SwingWorker,但不知道我应该在哪里以及如何实现它,因为它会改变我的程序结构。

以下是我的代码。对不起,它是混乱的,命名不是很连贯,我尝试了很多东西来使进度条更新,并需要一些时间来重新组织(但基本上代码工作正常)。

的GUI类(参见具体方法getYesButton()):

public class TextureRevertPanel extends JPanel { 

private TextureEditor te; 
private TextureEditorGUI parent; 
private JButton yesButton; 
private JButton noButton; 
private String imgtype; 
private String path; 
private JProgressBar pbar; 
static final int MY_MINIMUM = 0; 
static final int MY_MAXIMUM = 100; 

public TextureRevertPanel(TextureEditor te, TextureEditorGUI parent, String imgtype, String path) { 
    super(); 
    this.parent = parent; 
    setPreferredSize(new Dimension(800, 400)); 

    setLayout(new GridBagLayout()); 

    GridBagConstraints c = new GridBagConstraints(); 
    c.insets = new Insets(5, 5, 5, 5); 
    c.anchor = GridBagConstraints.WEST; 

    c.gridx = 0; 
    c.gridy = 0; 
    c.gridwidth = 2; 
    add(new JLabel("Energy saving mode is turned ON, do you want to turn it off?"), c); 

    c.gridx = 0; 
    c.gridy = 1; 
    c.gridwidth = 2; 
    JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); 
    bottomPanel.add(getYesButton()); 
    bottomPanel.add(getNoButton()); 
    add(bottomPanel, c); 

    c.gridx = 0; 
    c.gridy = 4; 
    c.gridwidth = 1; 
    add(new JLabel("Progress"), c); 

    c.gridx = 1; 
    c.gridy = 4; 
    c.gridwidth = 1; 
    pbar = new JProgressBar(); 
    pbar.setMinimum(MY_MINIMUM); 
    pbar.setMaximum(MY_MAXIMUM); 
    // add to JPanel 
    add(pbar, c); 

    this.te = te; 
    this.path = path; 
    this.imgtype = imgtype; 

} 

private JButton getYesButton() { 
    if (yesButton == null) { 
     yesButton = new JButton("Yes"); 
     yesButton.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       if (MouseEvent.BUTTON1 == e.getButton()) { 
        boolean b = te.revertTextures("Y", path, imgtype, pbar); 
        if (b) { 
         /*JOptionPane.showMessageDialog(
           parent.getMainFrame(), 
           "Textures in " + path + " have been reverted back", 
           "Notification", JOptionPane.INFORMATION_MESSAGE);*/ 
         //parent.showMainPane(); 
        } 
       } 
      } 
     }); 
    } 
    return yesButton; 
} 

private JButton getNoButton() { 
    if (noButton == null) { 
     noButton = new JButton("No"); 
     noButton.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mouseReleased(MouseEvent e) { 
       if (MouseEvent.BUTTON1 == e.getButton()) { 
        parent.showMainPane(); 
       } 
      } 
     }); 
    } 
    return noButton; 
} 
} 

按YES,类将调用TextureEditor类的方法revertTextures()。 JProgressBar pbar作为参数传递给方法。

然后,在TextureEditor的revertTextures方法:

public boolean revertTextures(String input, String texturepath, String imgtype,  JProgressBar pbar) { 
    System.out.println("Energy saving mode is on, do you want to turn it off?(Y/N)"); 
    if (input.equalsIgnoreCase("Y")) { 
     System.out.println("Turning off energy saving mode..."); 
     //copy all the png in the backup folder to texture folder 
final String tpath = texturepath; 
final String imagetype = imgtype; 
this.pbar = pbar; 
final Runnable doHelloWorld = new Runnable() { 

      public void run() { 
       System.out.println("Hello World on " + Thread.currentThread()); 
       restorebackup(tpath, imagetype); 
      } 
     }; 

     Thread appThread = new Thread() { 

      @Override 
      public void run() { 
       try { 
        SwingUtilities.invokeAndWait(doHelloWorld); 
        String text = "OFF"; 
        try { 
         File file = new File(tpath + "backup\\indicator.txt"); 
         BufferedWriter output = new BufferedWriter(new FileWriter(file)); 
         output.write(text); 
         output.close(); 
        } catch (IOException e) { 
         e.printStackTrace(); 
        } 
        System.out.println("Energy saving mode has been turned off."); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
       System.out.println("Finished on " + Thread.currentThread()); 
      } 
     }; 
     appThread.start(); 

然后该线程内,真正的处理方法restorebackup()被调用。这是关于SpringLayout应该被更新:

public void restorebackup(String tpath, String imgtype) { 
    File backuppath = new File(tpath + "backup\\"); 
    final File[] files = backuppath.listFiles(); 
    final String imagetype = "." + imgtype; 
    final String texpath = tpath; 
    final String imagtype = imgtype; 

    for (int i = 0; i < files.length; i++) { 
     final int ii = i; 
     System.out.println(files[i].getName()); 
     File texturepath; 
     BufferedImage image; 
     try { 
      System.out.println(files[ii]); 
      if (files[ii].getName().contains(imagetype)) { 
       texturepath = new File(texpath + files[ii].getName()); 
       image = ImageIO.read(files[ii]); 
       ImageIO.write(image, imagtype, texturepath); 
       double proportion = (ii/(double) (files.length - 1)); //count out the indicator file 
       System.out.println((int) (proportion * 100) + "%"); 
       pbar.setValue((int) (proportion * 100)); 
      } 
     } catch (IOException e) { 
      System.out.println("Could not open texture files in backup folder"); 
     } 
    } 
    System.out.println("Done"); 
} 
+0

1)为了更快得到更好的帮助,请发布[SSCCE](http://sscce.org/)。 2)请不要忘记添加'?'提问!有些人在页面中搜索'?'如果'问题'中不存在,则直接进入下一个(实际)问题。 –

回答

0

好的,最后我决定在我的TextureEditor类中使用一个SwingWorker类。这解决了我的问题。不过,我需要将restorebackup()操作复制到doInBackGround()。

private static class MySwingWorker extends SwingWorker<String, Double> { 

    private final JProgressBar fProgressBar; 
    private final String tpath; 
    private final String imagetype; 
    private final TextureEditorGUI parent; 

    private MySwingWorker(JProgressBar aProgressBar, String tpath, String imagetype, TextureEditorGUI parent) { 
     fProgressBar = aProgressBar; 
     this.tpath = tpath; 
     this.imagetype = imagetype; 
     this.parent = parent; 
    } 

    @Override 
    protected String doInBackground() throws Exception { 
     File backuppath = new File(tpath + "backup\\"); 
     File texturepath; 
     final File[] files = backuppath.listFiles(); 
     BufferedImage image; 
     final String texpath = tpath; 
     for (int i = 0; i < files.length; i++) { 
      final int ii = i; 
      try { 
       System.out.println(files[i].getName()); 
       System.out.println(files[ii]); 
       if (files[ii].getName().contains("." + imagetype)) { 
        texturepath = new File(texpath + files[ii].getName()); 
        image = ImageIO.read(files[ii]); 
        ImageIO.write(image, imagetype, texturepath); 
        double proportion = (ii/(double) (files.length - 1)); //count out the indicator file 
        publish(proportion); 
        System.out.println((int) (proportion * 100) + "%"); 
       } 
      } catch (IOException e) { 
       System.out.println("Could not open texture files in backup folder"); 
      } 
     } 
     return "Finished"; 
    } 

    @Override 
    protected void process(List<Double> aDoubles) { 
     //update the percentage of the progress bar that is done 
     int amount = fProgressBar.getMaximum() - fProgressBar.getMinimum(); 
     fProgressBar.setValue((int) (fProgressBar.getMinimum() + (amount * aDoubles.get(aDoubles.size() - 1)))); 
    } 

    @Override 
    protected void done() { 
     try { 
      JOptionPane.showMessageDialog(
        parent.getMainFrame(), 
        "Textures in " + tpath + " have been reverted back", 
        "Notification", JOptionPane.INFORMATION_MESSAGE); 
      parent.showMainPane(); 
     } catch (Exception ignore) { 
     } 
    } 
} 

但是,我有我的TextureEditor类中的另一种方法,需要进度栏更新以及。这是否意味着我需要为其他方法创建另一个SwingWorker类,或者SwingWorker内部的条件会做什么(即将参数传递给SwingWorker,并且它将通过条件为不同的方法执行不同的操作)?

0

你不是要求从后台线程​​。你从事件调度线程调用它,因为它的调用被包装在SwingUtilities.invokeAndWait()的调用中。因此,此方法中的所有工作都是在UI线程中完成的,冻结它并阻止它更新UI,直到方法完成。

您必须在后台线程中完成所有这项工作,除了进度条的更新外,必须将其更新到SwingUtilities.invokeLater()调用中。

或者更好,你应该阅读SwingWorker的文档并使用它。

+0

我如何在后台线程中完成这项工作?我试着把里面的进度条更新放在restorebackup()或revertTextures()里面的SwingUtilities.invokeLater()里面,它仍然没有更新。 –

+0

替换'SwingUtilities.invokeAndWait(doHelloWorld);'''restorebackup(tpath,imagetype);' –

相关问题