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

How to do an updateable JProgressBar in an JInternalFrame inside a thread?

这是我目前所知道的,可能是完全错误的...

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

此外 JInternalFrame 位于程序的其余部分之后,也许 JDialog 会更好。

将在这里提供更多需要的代码,如果您需要更多信息,也愿意 post 在 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);
}

}

没有完全可运行的示例,很难知道问题出在哪里。

你应该勇敢地在循环中更新进度。如果你能保证每个 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 Swing and Worker Threads and SwingWorker 了解更多详情