Swing JProgressBar in JDialog wird nicht angezeigt

Curry

Aktives Mitglied
Moin Moin!

Ich lese die Dateien eines Verzeichnises aus. Nach dem Auslesen werden diese Dateien in einer for-Schleife verarbeitet. Dieser Vorganng ist zeitintensiv. Deshalb würde ich gerne ein JDialog anzeigen, der den Status des Vorgangs mit einer JProgressbar und einer JTextArea wiederspiegelt.

Doch wird der Inhalt des JDialog immer erst angezeigt, wenn die ganze Arbeit getan ist. Oder wenn ich den Dialog modal setze (was eigentlich auch richtig wäre), dann läuft die Schleife nicht mehr ab.

Was könnte ich da tun? Threads?

Java:
public void readDirectory(String path) {
	
	File dir = new File(path);
	File[] files = dir.listFiles();
	
	// Dialog
	final JDialog dialog = new JDialog((JFrame)null, "Loading ...");
//	dialog.setModal(true);
	
	// Dialog - Label & ProgressBar
	JProgressBar pb = new JProgressBar(1, files.length);
	pb.setPreferredSize(new Dimension(175,20));
	pb.setString("Working");
	pb.setStringPainted(true);
	pb.setValue(1);
	
	JLabel label = new JLabel("Progress: ");
	JPanel northPanel = new JPanel();
	northPanel.add(label);
	northPanel.add(pb);
	dialog.getContentPane().add(northPanel, BorderLayout.NORTH);

	// Dialog - TextArea
	JTextArea ta = new JTextArea(10, 20);
	JPanel centerPanel = new JPanel();
	centerPanel.add(new JScrollPane(ta));
	dialog.getContentPane().add(centerPanel, BorderLayout.CENTER);
	
	// Dialog - Button
	JButton button = new JButton("Done");
	button.setActionCommand("done");
	button.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
			if ( evt.getActionCommand().equals("done") ) {
				dialog.dispose();
			}
		}
	});
	JPanel southPanel = new JPanel();
	southPanel.add(button);
	dialog.getContentPane().add(southPanel, BorderLayout.SOUTH);
	
	// Dialog - Anzeige
	dialog.pack();
	dialog.setLocationRelativeTo(null);
	dialog.setVisible(true);
	dialog.toFront();
	
	// Logik
	if (files != null) {
		for (int i = 0; i < files.length; i++) {
			if (files[i].isFile()) {
				int id = Integer.parseInt(files[i].getName().substring(0, files[i].getName().indexOf('.')));
				// Verarbeitung der Dateien die Zeit braucht steht eigentlich hier
				pb.setValue(i+1);
				ta.append((i + 1) + " -> " + Integer.toString(id) + "\r\n");
			}
		}
	}
}
 
Ich habe schon Jahre nichts mehr mit Swing gemacht, aber es sollte auch ohne repaint funktionieren sobald das Threading Problem behoben ist.
 
Ich habe mir eure Tipps mal angeschaut und ein Demo-Programm (welches die Anforderungen in meinem eigentlichen Programm simuliert) geschrieben.

Es funktioniert eigentlich schon sehr schön. Der Arbeitsprozess ist jetzt in einer Klasse MyWorker untergebracht, welche von Thread abgeleitet wurde. Für die Anzeige des Fortschritts verwende ich eine Klasse MyProgressDialog, die von JDialog abgeleitet ist. Das funktioniert auch schon sehr schön, aber wenn ich den Dialog modal setze, dann läuft der Worker nicht. Warum das so ist, dass verstehe ich schon, aber ich habe leider keine Idee wie ich das besser machen kann.

Die offizielle Klasse SwingWorker möchte ich ungerne benutzen, da ich sie nicht komplett verstehe. Ich würde lieber etwas Schlankeres verwenden, das ich selbst durchdringe. ;-)
Würde mich über Hilfe, Tipps und Anregungen freuen.

Hauptprogramm:
Java:
import java.awt.*;
import java.awt.event.*;
import java.io.File;

import javax.swing.*;


class MainFrame extends JFrame implements ActionListener {

	public MainFrame() {
		super("Test");
		initComponents();
	}
	
	private void initComponents() {
		Container cp = getContentPane();
		cp.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		
		JButton button = new JButton("start");
		button.addActionListener(this);
		gbc.gridy = 1;
		gbc.gridx = 1;
		cp.add(button, gbc);
		pack();
	}
	
	public void actionPerformed(ActionEvent event) {
		
		System.out.println(getClass().getName() + ".actionPerformed");
		
		File dir = new File("d:/");
		File[] files = dir.listFiles();
		
		/*
		 * Der Dialog soll den Fortschritt des Workers anzeigen und den Rest des unterbrechen (bis auf den Worker)
		 */
		MyProgressDialog dialog = new MyProgressDialog(this, "Loading...", 0, files.length);
		
		/*
		 * Der Worker vollrichtet die Arbeit und gibt dem Dialog regelmäßig den aktuellen Fortschritt durch, 
		 * damit dieser dem User diesen anzeigen kann
		 */
		MyWorker worker = new MyWorker(files, dialog);
		worker.start();
	}
	
}

MyProgressDialog:
Java:
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class MyProgressDialog extends JDialog implements ActionListener {
	
	private JProgressBar pb;
	private JTextArea ta;
	private JButton button;
	private String msg;
	
	private int min;
	private int max;
	private int i;
	
	public MyProgressDialog(Frame owner, String msg, int min, int max) {
		super(owner, false);

		this.msg = msg;
		this.min = min;
		this.max = max;
		this.i = min;		
		
		initComponents();
	}
	
	public void initComponents() {
		
		Container cp = getContentPane();
		cp.setLayout(new GridBagLayout());
		GridBagConstraints gbc = new GridBagConstraints();
		
		// Label
		JLabel label = new JLabel(msg);
		gbc.gridy = 1;
		gbc.gridx = 1;
		cp.add(label, gbc);
		
		// ProgressBar
		pb = new JProgressBar(min, max);
		pb.setPreferredSize(new Dimension(175,20));
		pb.setString("in progress");
		pb.setStringPainted(true);
		pb.setValue(1);
		gbc.gridy = 2;
		gbc.gridx = 1;
		cp.add(pb, gbc);
		
		// TextArea
		ta = new JTextArea(10, 20);
		gbc.gridy = 3;
		gbc.gridx = 1;
		cp.add(new JScrollPane(ta), gbc);
		
		// Button
		button = new JButton("close");
		if(i < max) {
			button.setEnabled(false);
		}
		gbc.gridy = 4;
		gbc.gridx = 1;
		cp.add(button, gbc);

		// Display the Dialog
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
		toFront();
	}
	
	public void increment() {
		i++;
		pb.setValue(i);
		if(i >= max) {
			button.setEnabled(true);
			pb.setString("done");
		}
	}
	
	public void addComment(String comment) {
		ta.append(comment);
	}
	
	public void actionPerformed(ActionEvent event) {
		System.out.println(getClass().getName() + ".actionPerformed");
	}
	
}

MyWorker:
Java:
import java.io.*;


public class MyWorker extends Thread {
	
	private boolean running = false;
	private File[] files;
	private MyProgressDialog dialog;
	
	public MyWorker(File[] files, MyProgressDialog dialog) {
		this.files = files;
		this.dialog = dialog;
	}
	
	public void run() {
		
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				dialog.increment();
				dialog.addComment(files[i].getName() + "\r\n");
				try {
					sleep(2500);
				} catch (InterruptedException ex) {
					ex.printStackTrace();
				}
			}
		}
		
	}

}
 

Zurück
Oben