Problem mit invokeLater / invokeAndWait

informatiker85

Grünschnabel
Hallo,
ich habe eine kleines Programm geschrieben, das eine Winamp-Playlist nimmt und alle Dateien in einen Ordner kopiert. So weit, so gut, der Kern des Programms läuft auch wunderbar. Mein Problem ist, dass im SwingGUI eine TextArea als Logging benutzt wird, damit man sieht, wo es Probleme mit dem Kopieren gab und wo da Programm gerade ist.
Das Logging klappt eigentlich auch, nur liefert es den kompletten Text erst ans GUI wenn das Kopieren komplett fertig ist. Das ist natürlich nicht Sinn der Sache bei einem Logging.
Nach einigem Lesen im Forum habe ich verschiedene Varianten mit invokeLater() und invokeAndWait() versucht, die das Problem aber nicht lösten.
Hat einer eine Idee, wie ich das GUI nach jeder Datei aktualisieren kann?
Danke.

Code:
import java.awt.Component;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.nio.channels.FileChannel;

public class PlaylistToFolder extends JFrame
{
	JTextField playListField, folderField;;
	JLabel playListLabel, folderLabel, progressLabel;
	JProgressBar progressBar;
	JButton playlistButton, folderButton, startButton;
	JTextArea logging;

	private String copyFile(String src, String dest)
	{
		File fromFile = new File(src);
		File toFile = new File(dest + "\\"
				+ src.substring(src.lastIndexOf("\\"), src.length()));

		try
		{
			FileChannel inputchannel = new FileInputStream(fromFile)
					.getChannel();
			FileChannel outputchannel = new FileOutputStream(toFile)
					.getChannel();
			inputchannel.transferTo(0, inputchannel.size(), outputchannel);
			inputchannel.close();
			outputchannel.close();
		} catch (FileNotFoundException e)
		{
			return ("Fehler! Datei existiert nicht: " + src);
		} catch (IOException e)
		{
			return ("Fehler beim Lesen oder Schreiben der Datei: " + src);
		}
		return ("Datei erfolgreich kopiert: " + toFile);
	}

	private void parsePlaylist()
	{
		int lineNumber = 0;

		try
		{
			BufferedReader input = new BufferedReader(new FileReader(
					playListField.getText()));
			try
			{
				while (input.ready())
				{
					String tmp = input.readLine();
					lineNumber++;
					if (lineNumber % 2 == 1 && lineNumber != 1)
					{
						if (lineNumber == 3)
						{
							logging
									.setText(copyFile(tmp, folderField
											.getText()));

						} else
						{
							logging.setText(logging.getText() + "\n"
									+ copyFile(tmp, folderField.getText()));

						}
					}
				}
				logging.setText(logging.getText()
						+ "\n\n Alle Aufgaben abgeschlossen.");
				return;
			} catch (IOException e)
			{
				logging.setText(logging.getText()
						+ "Fehler beim Lesen oder Schreiben der Datei: "
						+ playListField.getText());
				return;
			}
		} catch (FileNotFoundException e)
		{
			logging.setText(logging.getText()
					+ "Fehler! Datei existiert nicht: "
					+ playListField.getText());
			return;
		}
	}

	private void addComponent(Container cont, GridBagLayout gbl, Component c,
			int x, int y, int width, int height, double weightx, double weighty)
	{
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = x;
		gbc.gridy = y;
		gbc.gridwidth = width;
		gbc.gridheight = height;
		gbc.weightx = weightx;
		gbc.weighty = weighty;
		gbl.setConstraints(c, gbc);
		cont.add(c);
	}

	public PlaylistToFolder(int screenWidth, int screenHeight)
	{
		this.setSize(700, 500);
		this.setLocation((screenWidth - this.getWidth()) / 2,
				(screenHeight - this.getHeight()) / 2);
		this.setTitle("Playlist-to-Folder");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		Container cont = this.getContentPane();
		GridBagLayout gbl = new GridBagLayout();
		this.setLayout(gbl);

		playListLabel = new JLabel("Playlist: ");
		folderLabel = new JLabel("Ordner: ");
		progressLabel = new JLabel("Fortschritt: ");
		playListField = new JTextField(
				"C:\\Users\\USER 1\\Desktop\\testlist.m3u");
		folderField = new JTextField("C:\\Users\\USER 1\\Desktop\\test");
		progressBar = new JProgressBar();
		logging = new JTextArea();
		logging.setText("");
		playlistButton = new JButton("Durchsuchen...");
		folderButton = new JButton("Durchsuchen...");
		startButton = new JButton("Start");
		ActionListener playlistListen = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				JFileChooser chooser = new JFileChooser();
				chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
				chooser.setMultiSelectionEnabled(false);
				javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {
					public boolean accept(File file)
					{
						if (file.isDirectory())
							return true;
						if (file.getName().endsWith(".m3u"))
							return true;
						else
							return false;
					}

					public String getDescription()
					{
						return "Playlists (*.m3u)";
					}
				};
				chooser.setFileFilter(filter);
				int option = chooser.showOpenDialog(PlaylistToFolder.this);

				if (option == JFileChooser.APPROVE_OPTION)
				{
					File file = chooser.getSelectedFile();
					PlaylistToFolder.this.playListField.setText(file
							.getAbsolutePath());

				} else
				{
					// statusbar.setText("Sie haben " + filelist + " gewählt.");
					// statusbar.setText("Sie haben abgebrochen.");
					System.out.println("Abbruch");
				}
			}
		};
		ActionListener folderListen = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				JFileChooser chooser = new JFileChooser();
				chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				chooser.setMultiSelectionEnabled(false);
				int option = chooser.showOpenDialog(PlaylistToFolder.this);

				if (option == JFileChooser.APPROVE_OPTION)
				{
					File file = chooser.getSelectedFile();
					PlaylistToFolder.this.folderField.setText(file
							.getAbsolutePath());

				} else
				{
					// statusbar.setText("Sie haben " + filelist + " gewählt.");
					// statusbar.setText("Sie haben abgebrochen.");
					System.out.println("Abbruch");
				}
			}
		};
		ActionListener startListen = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e)
			{
				new Thread() 
				{
					public void run()
					{

						try
						{
							// SwingUtilities.invokeLater(new Runnable() {
							SwingUtilities.invokeAndWait(new Runnable() 
							{
								public void run()
								{
									PlaylistToFolder.this.parsePlaylist();
								}

							});
						} 
						catch (InterruptedException e)
						{
							e.printStackTrace();
						}
						catch (InvocationTargetException e)
						{
							e.printStackTrace();
						}
					}
				}.start();
			}
		};
		playlistButton.addActionListener(playlistListen);
		folderButton.addActionListener(folderListen);
		startButton.addActionListener(startListen);

		this.addComponent(cont, gbl, playListLabel, 0, 0, 1, 1, 0, 0);
		this.addComponent(cont, gbl, folderLabel, 0, 1, 1, 1, 0, 0);
		this.addComponent(cont, gbl, playListField, 1, 0, 3, 1, 1, 0);
		this.addComponent(cont, gbl, folderField, 1, 1, 3, 1, 1, 0);
		this.addComponent(cont, gbl, playlistButton, 4, 0, 1, 1, 0, 0);
		this.addComponent(cont, gbl, progressLabel, 0, 3, 1, 1, 0, 0);
		this.addComponent(cont, gbl, progressBar, 1, 3, 5, 1, 1, 0);
		this.addComponent(cont, gbl, folderButton, 4, 1, 1, 1, 0, 0);
		this.addComponent(cont, gbl, startButton, 4, 2, 1, 1, 0, 0);
		this.addComponent(cont, gbl, new JScrollPane(logging), 0, 4, 5, 1,1, 1);
		this.setVisible(true);
	}

	public static void main(String[] args)
	{
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		new PlaylistToFolder(toolkit.getScreenSize().width, toolkit
				.getScreenSize().height);
	}

}
 
Hi informatiker85,

Hab mal einen Blick auf das Programm geworfen.
Dein Stil zu coden macht mich etwas wuschig, aber das soll ja nicht Thema sein.

Du scheinst noch nicht sehr viel GUI-Erfahrung unter Java/Swing zu haben oder
sehe ich das falsch ? (Soll keine Kritik sein !)

So besorgst du dir den ContendPane des Frames, packst den LayoutManager aber
direkt in das JFrame ! Sehr sonderbar, meine IDE (eclipse) hat gleich gemeckert !
Welche IDE nutzt du ?

Das "selbst setzen" der Constraints ist auch sehr ungewöhnlich !
beim container.add(componente,constraints) reicht der Container
die constraints automatisch an den LayoutManager weiter.

Im übrigen ist es auch nicht nötig, immer ein neues GridBagConstraints-Objekt
zu erzeugen. Der LayoutManager erstellt sich selbst eine Kopie und man kann
dann nur die nötigen Änderungen an den Constraints vornehmen (neue Zeile/Spalte etc.)
und das Objekt sozusagen immer recyceln. Mit deiner addComponents-Methode
gehts auch, erzeugt aber auch mehr Datenmüll ! Aber wozu gibts den Garbage-Collector !

Die setText( getText()+"neuer Text" )-Konstrukte sind auch
sehr ulkig ! Was ist gegen append("neuer Text") der TextArea einzuwenden ? ?

Und drei separate ActionListener als Innere-Klassen für drei Buttons ?
Kann man machen . . . aber ! Egal funktioniert ja !

Aber zu deinem eigentlichen Problem :

So richtig ausprobieren konnte ich es nicht, da das Programm meine Playlisten nicht
so richtig Parsen wollte und immer abschmierte. Erst hatte ich in Verdacht, daß der
GUI-Thread über das Button-Event in die Playlist-Verabeitung geht und folglich keine
Zeit mehr fürs updaten der TextArea hat.
Du scheinst aber ja dort irgendwie einen neuen Thread zu erzeugen, der sich darum kümmern soll, die Playlisten zu Parsen ! Aber da blick ich auch nicht mehr so
richtig durch deinen Quellcode durch ! :confused: Kommt aber evtl. noch !

Du kannst ja noch mal deinen Code der die Playlisten zerpflückt kontrollieren !

Gruß JAdix

PS : Ein Java Programm muß nicht zwingend in einer Klasse implementiert sein ! :)
 
Hallo,

ich hatte heute etwas lange- und längere- und noch längere-weile ! :)

Hab mir deinen Code nochmal vorgenommen und etwas drin rumgestrickt !
Ist auch bei der Einklassenlösung geblieben !

Ein invokeLater oder invokeAndWait wirst du aber nirgens finden weil in diesem
Fall unnötig, weil die GUI nicht zwingend mit irgendwas synchron laufen muß !

Soweit läufts jedenfalls . . .

Code:
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;

public class PlaylistToFolder extends JFrame
{
	JTextField playListField, folderField;;
	JLabel playListLabel, folderLabel, progressLabel;
	JProgressBar progressBar;
	JButton playlistButton, folderButton, startButton;
	JTextArea logging;

	private boolean copyFile(File src, File dst) {

		byte[] buffer = new byte[1024];
		int len = 0;
		try {
			FileInputStream fis = new FileInputStream(src);
			FileOutputStream fos = new FileOutputStream(dst);
			
			while (true){
				len=fis.read(buffer);
				if (len>0) {
					fos.write(buffer,0,len);
				}
				else { break; }
			}
			
			fos.close();
			fis.close();
			
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			return false;
		}
		
		return true;
	}
	
	private void copyFiles(Vector src, File dst) {
		
		
		progressBar.setMaximum(src.size()-1);
				
		for (int i=0; i<src.size(); i++) {
			
			File s = (File)src.get(i);
			File d = new File(dst,s.getName());
			logging.append("Kopiere : "+d.getPath());
			if ( copyFile(s,d) ) {
				logging.append(" - OK !\n");
			} else {
				logging.append(" - FAILED !\n");
			}
			progressBar.setValue(i);
		}
	}

	private void parsePlaylist()
	{
		File playlist = new File(playListField.getText());
		
		if (!playlist.exists()) {
			
			logging.setText("Fehler! Datei "+playListField.getText()+" existiert nicht !\n");
			return;
		}
		
		File destination = new File(folderField.getText());
		
		if (!destination.exists() || !destination.isDirectory()) {
			
			logging.setText("Fehler! Verzeichnis "+folderField.getText()+" existiert nicht !\n");
			return;
		}
		
		int jobn = 0;
		long totalbytes = 0;
		Vector jobs = new Vector(10,10);
		String fsep = System.getProperty("file.separator");
		
		try	{

			BufferedReader input = new BufferedReader(new FileReader(playlist));
			
			logging.setText("Verarbeite "+playListField.getText()+"\n");
			
			while (input.ready()) {
				
				String listitem = input.readLine();
				String fileloc = null;	
				
				if (!listitem.startsWith("#")) { // Filter für ExtendetM3U
					
					if (listitem.indexOf(':')!=-1) { // Doppelpunkt des Laufwerksbuchstabens
					
						fileloc = listitem; // Absoluter Pfad !	
					} else {
					
						fileloc = playlist.getParent()+fsep+listitem; // Relativer Pfad !
					}
					
					File mp3file = new File(fileloc);
					if (mp3file.exists() ) {
						jobn++;
						totalbytes+=mp3file.length();
						jobs.add(mp3file);	
						logging.append("OK :"+fileloc+"\n");
					} else {
						logging.append("FAIL :"+fileloc+"\n");
					}
				}
			}

		} catch (IOException e)	{

			logging.append("Fehler beim verarbeiten der Playlist");
		}
		
		logging.append(jobn+" Datein werden kopiert. Insgesamt "+totalbytes+" Bytes\n");
				
		copyFiles(jobs,destination);
	}

	public PlaylistToFolder() {
	
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		this.setBounds(	(toolkit.getScreenSize().width-700)/2,
						(toolkit.getScreenSize().height-500)/2,
						700,500);
		this.setTitle("Playlist-to-Folder");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		Container cont = this.getContentPane();
		cont.setLayout(new GridBagLayout());

		playListLabel = new JLabel("Playlist: ");
		folderLabel = new JLabel("Ordner: ");
		progressLabel = new JLabel("Fortschritt: ");
		playListField = new JTextField("Playlist.m3u");
		folderField = new JTextField("Zielordner");
		progressBar = new JProgressBar();
		logging = new JTextArea("");
		playlistButton = new JButton("Durchsuchen...");
		folderButton = new JButton("Durchsuchen...");
		startButton = new JButton("Start");
		
		// InnerClass ButtonListener 
		ActionListener ButtonListener = new ActionListener() {
		
			public void actionPerformed(ActionEvent e)
			{
				if ( e.getSource()==startButton ) {
					
					Thread t = new Thread() {
						
						public void run() {
							
							parsePlaylist();
						}
					};
					
					t.start();
					return;
				}
				
				JFileChooser chooser = new JFileChooser();
				chooser.setMultiSelectionEnabled(false);
				
				if ( e.getSource()==playlistButton ) {
					
					// InnerClass FileFilter
					javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() {
						public boolean accept(File file)
						{
							if (file.isDirectory())
								return true;
							if (file.getName().endsWith(".m3u"))
								return true;
							else
								return false;
						}

						public String getDescription()
						{
							return "Playlists (*.m3u)";
						}
					}; // FileFilter end

					
					chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
					chooser.setFileFilter(filter);
				} else {
					chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				}
				
				int option = chooser.showOpenDialog(PlaylistToFolder.this);

				if (option == JFileChooser.APPROVE_OPTION) {
			
					File file = chooser.getSelectedFile();
					
					if ( e.getSource()==playlistButton ) {
						
						playListField.setText(file.getAbsolutePath());
					} else {
						folderField.setText(file.getAbsolutePath());
					}
				} else {
					logging.append("Auswahl abgebrochen !");
				}
			}
		};
		
		playlistButton.addActionListener(ButtonListener);
		folderButton.addActionListener(ButtonListener);
		startButton.addActionListener(ButtonListener);

		GridBagConstraints gbc = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 1;
		gbc.gridheight = 1;
		gbc.weightx = 0;
		gbc.weighty = 0;
		cont.add(playListLabel,gbc);
		
		gbc.gridy=1;
		cont.add(folderLabel,gbc);
		
		gbc.gridy=3;
		cont.add(progressLabel,gbc);

		gbc.gridx = 4;
		gbc.gridy = 0;
		cont.add(playlistButton,gbc);
		
		gbc.gridy=1;
		cont.add(folderButton,gbc);
		
		gbc.gridy=2;
		cont.add(startButton,gbc);
		
		gbc.gridx = 1;
		gbc.gridy = 0;
		gbc.gridwidth = 3;
		gbc.weightx = 1;
		cont.add(playListField,gbc);
		
		gbc.gridy = 1;
		cont.add(folderField,gbc);

		gbc.gridy = 3;
		gbc.gridwidth = 5;
		cont.add(progressBar,gbc);

		gbc.gridx = 0;
		gbc.gridy = 4;
		gbc.weighty = 1;
		cont.add(new JScrollPane(logging),gbc);

		this.setVisible(true);
	}

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

}

Hoffe es hilft dir weiter,

Gruß JAdix

PS : ne fette und nette Bewertung wäre prima :)
 
Zurück