Methode in eigenem Thread auslagern

Status
Nicht offen für weitere Antworten.

Dagobert

Bekanntes Mitglied
Einen wunder schönen guten Tag,

Ich habe ein mehr oder weniger kleines Problem (ich weis nicht wie groß XD):
Ich habe ein Hauptfenster und eine Klasse map. In der Klasse map wird die Karte für das Spiel gespeichert, und die Operationen für die Karte zu verfügung gestellt.
Nun möchte ich aus dem Hauptfenster die Karte laden. Da dies aber sehr lange dauern kann, möchte ich dieses in ein extra Thread auslagern, damit die GUI nicht gespert wird und ich ein ProgressMonitor verwenden kann.
Jedoch bekomme ich das nicht so ganz hin, dass ich die Methode in einem extra Thread ausgeführt wird. Desweitern müsste dieser Thread auf eine Variable aus dem Hauptfenster zugreiffen können und die Karte als Rückgabewert zurückgeben. Wie bekomme ich dies hin?
Ich habe versucht die Klasse map mit Runnable zu erweitern, aber dies ist ja nicht ganz mein Ziel oder?! Da ja so die ganze Karte als eignes Thread läuft, kann ich doch späte Probleme bei den Animmationen bekommen, da ich ja die Frame- bzw. Delta-Zeiten aus den Hauptfenster beachten muss, oder?

Das Hauptfenster:
Code:
public class MapEditor extends JPanel implements Runnable {

	public void loadMap() {
		JFileChooser fc = new JFileChooser("resourcen/maps/");
		fc.setDialogTitle("Karte wählen");
		fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
		fc.setAcceptAllFileFilterUsed(false);
		fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
			public boolean accept(File f) {
				return f.isDirectory()
						|| f.getName().toLowerCase().endsWith(".mapi");
			}

			public String getDescription() {
				return "map(*.mapi)";
			}
		});
		
		int returnvalue = fc.showOpenDialog(null);
		if (returnvalue == JFileChooser.APPROVE_OPTION) {
			File selecteFile = fc.getSelectedFile();
				System.out.println("Karte wird geladen");
				map = map.loadMap(selecteFile.getAbsolutePath());
		}	
	}
}

Die Karte:
Code:
public class Map{
	
	private String name;				// Name der Karte
	private String author;				// Autor der Karte
	private String description;			// Beschreibung der Karte selbst
	private long height;				// Aktuelle Höhe der Karte
	private long width;					// Aktuelle Breite der Karte
	
	private HashMap<Integer, Tile> availableTiles;	// Verfügbare Tiles werden gespeichert
	private Vector<Tile> tiles;				// Speicher für die Tiles der Karte
	private Vector<Objects> objects;		// Speicher für die Objekte der Karte
	
	//Hauptkonstruktor, der immer alle Atribute erwartet
	public Map(int height, int width, String name, String author, String description, Vector<Tile> tiles){
		
		setHeight(height);
		setWidth(width);
		setName(name);
		setAuthor(author);
		setDescription(description);
		copyTile(tiles);
		
		availableTiles = new HashMap<Integer, Tile>();
		tiles = new Vector<Tile>();
	}
	
	public Map(){
		this(10, 10 , "", "", "", new Vector<Tile>());
	}
	
	public Map(int height, int width){
		this(height, width, "", "", "", new Vector<Tile>());
	}
	
	public Map(int height, int width, Vector<Tile> tiles){
		this(height, width, "", "", "", tiles);
	}
				
	public Map loadMap(String openFile){
		System.out.println(openFile);
		FileReader fr = null;
		Map map = new Map();
		try {
			fr = new FileReader(openFile);
		} catch (FileNotFoundException e) {
			System.out.println("Karte konnten nicht geladen oder gefunden werden");
			e.printStackTrace();
			return null;
		}
		try {
			Document xml = new SAXBuilder().build(fr);
			Element root= xml.getRootElement();
			Element eigenschaften = root.getChild("eigenschaften");
			Element tilesInfo = root.getChild("tiles");
			map.setName(eigenschaften.getAttributeValue("name"));
			map.setAuthor(eigenschaften.getAttributeValue("autor"));
			map.setDescription(eigenschaften.getAttributeValue("beschreibung"));
			map.setWidth(eigenschaften.getAttribute("breite").getLongValue());
			map.setHeight(eigenschaften.getAttribute("hoehe").getLongValue());
		    File f = new File("./resourcen/tiles/");
		    
			String[] filenames = f.list(new FilenameFilter(){
				public boolean accept(File dir, String name){
					return name.endsWith(".ttr");
		    }});
						
			for(int i = 0; i < filenames.length; i++){
				Tile tile = new Tile();
				tile = tile.loadTile("./resourcen/tiles/" + filenames[i]);
				map.availableTiles.put(tile.getID(),tile);
			}
										
			for(int i = 1; i <= tilesInfo.getAttribute("anzahl").getLongValue();i++){
				Element currentTileInfo = tilesInfo.getChild("t"+i);
				Tile tile =  map.availableTiles.get(currentTileInfo.getAttribute("id").getIntValue());
				tile.setPosition(currentTileInfo.getAttribute("xpos").getIntValue(), currentTileInfo.getAttribute("ypos").getIntValue());
				addTile(tile);
			}
		} catch (JDOMException e) {
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return map;
	}
}

mfg. Dagobert
 
S

Spacerat

Gast
Schau dir mal "java.util.concurrent,FutureTask" an (JDK/JRE1.6). Da kann man z.B. ein anonymes "Runnable" und ein Objekt der Klasse die man zurückgegeben haben will übergeben. Ich selber hab' zwar mit diesem Paket selber noch nicht gearbeitet, aber vllt. gehts damit ja besser, als eine komplette innere oder eingebettete Klasse selbst zu basteln.
 

Marco13

Top Contributor
Wichtig wäre auch zu wissen, was dort wo gestartet wird. Ein "new Thread" habe ich beim Überfliegen jedenfalls nicht gesehen...
 

Dagobert

Bekanntes Mitglied
Da wird noch nix gestartet, weil ich auf dem Schlauch stehe und das auch nur ausschnitte sind, da bestimmt keiner lust hat den ganzen code zu durch zu gucken oder? (sind immerhin schon >1000 Zeilen)
Also ich starte die Hauptkasse als Thread, aber wenn ich einfach so die Karte dann durch das gleiche Thread laden lasse schläft die GUI ein wenn ich ein JDialo/Progressmonitor aufbauen will, oder ich mache dabei auch was falsch. Es geht mir eigentlich nur darum eine Statusanzeige für das Laden einzubauen, wenn wer ne laternative zu meiner Threadidee hat bin ich gerne dafür offen ;)

mfg. Dagobert
 
S

Spacerat

Gast
Marco13 hat gesagt.:
Wichtig wäre auch zu wissen, was dort wo gestartet wird. Ein "new Thread" habe ich beim Überfliegen jedenfalls nicht gesehen...
Tja... so recht weis ich das auch nicht... Müsste da auch erst Experimentieren. z.B. mit solch einem Ansatz:
Code:
new Thread(new RunnableFuture<ReturnObject>()
{
  public boolean cancel(boolean mayInterruptIfRunning)
  {
    // ...
  }

  public boolean isCanceled()
  {
    // ...
  }

 public ReturnObject get(long value, TimeUnit tu)
  {
    // ...
  }

  public ReturnObject get()
  {
    // ...
  }

  boolean isDone()
  {
    // ...
  }

  void run()
  {
    // ...
  }
}, "EXPERIMENTAL").start();
Versuch was draus zu machen... good Luck...
@Edit: Huch... Hab' mich angesprochen gefühlt, weil ich bei meinem Vorschlag so etwas auch nicht gesehen habe...
 
Zuletzt bearbeitet von einem Moderator:

Dagobert

Bekanntes Mitglied
Danke für die Anregung.
Ich werde mal gucken was ich raus mache kann. Und fallls nicht weiter komme melde ich mich wieder und rücke mit mehr Geheimnissen raus.
Aber noch eine Frage kann ich einem Thread Parameter mit auf dem weg geben oder wie komme ich an meinen Filename ran? Und wöfür steht das "EXPERIMENTAL" als 2ter Paramter beim Threadaufruf?

mfg. Dagobert
 
S

Spacerat

Gast
Das "EXPERIMENTAL" soll der Thread-Name sein. Hier kennzeichnet er, das der Code nicht gestestet wurde. Kenn geändert aber auch weggelassen werden.
 

Dagobert

Bekanntes Mitglied
Ich hab jetzt mal das so aufgebaut:
Code:
setMap(new Thread(new RunnableFuture<Map>(){
				
				private Map map = null;
								
				public void run(){
					
					map = new Map();
					
					JFileChooser fc = new JFileChooser("resourcen/maps/");
					fc.setDialogTitle("Karte wählen");
					fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
					fc.setAcceptAllFileFilterUsed(false);
					fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
						public boolean accept(File f) {
							return f.isDirectory()
									|| f.getName().toLowerCase().endsWith(".mapi");
						}

						public String getDescription() {
							return "map(*.mapi)";
						}
					});
					
					int returnvalue = fc.showOpenDialog(null);
					if (returnvalue == JFileChooser.APPROVE_OPTION) {
						File selecteFile = fc.getSelectedFile();
						map = map.loadMap(selecteFile.getAbsolutePath());
					}
				}

				@Override
				public Map get() throws InterruptedException,
						ExecutionException {
					System.out.println("Get zurück");
					return map;
				}

				@Override
				public Map get(long arg0, TimeUnit arg1)
						throws InterruptedException, ExecutionException,
						TimeoutException {
					// TODO Auto-generated method stub
					return null;
				}

				@Override
				public boolean isCancelled() {
					// TODO Auto-generated method stub
					return false;
				}

				@Override
				public boolean isDone() {
					// TODO Auto-generated method stub
					return false;
				}

				@Override
				public boolean cancel(boolean mayInterruptIfRunning) {
					// TODO Auto-generated method stub
					return false;
				}
			},"MAPLOAD").start());
	}

	public void setMap(Map map) {
		this.map = map;
	}

	public Map getMap() {
		return this.map;
	}

Wie bekomme ich denn jetzt das Object zurückgegeben, er macht das ja nicht von alleine wie ich feststellen musste^^

mfg. Dagobert
 

yujin

Neues Mitglied
Hallo,

probier mal folgendes:

Code:
public class MapEditor extends JPanel implements Runnable {

    public void loadMap() {
        JFileChooser fc = new JFileChooser("resourcen/maps/");
        fc.setDialogTitle("Karte wählen");
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(new javax.swing.filechooser.FileFilter() {
            public boolean accept(File f) {
                return f.isDirectory()
                        || f.getName().toLowerCase().endsWith(".mapi");
            }

            public String getDescription() {
                return "map(*.mapi)";
            }
        });
        
        int returnvalue = fc.showOpenDialog(null);
        if (returnvalue == JFileChooser.APPROVE_OPTION) {
    
// SwingWorker anlegen
            SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() {
                    File selecteFile = fc.getSelectedFile();
                    System.out.println("Karte wird geladen");
                    map = map.loadMap(selecteFile.getAbsolutePath());        
                    return null;
                }
                @Override
                public void done() {
                    
                }
            };
// SwingWorker ausführen, Aufgabe läuft im Hintergrund
            worker.execute();            
        }    
    }
}
Mit dem SwingWorker lagerst du deine aufgabe in einem neuen Thread aus und die GUI wird dadurch nicht blockiert.
 
S

Spacerat

Gast
OK... Back to the Roots... Dann eben Ohne "concurrent"...
Hab' hier mal, wenn auch recht dürftig, einen "MapManager" (Singleton!!!) entwickelt. Dort lassen sich "LoadEventListener" registrieren, die den Status (LoadLevel) abfragen und oder auf die Fertig geladene "Map" warten können.[highlight=java]import java.io.File;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Iterator;
import java.util.TreeMap;

public final class MapManager
{
private static volatile MapManager instance;

private java.util.Map<File, Map> maps = new TreeMap<File, Map>();
private final ArrayList<LoadEventListener> listener =
new ArrayList<LoadEventListener>();

private MapManager()
{
}

public synchronized static MapManager getInstance()
{
if(instance == null) {
instance = new MapManager();
}
return instance;
}

private void loadMapImpl(final File f)
{
final Map m = new Map();
maps.put(f, m);
new Thread(new Runnable()
{
public void run()
{
m.load(f);
Iterator<LoadEventListener> i = listener.iterator();
while(i.hasNext()) {
i.next().loadProcessFinished(new LoadEvent(m));
}
}
},"MAPLOAD").start();
}

/**
* FileChooser muss an dieser Stelle bereits
* aufgerufen worden sein
* @param f
* @return loaded Map
*/
public synchronized Map loadMap(File f)
{
if(!maps.containsKey(f)) {
loadMapImpl(f);
return null;
}
if(!maps.get(f).isReady()) return null;
return maps.get(f);
}

public void addLoadEventListener(LoadEventListener lel)
{
if(!listener.contains(lel)) listener.add(lel);
}

public void removeLoadEventListener(LoadEventListener lel)
{
listener.remove(lel);
}

public interface LoadEventListener
extends EventListener
{
void loadProcessFinished(LoadEvent e);
void loadProcessUpdated(LoadEvent e);
}

public class LoadEvent
extends EventObject
{
private static final long serialVersionUID = 1L; // supressWarning

public LoadEvent(Object source)
{
super(source);
}

public Map getMap()
{
return (Map) getSource();
}
}

public class Map
{
private float loadlevel;

Map()
{
loadlevel = 0.0f;
}

void load(File f)
{
// Hier wird die Map geladen
// der loadlevel aktualisiert und
// prozesslistener informiert.
Iterator<LoadEventListener> i = listener.iterator();
while(i.hasNext()) {
i.next().loadProcessUpdated(new LoadEvent(this));
}
}

public float loadLevel()
{
return loadlevel;
}
}
}[/highlight]In der Laderoutine sollte noch irgendwo während geladen wird ein "Thread.sleep(10)" eingefügt werden, sonst lastets den Prozessor aus (100%).
 
Zuletzt bearbeitet von einem Moderator:
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
B paintComponent Methode Spiele- und Multimedia-Programmierung 4
P Zahlenwert durch Methode ersetzen Spiele- und Multimedia-Programmierung 1
P .Wav Datei vor main-Methode abspielen? Spiele- und Multimedia-Programmierung 9
H Exeption in thread "Thread-2" NullPointerExeption: init methode? Spiele- und Multimedia-Programmierung 25
S GetBufferStrategy-Methode wird nicht angezeigt Spiele- und Multimedia-Programmierung 6
K Flackern bei repaint Methode Spiele- und Multimedia-Programmierung 3
A Zeichnen außerhalb der paint-Methode Spiele- und Multimedia-Programmierung 6
R Aufruf einer render-Methode Spiele- und Multimedia-Programmierung 12
G Methode sleepen während das Spiel weiterläuft Spiele- und Multimedia-Programmierung 3
M Beste methode zur Map Erstellen in "Block" Games Spiele- und Multimedia-Programmierung 2
J Images laden in static Methode Spiele- und Multimedia-Programmierung 8
P NullPointerException bei Aufruf von Methode Spiele- und Multimedia-Programmierung 10
G Mein erstes minigame -> problem mit Methode Spiele- und Multimedia-Programmierung 3
D Problem Mit Miensweeper Clone & rekursive Methode Spiele- und Multimedia-Programmierung 4
M Run- Methode zu überladen Spiele- und Multimedia-Programmierung 4
S Methode verändert mein Eingabe Array oO Spiele- und Multimedia-Programmierung 6
S Problem beim laden eines Bildes in einer Methode Spiele- und Multimedia-Programmierung 14
A Hilfe bei der Methode COLOR (Java) Spiele- und Multimedia-Programmierung 10
S transparenz per paint()-methode will nicht Spiele- und Multimedia-Programmierung 12
H Bilder speichern 2 - Methode richten? Spiele- und Multimedia-Programmierung 2
S Zur Laufzeit auf die Methode einer anderen Klasse zugreifen Spiele- und Multimedia-Programmierung 5
A Methode:setPointAntialiasingEnable(true) Spiele- und Multimedia-Programmierung 2
chik Wie arbeitet die polygon.contains Methode in Java Spiele- und Multimedia-Programmierung 4
D JAVA Basiertes Spiel aus dem Internet in eigenem Client laden Spiele- und Multimedia-Programmierung 1
G Minecraft PlayerBot (Listener Thread für jeden Spieler?) Spiele- und Multimedia-Programmierung 3
O Thread pausieren und wieder starten Spiele- und Multimedia-Programmierung 2
kaoZ Animation in eigenen Thread auslagern..... Spiele- und Multimedia-Programmierung 1
gamebreiti Daemon Thread Spiele- und Multimedia-Programmierung 4
M Point & Click Thread Probleme Spiele- und Multimedia-Programmierung 20
N JPanel Inhalt aktualisiert nach Thread.sleep nicht Spiele- und Multimedia-Programmierung 2
S Thread und jpanel-paintcomponent kombinierbar?? Spiele- und Multimedia-Programmierung 14
Kenan89 Alternative zu Thread Runnable Spiele- und Multimedia-Programmierung 2
O Universe <- show Thread Spiele- und Multimedia-Programmierung 14
Y Warum Thread für Spieleprogrammierung? Spiele- und Multimedia-Programmierung 27
C ***** bitte thread löschen *** Spiele- und Multimedia-Programmierung 3
A KeyListener - Thread Problem Spiele- und Multimedia-Programmierung 2
D Snake n+1-Thread Spiele- und Multimedia-Programmierung 2
B Applet startet, aber führt den Thread nicht aus Spiele- und Multimedia-Programmierung 7
S Ein Thread für alle Animationen oder mehrere? Spiele- und Multimedia-Programmierung 2
G Thread startet nicht im Vollbild modus Spiele- und Multimedia-Programmierung 3
E TetrisApplet Thread Hilfe Spiele- und Multimedia-Programmierung 6
Developer_X Thread in Java3D Spiele- und Multimedia-Programmierung 8
S Probleme mit Thread beim Streaming Spiele- und Multimedia-Programmierung 1
F Problem mit Thread.sleep() Spiele- und Multimedia-Programmierung 7
Tapsi Thread wartet auf Threads Spiele- und Multimedia-Programmierung 7
M Thread.sleep() problem Spiele- und Multimedia-Programmierung 10
0 Workaround für Thread.sleep()-Bug Spiele- und Multimedia-Programmierung 15
M Roundbased - Thread anhalten Spiele- und Multimedia-Programmierung 8
D Wasserstrahl animieren: ein Thread je Tropfen? Spiele- und Multimedia-Programmierung 7
S Thread unterbrechen Spiele- und Multimedia-Programmierung 3

Ähnliche Java Themen

Neue Themen


Oben