0

There are some example for similar question (Progress Bar Java) and (Java uploading percentage progressbar thread) but didn't understand how to make it work for my code.

My main has 2 panels one over the other (one of which is a tabbedPane with 2 tabs)

public class MainIRH {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }
                MainWindow window = new MainWindow();
                JPanel mainPanel = new JPanel(new BorderLayout(0, 20));
                mainPanel.setBorder(new EmptyBorder(20, 20, 20, 20));

                JTabbedPane tabbedPane = new JTabbedPane();
                tabbedPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));

                ControlPanel controlPanel = new ControlPanel();

                tabbedPane.setBorder(new EmptyBorder(10, 10, 10, 10));
                controlPanel.setBorder(new EmptyBorder(0, 20, 20, 20));

                ECPanel ecPanel = new ECPanel();
                SMRPanel smrPanel = new SMRPanel();

                tabbedPane.addTab("Environnement Canada", null, ecPanel, "Convertir des données des stations d\'Environnement Canada");
                tabbedPane.addTab("Station Météo Routière", null, smrPanel, "Convertir des données des stations météos routières");

                mainPanel.add(tabbedPane, BorderLayout.NORTH);
                mainPanel.add(controlPanel, BorderLayout.CENTER);
                window.add(mainPanel);

                new ControllerIRH(ecPanel, smrPanel, controlPanel);

                window.setVisible(true);
            }
        });
    }
}

The important bit is this object : SMRPanel smrPanel = new SMRPanel();

Inside this object I have a JButton convertArchiveButton that I add a ActionListener from a Controller class

public void addConvertArchiveButton(ActionListener ConvertArchiveButton) {
    convertArchiveButton.addActionListener(ConvertArchiveButton);
}

Here's the the implementation of the Listener in the Controller

private class ConvertArchiveButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent event) {
             converter.convert();
    }
}

converter is the class that does the lengthy operation

File[] listOfFiles = folder.listFiles();

for (int file = 0; file < listOfFiles.length; file++) {

     int progress = Math.round(file * 100 / listOfFiles.length);

     //tried a lot of things here...

    //...computing

}

I example tried to add some new Runnable with both EventQueue and SwingUtilities but didn't work. A SwingWorker class would be useful? Don't quite understand the use.

Basically, int progress would be passed to the JProgressBar in the SMRPanel.

EDIT WITH ControlAltDel answer :

Still doesn't work, converter.readFile(file); doesn't get called.

private class ConvertArchiveButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent event) {
        File[] listOfFiles = folder.listFiles();

        System.out.println(listOfFiles.length);

        for (int i = 0; i < listOfFiles.length; i++) {
            final File file = listOfFiles[i];
            final int idx = (i * 100) / listOfFiles.length;
            Thread t = new Thread(new Runnable() {
                public void run() {
                    converter.readFile(file);

                    System.out.println(idx);

                    SwingUtilities.invokeLater(new Runnable() {

                        @Override
                        public void run() {
                            smrPanel.setProgressBarValue(idx);
                        }
                    });
                }
            });

            try {
                t.start();
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        converter.convert(year);

    }
}
Community
  • 1
  • 1
Benoit
  • 363
  • 6
  • 23
  • Basically, you need your runnable to be executed in any thread but the EDT. EventQueue and SwingUtilities only dispatch to the EDT. Yes a SwingWorker will do a great job at this: For [example](http://stackoverflow.com/questions/16288303/best-example-for-programmatically-creating-splashscreen-with-text/16289376#16289376). – Guillaume Polet Aug 18 '15 at 18:43
  • sorry, shoud be try try { t.start(); t.join(); } ... – ControlAltDel Aug 18 '15 at 19:39
  • I have modified my code... I made a mistake that could cause the file processing threads to complete and the adjustment of the ProcessBar to not take place in order. I have now fixed this – ControlAltDel Aug 18 '15 at 19:55
  • @ControlAltDel That was doing what you thought at first, but the update did the trick. – Benoit Aug 18 '15 at 20:09

1 Answers1

3

Your problem is that you are running your loop in the EDT thread. Fix by running this in another thread, and then setting the updated progress value in the EDT when you finish processing a file

private class ConvertArchiveButtonListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent event) {
            new Thread(new Runnable() {
            public void run() {
               for (int file = 0; file < listOfFiles.length; file++) {
                  final File f = listOfFiles[i];
                  final idx = file;
                  Thread t = new Thread(new Runnable() {
                    converter.convert(f);
                    swingUtilities.invokeLater(new Runnable() {
                      myProgressBar.setValue(idx);
                    });
                   t.start();
                   t.join();
                  });
                 }
             }).start();
    }
}
ControlAltDel
  • 33,923
  • 10
  • 53
  • 80