1

I have a java program that load a text file as input, read its content, modify some strings and then prints the result to a textarea. Due to several seconds required by this operation i would like to show a JProgressBar during this activity in order to inform the user that the execution is in progress and when the activity is completed close the dialog containing the JprogressBar and print the results.

Here is the code:

JButton btnCaricaFile = new JButton("Load text file");
        panel.add(btnCaricaFile);
        btnCaricaFile.setIcon(UIManager.getIcon("FileView.directoryIcon"));
        btnCaricaFile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //JFileChooser choice = null;
                final JFileChooser choice = new JFileChooser(userDir +"/Desktop");
                int option = choice.showOpenDialog(GUI.this);
                if (option == JFileChooser.APPROVE_OPTION) {
                    final JDialog dialog = new JDialog(GUI.this, "In progress", true);
                    JProgressBar progressBar = new JProgressBar(0, 100);
                    progressBar.setIndeterminate(true);
                    dialog.getContentPane().add(BorderLayout.CENTER, progressBar);
                    dialog.getContentPane().add(BorderLayout.NORTH, new JLabel("Elaborating strings..."));
                    dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
                    dialog.setSize(300, 75);
                    dialog.setLocationRelativeTo(GUI.this);
                    Thread t = new Thread(new Runnable() {
                        public void run() {
                            dialog.setVisible(true);
                            File file = choice.getSelectedFile();
                            lista.clear();
                            textArea.setText("");
                            lista = loadFile.openFile(file);
                            for(int i=0; i<lista.size(); i++) {
                                textArea.append(lista.get(i)+"\n");
                            }
                            dialog.setVisible(false);
                        }
                    });
                    t.start();
                }
            }
        });

For this purpose i'm using a JDialog as container for the JProgressBar executed by an appropriate thread. The problem is that the progress bar is shown for an infinite time and is not printed anything to the textarea.

Could you help me to solve this? Thanks

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
xXJohnRamboXx
  • 739
  • 3
  • 10
  • 24

1 Answers1

4

Yes, you're creating a background thread for your file reading, good, but you're also making Swing calls from within this same background thread, not good, and this is likely tying up the Swing event thread inappropriately. The key is to keep your threading separate -- background work goes in the background thread, and Swing work goes only in the Swing thread. Please read Lesson: Concurrency in Swing fore more on this.

Myself, I would create and use a SwingWorker<Void, String>, and use the worker's publish/process method pair to send Strings to the JTextArea safely.

For example, something like...

final JDialog dialog = new JDialog(GUI.this, "In progress", true);
JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setIndeterminate(true);
dialog.getContentPane().add(BorderLayout.CENTER, progressBar);
dialog.getContentPane().add(BorderLayout.NORTH, new JLabel("Elaborating strings..."));
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setSize(300, 75);
dialog.setLocationRelativeTo(GUI.this);
lista.clear();
SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {

    @Override
    public Void doInBackground() throws Exception {
        // all called *off* the event thread
        lista = loadFile.openFile(file);
        for (int i = 0; i < lista.size(); i++) {
            publish(lista.get(i));
        }
        return null;
    }

    @Override
    protected void process(List<String> chunks) {
        // called on the event thread
        for (String chunk : chunks) {
            textArea.append(chunk + "\n");
        }
    }

    // called on the event thread
    public void done() {
        dialog.setVisible(false);
        // should call get() here to catch and handle
        // any exceptions that the worker might have thrown
    }
};
worker.execute();
dialog.setVisible(true); // call this last since dialog is modal

Note: code not tested nor compiled

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373