Threads Timer wird unterbrochen

GreenIguana

Mitglied
Hallo Leute,
ich habe einen java.swing.Timer in ein Programm eingebaut. Dieser wird, auf sieben Millisekunden eingestellt,
bevor er alle Programmschritte abgearbeitet hat, unterbrochen, er soll jedoch durchlaufen.
Wird die Klasse Timer auch vom Thread-Scheduler geregelt (sonst sind nur noch main- und Swing-Threads laufen) oder wie läuft das ab?
Hoffe das klingt verständlich... *überflieg*... oder auch nicht 😀.

Schonmal danke im Voraus!
Grüße,
Grüner... Leguan? :bahnhof:
 
@XHelp Wenn Du 2000 Zeilen Code haben willst, dann bitte, aber ich glaube, dass Dir das nicht hilft.
So viel: Es werden jeden Frame ca. 20 ~0,5Mb große Images auf ein JPanel gezeichnet.
 
Also hier ein paar:
Java:
timer = new Timer(7, this);
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

public void actionPerformed(ActionEvent e) {*Die besagten Zeilen mit Aufrufen*}
 
Naja, da sollte nichts unterbrochen werden, deswegen ist der Fehler irgendwo in deinem Code.
Ich glaube doch, da wie folgt:
Der Durchlauf wird unterbrochen, weil manchmal nur der zuerst gezeichnete und alles überdeckende Hintergrund zu sehen ist. Manchmal zusätzlich auch das zweitgezeichnete Bild usw. Also sind auch die zeitlichen Abstände immer unterschiedlich, werden aber mit zunehmender Programmlaufzeit immer kürzer (anfänglich läuft es so gut wie einwandfrei).
 
Ich verstehe nichts:bahnhof:

Aber es hört sich für mich so an, als ob da von mehreren Threads versucht wird eine GUI zu modifizieren. Dieses geht in Swing nicht und Änderungen an der GUI dürfen nur vom Event-Dispatch-Thread (EDT) gemacht werden.

Ich sehe auch nicht, wodurch der Timer unterbrochen werden sollte. Weiterhin verstehe ich nicht, wofür Du meinst einen Timer einzusetzen,der durchlaufen soll. Ist das nicht Aufgabe des Hauptprogramms?

Alles zusammen:
Wir benötigen eindeutig mehr Infos, damit wir Dir weiterhelfen können😉
 
Dieses geht in Swing nicht und Änderungen an der GUI dürfen nur vom Event-Dispatch-Thread (EDT) gemacht werden.
Doch, das geht! Wenn man z.B. (in einem sehr kleinen Programm) in der vom "main-thread" aufgerufenen
Code:
main(String[])
-methode einer sub-Klasse von JPanel
Code:
repaint();
aufruft, und die Methode
Code:
paint(Graphics)
oder
Code:
paintComponent(Graphics)
in etwa so
Java:
public void paint(Graphics g) {
		
		g2D = (Graphics2D) g;
		
                /** Anderes Gebimsel mit dem Graphics2D-Object */
	}
überschreibt, passieren die Änderungen bestimmt auch im Thread "main", wenn aber der durch den aufruf von
Code:
repaint()
etwas im Event-Dispatching-Thread in Gang gesetzt wird, ist das auch ok und ändert nichts daran, dass die Vorgehensweise beim Zeichnen korrekt ist, und auch in zahlreichen Lehrbüchern vertreten ist.
Wenn ich Dich oder etwas im Swing-Komplex falsch verstanden habe, tut es mir Leid. Lass es mich wissen.
Gruß,
Grüner... Leguan:bahnhof:
 
passieren die Änderungen bestimmt auch im Thread "main"
Öhm, nö?
Java:
public class Test {
	public static void main(String[] args) {
		JFrame frame = new JFrame(){
			@Override
			public void paint(Graphics g) {
				super.paintComponents(g);
				System.out.println(">>>>>paintComponent called");
				StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
				for (StackTraceElement e: stackTrace) {
					System.out.println(e);
				}
			}
		};
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(300, 300);
		frame.setVisible(true);
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("<<<<<REPAINT FROM MAIN");
		frame.repaint();
	}
}

Aber generell verstehe ich nicht, worum es hier geht. Mittlerweile 2 Leute sagen dir, dass der Fehler höchstwahrscheinlich irgendwo in deinem Code ist. Du behauptest hingegen, dass das nicht der Fall ist... es läuft zwar nichts, du weißt nicht warum es so ist oder wo der Fehler ist, aber in deinem Code ist es mit Sicherheit nicht :bahnhof:
Alleine schon die Tatsache, dass da irgendwas alle 7ms (142 mal pro Sekunde) gezeichnet werden soll erscheint mir schon äußerst suspekt. Und die Aussage "Durch den Timer läuft tatsächlich das gesamte Programm" lässt mich auch irgendwie an der Unfehlbarkeit des Codes zweifeln.
 
Ist es möglich die ganze actionPerformed-Methode zu sehen?
Es wird euch nicht viel helfen, weil insgesamt 34 verschiedene Klassen á 350 Zeilen aufgerufen werden, aber bitte. (Alle Kommentare habe ich rausgenommen und den Code um für hier wichtige Kommentare ergänzt).
Java:
public void actionPerformed(ActionEvent e) {
		
		paint();
		
		int delta = getDelta();
		samShots = player.shots;

		for (int i = 0; i < enemies.size(); i++) {
			for (int y = 0; y < enemies.get(i).getShots().size(); y++)
				enemyShots.add(enemies.get(i).getShots().get(y));

		}

		for (int i = 0; i < doors.size(); i++)
			doors.get(i).animate();

		for (int i = 0; i < enemies.size(); i++) {

			enemies.get(i).animate();

			if (!enemies.get(i).getIsLiving()) {

				items.add(new ItemHeart(enemies.get(i).getX(), enemies.get(i).getY()));
				enemies.remove(i);

			}
		}

		if (enemies.size() == 0) {
			for (int i = 0; i < doors.size(); i++) {

				if (Room.rooms[doors.get(i).getDestination()].getEnemies().size() == 0)
					doors.get(i).isClean();

			}
		}

		if (yOffsetSource == 1080 & yOffset < 1080) {
			yOffset += xOffsetSpeed;
		}

		if (yOffsetSource == -1080 & yOffset > -1080) {
			yOffset -= xOffsetSpeed;
		}
		if (xOffsetSource == 1920 & xOffset < 1920) {
			xOffset += yOffsetSpeed;
		}
		if (xOffsetSource == -1920 & xOffset > -1920) {
			xOffset -= yOffsetSpeed;
		}

		if (yOffsetSource == 1080 & yOffset >= 1080 | yOffsetSource == -1080 & yOffset <= -1080) {
			yOffset = yOffsetSource = 0;
			changeMainRoomToSecondary();
		}
		if (xOffsetSource == 1920 & xOffset >= 1920 | xOffsetSource == -1920 & xOffset <= -1920) {
			xOffset = xOffsetSource = 0;
			changeMainRoomToSecondary();
		}

		callManager(delta);  // Hier wird ein Großteil des Programms aufgerufen
		paint(); // Hier wird ein Buffer, der mit der für das Rendern zuständigen Klasse verknüpft ist, aufgefrischt

	}
 
Mach mal an den Anfang der Methode ein Sysout "Ich wurde aufgerufen..." und ans Ende "Und jetzt bin ich fertig..."
Dann müssten beide Ausgaben in der Konsole erscheinen.
 
Glaskugel sagt: Problem liegt an Code...
Ich denke mal, dass sie (die Glaskugel) damit meint, dass dort irgendwo Fehler und RuntimeExceptions z.B. durch catch Throwable abgefangen werden könnten, die unter anderem auch "OutOfMemory"-Errors verschlucken. 2000 Zeilen Code mit Bildmanipulation für 7ms sind schon beachtlich.
 
Diese Vermutung wie Spacerat habe ich auch. Ich vermute in den Untiefen des Programms eine Exception. die Du nicht zu sehen bekommst.

Wrappe mal Deine gesamte actionPerformed-Methode in einen try-catch Block und prüfe ob da eine Exception geworfen wird. Meine Vermutung ja und glaube an eine ConcurrentModificationException.

Java:
	public void actionPerformed(ActionEvent ae) {
		try {
			// Deine bisherigen Aufrufe hier
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
Ich vermute mal, dass das Problem hier mit
Code:
repaint()
zusammenhängt. Denn diese Methode zeichnet nicht sofort alles neu, sondern setzt lediglich den Hinweis/Wunsch des Neuzeichenens. Somit stimmt wohl auch folgendes vermutlich nicht:
Und ca. 140 Fps habe ich auch 😛ueh: 😀

Die Fps ermittelst du, wenn du die paint()-Methode der ContentPane des Haupt-JFrames überschreibst, oder das obersten JPanels, in welchem deine Zeichenvorgänge ablaufen, und vor den super.paint()-Aufruf die Zeit misst und danach. Auf jeden Fall nicht, wenn du die Zeit vor und nach dem repaint()-Aufruf oder in dem Thread (-> hier Timer) misst.

[JAPI]http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#repaint%28%29[/JAPI]
Painting in AWT and Swing
 
Wrappe mal Deine gesamte actionPerformed-Methode in einen try-catch Block und prüfe ob da eine Exception geworfen wird. Meine Vermutung ja und glaube an eine ConcurrentModificationException.

Java:
	public void actionPerformed(ActionEvent ae) {
		try {
			// Deine bisherigen Aufrufe hier
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
Wenn meine Vermutung stimmt und irgendwo bereits ein [c]catch(Throwable t)[/c] eingefügt wurde, hat TO davon auch nicht mehr viel.
Aber GUI-Programmers Vermutung kann natürlich ebenso zutreffen. Wenn man innerhalb eines EDT-Durchlaufs 140 mal [c]repaint()[/c] aufruft, rendert man ebensoviele Frames in den Hades. Das ist so effizient, als würde man ein Backup-Device nach [c]/dev/null[/c] mounten.
 
Ich vermute mal, dass das Problem hier mit
Code:
repaint()
zusammenhängt. Denn diese Methode zeichnet nicht sofort alles neu, sondern setzt lediglich den Hinweis/Wunsch des Neuzeichenens. Somit stimmt wohl auch folgendes vermutlich nicht:

Die Fps ermittelst du, wenn du die paint()-Methode der ContentPane des Haupt-JFrames überschreibst, oder das obersten JPanels, in welchem deine Zeichenvorgänge ablaufen, und vor den super.paint()-Aufruf die Zeit misst und danach. Auf jeden Fall nicht, wenn du die Zeit vor und nach dem repaint()-Aufruf oder in dem Thread (-> hier Timer) misst.

[JAPI]http://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#repaint%28%29[/JAPI]
Painting in AWT and Swing

Endlich einmal etwas hilfreiches:toll:. Aber mein Problem ist immer noch nicht gelöst. Ich werde das versuchen anders zu gestalten. 😉 Mal schauen...
 

Zurück
Oben