如何在线程内的JInternalFrame中执行可更新的JProgressBar?

时间:2015-07-06 11:21:18

标签: java multithreading swing jprogressbar

这是我到目前为止所做的,可能完全错了......

问题似乎是更新循环内的百分比,然后在SwingUtilities.invokeLater程序中调用它。

同样JInternalFrame位于该计划的其余部分后面,或许可以更好地使用JDialog

如果您需要更多信息,还可以在此处获取所需的代码,也愿意在github上发布整个项目。(如果允许的话)

这是我的第一个带代码的项目,所以任何帮助都会受到赞赏!

package twoDMapEditor;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;

import javax.swing.BorderFactory;
import javax.swing.JInternalFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;

public class SaveActionListener implements ActionListener {
    public void actionPerformed(ActionEvent me) {
        final JProgressBar progressBar = new JProgressBar();
        progressBar.setValue(0);
        progressBar.setStringPainted(true);
        progressBar.setBorder(BorderFactory.createTitledBorder("Saving..."));
        final JInternalFrame loadingDialog = new JInternalFrame();
        loadingDialog.add(progressBar);
        loadingDialog.pack();
        loadingDialog.setVisible(true);
        TwoDMapEditor.frame.add(loadingDialog);
        TwoDMapEditor.frame.revalidate();
        TwoDMapEditor.frame.repaint();

        new Thread(new Runnable() {
              public void run() {
                  final int percentage = 0;
                  int i = 0, j;
                  while (i < TwoDMapEditor.size[0]) {
                      j = 0;
                        while(j < TwoDMapEditor.size[1]){
                            if (!TwoDMapEditor.mySql.updateMapPiece(i, j)) {
                                System.out.println("Something went wrong");
                            }
                            //percentage = ((i * TwoDMapEditor.size[1]) + j+1) * 100 / (TwoDMapEditor.size[0] * TwoDMapEditor.size[1]);
                            j++;
                        }
                        i++;
                  }

                  try {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        public void run() {
                            progressBar.setValue(percentage);
                        }
                      });
                } catch (InvocationTargetException | InterruptedException e1) {
                    e1.printStackTrace();
                }

                  try {
                    java.lang.Thread.sleep(100);
                  }
                  catch(Exception e) { }
              }
        }).start();
    }
}

编辑:现在就搞定了:

package twoDMapEditor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.JInternalFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

public class SaveActionListener implements ActionListener, PropertyChangeListener {
JProgressBar progressBar;
ProgressBar progressBarClass;
JInternalFrame loadingDialog;

SaveActionListener(){
    progressBar = new JProgressBar();
    progressBar.setValue(0);
    progressBar.setStringPainted(true);
    progressBar.setBorder(BorderFactory.createTitledBorder("Saving..."));
    loadingDialog = new JInternalFrame();
    loadingDialog.add(progressBar);
    loadingDialog.pack();
    loadingDialog.setVisible(true);
    TwoDMapEditor.frame.add(loadingDialog);
    TwoDMapEditor.frame.revalidate();
    TwoDMapEditor.frame.repaint();          
}

class ProgressBar extends SwingWorker<Void, Void>{
    public int percentage = 1;
    protected Void doInBackground(){
        int i = 0, j;
          while (i < TwoDMapEditor.size[0]) {
              j = 0;
                while(j < TwoDMapEditor.size[1]){
                    if (!TwoDMapEditor.mySql.updateMapPiece(i, j)) {
                        System.out.println("Something went wrong");
                    }
                    percentage = ((i * TwoDMapEditor.size[1]) + j+1) * 100 / (TwoDMapEditor.size[0] * TwoDMapEditor.size[1]);
                    progressBar.setValue(percentage);
                    System.out.println(percentage);
                    j++;
                }
                i++;
          }

        return null;
    }

    public void done(){
        loadingDialog.dispose();
    }
}

public void actionPerformed(ActionEvent me) {
    progressBarClass = new ProgressBar();
    progressBarClass.addPropertyChangeListener(this);
    progressBarClass.execute(); 
}

public void propertyChange(PropertyChangeEvent pce) {
    System.out.println(TwoDMapEditor.saveActionListener.progressBarClass.percentage);
    progressBar.setValue(TwoDMapEditor.saveActionListener.progressBarClass.percentage);
}

}

1 个答案:

答案 0 :(得分:0)

如果没有一个完全可运行的例子,很难知道问题可能在哪里。

您应该在循环中更新进度。如果您可以保证每个TwoDMapEditor.size[1]都是相同的值,那就更容易了。

您基本上需要知道两件事,即可能的迭代总数和您已完成的迭代次数,但我不会在您的代码段中看到可能提供该信息的任何信息。

无论如何,我还建议使用SwingWorker,因为它提供了很容易通知UI进度状态变化的能力,例如......

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestProgress {

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

    public TestProgress() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JDesktopPane dp = new JDesktopPane() {

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(400, 400);
                    }

                };
                JInternalFrame inf = new JInternalFrame("Progressing", true, false, false, false);
                inf.add(new TestPane());
                inf.pack();
                dp.add(inf);
                inf.setVisible(true);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(dp);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JProgressBar pb;

        public TestPane() {
            setLayout(new GridBagLayout());
            pb = new JProgressBar();
            add(pb);

            LongRunningProcessWorker worker = new LongRunningProcessWorker();
            worker.addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    String name = evt.getPropertyName();
                    SwingWorker worker = (SwingWorker) evt.getSource();
                    switch (name) {
                        case "progress":
                            System.out.println(worker.getProgress());
                            pb.setValue(worker.getProgress());
                            break;
                        case "state":
                            switch (worker.getState()) {
                                case DONE:
                                    // Close the window or something
                                    break;
                            }
                            break;
                    }
                }
            });
            worker.execute();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public class LongRunningProcessWorker extends SwingWorker {

        @Override
        protected Object doInBackground() throws Exception {

            Random rnd = new Random();
            int outterMax = rnd.nextInt(150) + 50;
            int innerMax = rnd.nextInt(150) + 50;

            System.out.println(outterMax + "/" + innerMax);

            for (int outter = 0; outter < outterMax; outter++) {
                for (int inner = 0; inner < innerMax; inner++) {
                    float progress = (float)((outter * innerMax) + inner) / (float)(innerMax + outterMax);
                    Thread.sleep(10); // Simulate some processing
                }
            }
            return null;
        }

    }

}

请查看Concurrency in SwingWorker Threads and SwingWorker了解详情