Paralleler Thread für eine Diashow im JApplet

Status
Nicht offen für weitere Antworten.

Batikan

Mitglied
Hallo!
Nach langer Suche und meheren Experimenten im Punkto Thread Programmierung, muss ich wohl wieder hier einige Herrschaften mit meinen Problemen belästigen. 🙂
Folgendes: Es soll auf einem JApplet mithilfe eines Thread das JLabelicon ín bestimmten zeitabständen verändern werden. Es ist bestimmt nicht die Beste Methode eine Diashow zu realisieren, für neue Ideen bin ich Offen.

Ich erzeuge das Thread in einem JButton-Listener.
Java:
jButtonEinloggen.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
.
.
.
                                           DiashowThread thDia = new DiashowThread(jLabelInfo,station); 
						thDia.start();
						try {
					        Thread.sleep(4000);#
                                                //thDia.sleep(4000) So tritt dasselbe problem auf
					    }

Hier eine kurze Beschreibung der Klasse:
Im Applet wird ein Thread erzeugt der 4 Sekunden anhält. Während diesen 4 Sekunden ist noch ein Thread vorhanden der in Einsekundentakt die Bilder ändern soll, was halt noch nicht funktioniert. Die Konsolenausgabe zeigt mir jedoch, dass dieser durchläuft.
Es soll, wie ich gelesen habe, ein Hauptthread existieren. In diesen 4 Sekunden werden auch andere anzeigen(Berechnungen) unterbrochen.
Ich möchte halt ein "Babythread" haben der diese Diashow steuert

Java:
public class DiashowThread extends Thread{
	public JLabel objJLabelInfoBild;
	int station;
	public DiashowThread(JLabel objJLabelInfo, int round) {
		objJLabelInfoBild = objJLabelInfo;
		station = round;
	}
	
	
	public void run(){
		int tmpStation;
		tmpStation = station +1;
		while(true){
			if (isInterrupted()){
				break;
			}
			Integer istr = new Integer(tmpStation);
			objJLabelInfoBild.setIcon(new ImageIcon(getClass().getResource("/images/bild"+istr.toString()+".jpg")));
				
			showImages(tmpStation); 
			tmpStation++;
		}
				
}
	public void showImages(int i) {
		Integer istr = new Integer(i);
		System.out.println(istr.toString());
		objJLabelInfoBild.setIcon(new ImageIcon(getClass().getResource("/images/bild"+istr.toString()+".jpg")));
		System.out.println(new ImageIcon(getClass().getResource("/images/bild"+istr.toString()+".jpg")).toString());
		objJLabelInfoBild.setText("Hallo"+i);
		try{
			Thread.sleep(1000);
		}catch(InterruptedException e) {
			interrupt();
		}
	
	}
}

Danke für Annregungen.

LG
 
Zuletzt bearbeitet von einem Moderator:
Durch ein Thread.sleep(4000) in der actionPerformed wird der EDT für 4 Sekunden blockiert - in dieser Zeit "friert das GUI ein". Welcher Thread soll denn dort (warum) für 4 Sekunden warten?
 
Hi!
Die 4 Sekunden sollen bewirken, dass die Diashow solange funktionieren soll!
Ich weiß nicht wie ich 4 bilder in jeweils einer Sekunde länge anzeigen soll.
wenn ich diese Unterbrechung mit thdia.sleep mache friert die GUI auch dergleich ein.

Ist halt mein Ansatz... Wie kann ich nun am effektivsten eine Diashow
a. mit meinem Ansatz oder
b. einem anderen Ansatz realisieren.

Danke!
LG
 
wenn ich diese Unterbrechung mit thdia.sleep mache friert die GUI auch dergleich ein.
sleep(...) ist eine statische Methode. Ob du nun Thread.sleep(123) oder thdia.sleep(123) aufrufst macht 0,nix unterschied, außer, dass der Compiler thdia zur Klasse Thread auflöst. Deshalb hast du auch den gleichen Effekt.

Natürlich musst du Threads nutzen, aber eben die komplette "Show" ausgliedern. Das mit den 4 Sekunden ist mir leider auch noch nicht klar, meintest du nun 4x1 Sekunde Bilder? Dann brauchst du einfach nur eine Schleife in der Run-Methode von DiashowThread, die dir den tmpStation hochzählt. Bzw. gibt es einen Grund, warum du das als Konstuktorparameter mitübergibst?
 
Hey,

Ich würde eine Liste machen, welche alle Bilder enthält, wenn jetzt jemand den Button Start drückt, erzeug dieses Event eine Therad, welche das Erste Bild aus der Liste hold und es dan auf das jLabel bringt,nun 4 Sek Schläft & da nach sich das negste Bild holt. usw. So ist nicht der EDT blockirt, weil den Brauchst du um das Bild dan zu Zeichenen. So kannst du auch eine Button Stop ein bauen, der dan den Thread Interruptet^^

Ich kann dir mal schnell ein beispiel scheiben?
 
Die 4 Sekunden sollen bewirken, dass die Diashow solange funktionieren soll!
Ich weiß nicht wie ich 4 bilder in jeweils einer Sekunde länge anzeigen soll.
Das machst du ja schon mit der showImages-Methode: Der Thread, der diese Methode aufruft, wartet dann 1 Sekunde, und wenn es 4 Bilder sind, dauert das insgesamt 4 Sekunden... also, so beim groben Drüberschauen, sollte es schon reichen, das Thread.sleep(4000) aus der actionPerformed rauszunehmen - was funktioniert denn dann nicht?
 
Also ich habe mal eine fertige Diashow gebaut. Es wird eine JFrame erzugt, wo man dan den Pfad zu dem Ordner setzen kann, wo die Images liegen. Man kann dan die Diashow Starten und stopen, also bei mir Funktionirtes Prima.Der Code ist nicht so sauber, man kan noch vieles verbessern.Also Hier meine 3 Klassen für die Diashow:

MainFrame.java
Java:
package diashow.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;

import diashow.gui.control.MainFrameController;
import diashow.thread.DiashowThread;

public class MainFrame extends JLabel {

	private static final long serialVersionUID = -2790640672712386670L;

	/** Der Pfad zum Ordner mit den Bildern */
	private String imagePath = null;

	/** Der JFrame */
	private JFrame f = null;

	/** Das {@link JLabel} fuer die Images */
	private JLabel imageLabel = null;

	/** Der JButton fuer den start der Diashow */
	private JButton startDiashow = null;
	
	/** Der JButton fuer den stop der Diashow */
	private JButton stopDiashow = null;
	
	/** Instanz zu Diashow */
	private DiashowThread diashowThread = null;

	/** Der MainFrame Contoller fuer den ActionListener */
	private MainFrameController mfController = null;

	/**
	 * Erzugt dein {@link MainFrame}
	 */
	public MainFrame() {

		/* Erzugt den MainFrameController */
		mfController = new MainFrameController(this);
		makeGUI();
	}

	/**
	 * Init die GUI, und fuegt alle Comptoneten hinzu
	 */
	private void makeGUI() {
		f = new JFrame("Show");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.setPreferredSize(new Dimension(800, 600));
		f.getContentPane().setLayout(new BorderLayout());

		/* Erzugt den JLabel */
		imageLabel = new JLabel();
		imageLabel.setBorder(new EtchedBorder());
		f.getContentPane().add(imageLabel, BorderLayout.CENTER);

		f.getContentPane().add(buttonPanel(), BorderLayout.SOUTH);

		f.pack();

		f.setLocationRelativeTo(null);
		f.setVisible(true);
	}

	/**
	 * Erzugt eine {@link JPanel} mit allen Buttons
	 * 
	 * @return - das {@link JPanel}
	 */
	private JPanel buttonPanel() {
		JPanel p = new JPanel();

		/* der JButton fuer den Folder Path zu setzten */
		JButton setPath = new JButton("Set Image Path");
		addListener(setPath, "setpath");
		p.add(setPath);

		/* Der Button um die Diashow zu starten */
		startDiashow = new JButton("Start");
		addListener(startDiashow, "start");
		p.add(startDiashow);
		
		/* Der Button um die Diashow zu stoppen */
		stopDiashow = new JButton("Stop");
		stopDiashow.setEnabled(false);
		addListener(stopDiashow, "stop");
		p.add(stopDiashow);

		return p;
	}

	/**
	 * Fuegt einem {@link JButton} eine {@link ActionListener} hinzu.
	 * 
	 * @param b
	 *            der {@link JButton}
	 * @param actionCommand
	 *            - das ActionCommand als {@link String}
	 */
	private void addListener(JButton b, String actionCommand) {
		b.setActionCommand(actionCommand);
		b.addActionListener(mfController);
	}

	/**
	 * Started die Diashow
	 */
	public void startDiashow() {

		/* Pruft ob der ImagePath gesetzt ist */
		if (imagePath == null || imagePath.equals("")) {
			JOptionPane.showMessageDialog(f, "No Image Path set!", "Error", JOptionPane.ERROR_MESSAGE);
			return;
		}
		System.out.println("Start diaShow");

		/* Erzugt den DiashowThread */
		diashowThread = new DiashowThread(this);
		diashowThread.setDelayTime(4000);

		/* Started den Therad */
		Thread t = new Thread(diashowThread);
		t.start();

		/* Disable den StartedButton */
		startDiashow.setEnabled(false);
		stopDiashow.setEnabled(true);
	}
	
	/**
	 * Stoppt die DieShow
	 */
	public void stopDiashow(){
		if(diashowThread != null){
			diashowThread.stop();
		}
	}

	/**
	 * Setzt den ImagePath
	 */
	public void setImagePath() {
		imagePath = JOptionPane.showInputDialog(f, "Pfad zum Ordner mit den Images:", "Input", JOptionPane.INFORMATION_MESSAGE);
	}

	/**
	 * Gibt den Image Path zurueck
	 * 
	 * @return der ImagePath als {@link String}
	 */
	public String getImagePath() {
		return imagePath;
	}

	/**
	 * Gibt das {@link JLabel} zurueck um dan darauf die Images zu setzen
	 * 
	 * @return das {@link JLabel}
	 */
	public JLabel getImageLabel() {
		return imageLabel;
	}

	/**
	 * Gibt den Start Button von der Diashow zurueck
	 * 
	 * @return der {@link JButton}
	 */
	public JButton getStartDiashow() {
		return startDiashow;
	}
	
	/**
	 * Gibt den {@link JButton} zureck verlcher zum Stoppen der Diashow zustaendig ist
	 * @return der {@link JButton}
	 */
	public JButton getStopDiashow() {
		return stopDiashow;
	}

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

}
MainFrameController.java
Java:
package diashow.gui.control;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import diashow.gui.MainFrame;

public class MainFrameController implements ActionListener{
	
	private MainFrame mainFrame = null;

	public MainFrameController(MainFrame mainFrame) {
		this.mainFrame = mainFrame;
	}

	public void actionPerformed(ActionEvent e) {
		String actionCommand = e.getActionCommand();
		
		if(actionCommand.equals("start")){
			mainFrame.startDiashow();
		}else if(actionCommand.equals("setpath")){
			mainFrame.setImagePath();
		}else if(actionCommand.equals("stop")){
			mainFrame.stopDiashow();
		}
	}
	
	

}
DiashowThread.java
Java:
package diashow.thread;

import java.io.File;
import java.io.FileFilter;

import javax.swing.ImageIcon;
import javax.swing.JLabel;

import diashow.gui.MainFrame;

public class DiashowThread implements Runnable {

	/** Ob die Diashow gestartet ist */
	private boolean started = true;

	/** Der Timer fuers negste Bild */
	private int delayTime = 2000;

	/** der Image Folder Path */
	private String imagePath = null;

	/** Alle Images als File */
	private File[] images = null;

	/** Das Image Labe um die Images anzuziegen */
	private JLabel imageLable = null;

	/** Der MAinFrame */
	private MainFrame mainFrame = null;

	/**
	 * Erzugt den Diashow Thread mit dem MainFrame, um den ImagePath und das
	 * ImageLabel zuholen
	 * 
	 * @param mainFrame
	 *            - der {@link MainFrame}
	 */
	public DiashowThread(MainFrame mainFrame) {
		this.mainFrame = mainFrame;
		this.imagePath = mainFrame.getImagePath();
		this.imageLable = mainFrame.getImageLabel();
	}

	public void run() {

		/* Prueft ob der Therad gestartet ist */
		if (!isALive()) {
			System.err.println("Diashow not ALive!");
			/* Aktivirt wider den Start Button und Setzt das Image Null */
			cleanUP();
			return;
		}

		System.out.println("Image Folder Path: " + imagePath);

		/* Durechlauft den Folder und prueft ob bilder gefunden worden sind */
		if (!getImages() || images.length <= 0) {
			System.err.println("Cna't load or find Images!");
			/* Aktivirt wider den Start Button und Setzt das Image Null */
			cleanUP();
			return;
		}

		for (File file : images) {
			/* Prueft ob die Diashow gestartet ist */
			if (!isALive()) {
				System.err.println("Diashow not ALive!");
				/* Aktivirt wider den Start Button und Setzt das Image Null */
				cleanUP();
				return;
			}

			System.out.println(file.getAbsolutePath() + " loaded!");

			/* Leade das Image auf das JLabel */
			imageLable.setIcon(loadImage(file));
			/* Zeichnet das JLabel neu */
			imageLable.revalidate();

			/* Schlaeft */
			sleep();
		}

		System.out.println("Diashow ends!");

		/* Aktivirt wider den Start Button und Setzt das Image Null */
		cleanUP();
	}

	/**
	 * Hold alle Images aus den Folder und spiecher sie in der Array
	 * 
	 * @return {@link Boolean} True / false
	 */
	private boolean getImages() {
		File path = new File(imagePath);

		/* Prueft den Folder */
		if (!path.canRead() || !path.isDirectory() || !path.exists()) {
			return false;
		}

		/* Erzugt eine FileFilder um nur Images zu laden */
		FileFilter fileFilter = new FileFilter() {
			public boolean accept(File pathname) {
				return pathname.getName().endsWith("jpg") || pathname.getName().endsWith("png") || pathname.getName().endsWith("gif");
			}

		};

		/* Lade alle Images als Files */
		images = path.listFiles(fileFilter);

		return true;
	}

	/**
	 * Leade das Image aus dem File
	 * 
	 * @param file
	 *            - das Image als {@link File}
	 * @return das {@link ImageIcon}
	 */
	private ImageIcon loadImage(File file) {
		if (!file.exists() || file.isDirectory() || !file.canRead()) {
			return null;
		}

		return new ImageIcon(file.getAbsolutePath());
	}

	private void sleep() {
		try {
			Thread.sleep(delayTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void setDelayTime(int delayTime) {
		this.delayTime = delayTime;
	}

	public boolean isALive() {
		return started;
	}

	/**
	 * Aktivirt den Started Button und entfert das Image vom jLabel
	 */
	private void cleanUP() {

		/* Setzt Image Null */
		imageLable.setIcon(null);
		/* Kurze Info */
		imageLable.setText("Diashow Ende");
		imageLable.setHorizontalAlignment(JLabel.CENTER);

		/* Zeichnet Neu */
		imageLable.revalidate();

		/* Aktivirt den Start Button */
		mainFrame.getStartDiashow().setEnabled(true);
		mainFrame.getStopDiashow().setEnabled(false);
	}
	
	/**
	 * Stopt die Diashow
	 */
	public void stop(){
		System.out.println("Stop Diashow in max. " + delayTime + " s.");
		started = false;
		cleanUP();		
	}
}

Vielicht bring das dich auf eine bessere Idea^^ (bitte die rechtschreibfehler Ignorieren)

edit: Wenn du das Projekt haben Willst kann ich es die Schiken^^
 
Hey super danke dir!
ICh hab es jetzt ander gelöst!

Ich erzeuge ein Objekt einer JPanel Klasse und setzte diesen JPanel in das JApplet.

Java:
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import javax.swing.JPanel;
import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;

public class JDiaPanel extends JPanel implements Runnable {

	Thread th;
	private Image[] arImg;
	private int actimage;
	private int ladeimage;
	/**
	 * This is the default constructor
	 */
	public JDiaPanel() {
		super();
		initialize();
		th = new Thread(this);
	}

	private void initialize() {
		
		this.setSize(309, 288);
		this.setLayout(null);
	}
	
	public void startAnimation()
	  {
		    actimage = -1;
		    th.start();
	  }
	
	  public void run()
	  {
	    //Animation beginnen
	    actimage = 0;
	    while (true) {
	    	if (th.isInterrupted()){ 
	    		break;
	    	}
	      repaint();
	      actimage = (actimage + 1) % 5;
	      try {
	        Thread.sleep(2000);
	      } catch (InterruptedException e) {
	      }
	    }
	  }

	  public void paint(Graphics g)
	  {
	    if (actimage < 0) {
//	   if (getLadeimage() < 0) {
	      g.drawString("Lade Bitmap "+(-actimage),10,50);
	    } else {
	      g.drawImage(getArImg()[actimage],0,0,this);
	    }
	  }

	public void setArImg(Image[] arImg) {
		this.arImg = arImg;
	}

	public Image[] getArImg() {
		return arImg;
	}

	public void setLadeimage(int ladeimage) {
		this.ladeimage = ladeimage;
	}

	public int getLadeimage() {
		return ladeimage;
	}

}

Im JApplet habe ich folglich dieses:

diapanel.setArImg(arImg);
diapanel.startAnimation();

Es funktioniert einwandfrei. Jedoch arbeite ich gerade dran, die diashow zu stoppen.
th.stop bringt nocht da es Depricated ist. und mit

public void stopDiashow(){
th.interrupt();
}
komme ich auch nicht weit. Was kann ich tun um diesen Thread sicher zu stoppen und wieder zu starten:...

Danke!!!
 
Zuletzt bearbeitet von einem Moderator:
Java:
th.interrupt();
Und in Zeile 50 einfügen:
Java:
// "interrupted" flag needs to be reset after InterruptedException
Thread.currentThread().interrupt();
Ebenius
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben