Querstreifen beim Bilder malen und anpassen an neue CPU

windl

Bekanntes Mitglied
Hi Leute,

folgendes Problem hat sich mir gestern aufgedrängt.
Ich habe mir eine Anwendung geschrieben, die digitale Bilder über den Monitor schiebt (ähnlich bei MediaCenter - Bilder visualisieren). Es liegen 64 Bilder in einem Block von 8 x 8 Reihen auf dem Bildschirm. Per Zufallsgenerator wird nun ein Bild ausgewählt und groß und in Farbe angezeigt. Das alles habe ich mit Transformationen realisiert und hat auch auf dem "alten" Rechner sehr gut funktioniert und gut ausgesehen. Leider hat mich nun das Mainboard im Stich gelassen und ich musste Mainboard / CPU usw austauschen.
Die Anwendung selber funktioniert noch - nur rennen jetzt die Bilder über den Screen und plötzlich habe ich leichte Querstreifen beim Zeichnen der Bilder auf Fernseher.

Gibt es eine Möglichkeit, die Rechengeschwindigkeit für das Malen von Bildern herauszubekommen um über das Verhalten evtl mit SLEEP-Funktionen zu reduziern?

Gibt es eine andere Möglichkeit an die ich nicht gedacht habe. Ach ja, ich Puffere das Graphics in einem BufferedImage zwischen und male dann auf einmal.

Danke Uwe
 
Hi,
hier die paint-Methode.
Ich verstehe nicht, warum er hakt.
Interessant wäre auch zu wissen, wie ich die Scrollgeschwindigkeit auf verschiedenen CPU's gleich halten kann..

Java:
	public void drawComponent(Graphics2D g2d){
		
		/*Alten Z-Wert speichern um nur bei Veränderung aktiv zu werden*/
		double oldMoveZ = moveZ;
		double oldMoveX = moveX;
		double oldMoveY = moveY;
		
		
		/*Die Größe und Höhe wird immer neu gezogen um bei einer Veränderung das Bild zentrieren zu können*/
		width  = MediaGateStatics.mediaGate.getWidth();//getWidth();
		height = MediaGateStatics.mediaGate.getHeight();//getHeight();
		
		
		g2d.drawImage(MediaGateStatics.skinLoader.getImageIcon("background").getImage(), 0, 0,MediaGateStatics.mediaGate.getWidth(),MediaGateStatics.mediaGate.getHeight(), null);
		
		if(DEBUG){
		g2d.setColor(Color.black);
		g2d.drawLine(MediaGateStatics.mediaGate.getWidth()/2, 0, MediaGateStatics.mediaGate.getWidth()/2, MediaGateStatics.mediaGate.getHeight());
		g2d.drawLine(0, MediaGateStatics.mediaGate.getHeight()/2, MediaGateStatics.mediaGate.getWidth(), MediaGateStatics.mediaGate.getHeight()/2);
		}
		
		/*Event auslesen*/
		if(eventList.size() > 0 || currentEvent != null){
			/*Event vorhanden*/
			if(currentEvent == null){
				currentEvent = eventList.get(0);
			}
			
			/*abfragen um welches Event es sich handelt*/
			if(currentEvent.eventType == PictureEvent.MOVEEVENT){
				/*MoveEvent*/
				moveX = moveX + currentEvent.stepX;
				moveY = moveY + currentEvent.stepY;
				currentEvent.mustMove = currentEvent.mustMove - moveStep;
				
				if(currentEvent.mustMove<=0){
					if(DEBUG){System.out.println("MoveEvent - Ziel erreicht - Event abschalten");}
					refreshEvent();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.FADEINEVENT){
				/*Fadein-Event*/
				if(moveZ < FADESIZE){
					moveZ = moveZ + 0.02;
				} else {
					/*Ende erreicht*/
					refreshEvent();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.FADEOUTEVENT){
				/*Fadeout-Event*/
				if(moveZ >1.0d){
					moveZ = moveZ - 0.02;
				} else{
					/*Ende erreicht*/
					
					//Die großen Bilder werden so lange im Speicher gehalten, wie sie benötigt werden!
					//Wenn die Bilder nun alle wieder "klein" sind, dann kann ich diese aus dem
					//Speicher nehmen und wieder durch die kleinen Bilder ersetzen.
					for(int i = 0;i<seitenLängeRow;i++){
						for(int o = 0;o<seitenLängeCol;o++){
							mcePicture[i][o].deleteColorPicture();
						}
					}
					System.gc();
					refreshEvent();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.TIMEREVENT){
				/* TimerEvent starten */
				if(!waitTimer.isRunning()){
					if(DEBUG){System.out.println("Waittimer wird gestartet");}
					waitTimer.restart();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.COLOREVENT){
				/*Nun wird das Bild farbig gemacht*/
				for(int i = 0;i<seitenLängeRow;i++){
					for(int o = 0;o<seitenLängeCol;o++){
						mcePicture[i][o].addDarkTriangular();
					}
				}
				if(!currentEvent.picture.stepNextColor()){
					refreshEvent();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.UNCOLOREVENT){
				/*Nun wird das Bild grau gemacht*/
				for(int i = 0;i<seitenLängeRow;i++){
					for(int o = 0;o<seitenLängeCol;o++){
						mcePicture[i][o].removeDarkTriangular();
					}
				}
				if(!currentEvent.picture.stepPreviousColor()){
					refreshEvent();
				}
			}
			
			if(currentEvent.eventType == PictureEvent.RELOADEVENT){
				/*Reload-Event*/
				if(moveZ >1.0d){
					moveZ = moveZ - 0.02;
				} else{
					/*Ende erreicht*/
					refreshEvent();
					reloadPictures();
					return;
				}
			}
			
		}
		
		/*Ermmittelt den absoluten X Wert in Abhängigkeit des Scalefaktors*/
		double x = (getWidth()/ 2)-(((getWidth() /2)-moveX) * moveZ);
		/*Ermmittelt den absoluten Y Wert in Abhängigkeit des Scalefaktors*/
		double y = (/*getHeight()*/768/2)-(((/*getHeight()*/768/2)-moveY) * moveZ);
		
	    if(DEBUG){
	    System.out.println("Width=" + getWidth()  + " moveX=" + moveX +  "  x=" + x + "  moveZ="+moveZ );
	    System.out.println("------------------------------------------------------");
		System.out.println(oldMoveZ + " - " + moveZ);
		System.out.println(oldMoveX + " - " + moveX);
		System.out.println(oldMoveY + " - " + moveY);
		System.out.println("------------------------------------------------------");
	    }
	    
        /*MainTransformation auf Initialwert zurück setzen..*/
	    mainTransformation.setToIdentity();
	    /*X und Y Wert neu transformieren*/
	    mainTransformation.translate(x,y);
	    /*Die ScaleTransformation muss nur verändert werden, wenn sie sich auch wirklich verändert hat*/
	    if(moveZ >1.0){
		    if(oldMoveZ != moveZ){
				/*Scalefaktor einbeziehen*/
		    	scaleTransformation.setToIdentity();
			    scaleTransformation.scale(moveZ, moveZ);
		    }
		    /*Beide Transformationen verschmelzen*/
	    	mainTransformation.concatenate(scaleTransformation);
	    }
	    
	    if(currentEvent == null){
	    	g2d.setColor(Color.white);
	    	g2d.setFont(g2d.getFont().deriveFont(Font.BOLD, 30));
	    	String ausgabe = "Bilder werden geladen...";
	    	Point p = ExtendedSwingUtilities.centerText(g2d, ausgabe, getWidth(), getHeight());
	    	g2d.drawString(ausgabe, p.x, p.y);
	    }
		
		if(currentEvent != null){
			
			if(currentEvent.eventType == PictureEvent.BUBBLELING){
				//Die aufbubbelnden Bilder vergrößern
				resizeBubblePictures();
				//Abfragen ob alle Bilder fertig aufgebaut sind
				if(allPicturesBubbled()){
					refreshEvent();
					setBubblePicturesToNormalSize();
				} else {
					//weitere Bilder nachladen
					bubblePictures();
				}
			}
			
			/*Transformation ans Grafik-Objekt hängen*/
			g2d.setTransform(mainTransformation);
			
			/*Alle Childkomponenten malen (Bilder)*/
			this.paintChildren(g2d);
			
			if(currentEvent.eventType == PictureEvent.UNREGISTERED){
				currentEvent = null;
				Runnable pRun = new Runnable(){
					public void run(){
						findNextPicture(true);
					}
				};
				Thread pThread = new Thread(pRun);
				pThread.setPriority(Thread.MIN_PRIORITY);
				pThread.run();
			}
			SwingUtilities.invokeLater(new Runnable(){
				public void run(){
					Thread.yield();
					MediaGateStatics.mediaGate.repaint();
					Thread.yield();
				}
			});
		}
	}
 
hmm, daraus kann ich leider keinen Fehler herleiten, zumal ich nicht weiss, was in der paintChildren(Graphichs2D) drinn steht.

Ich pers. zeichne per piantComponent(); auf JPanel und dort kann man mit drawImage(MeinBufferedImage, ......); sehr einfach arbeiten.
Dann benötigst du nur einen Thread, der dein BufferedImage in einem festgelegten Zeitintervall neu berechnet und die Geschwindigkeit sollte CPU unabhängig stimmen.

Die drawComponent(),; scheint mit dem LaF zusammen zu hängen. Da bin ich leider nicht so erfahren.
Wird sich aber bestimmt jemand hier finden, der noch eine Idee hat.

Sry, und Gruß
Vanny
 
Wohl kaum - der Code ist schwer nachvollziehbar. Was zum (!?) wird da gemacht? Das sieht aus, als ob du eine eigene Eventverarbeitung gebastelt hast, die IN (!) der paint- bzw. drawComponent-Methode abläuft... dort wird tatsächlich während des Zeichnens ein Thread gestartet???
 
Es handelt sich hierbei nicht um einen eigenen Eventhandler! Die Klasse hält lediglich die Zustände um zu wissen, wie was im Augenblick gemalt werden soll. Der Thread war in der paint-Methode in der Tat blöd. Den habe ich nun entfernt - totzdem wurde es nicht besser.

Das Problem, dass aufgrund der CPU-Geschwindigkeit Querstreifen bzw. ein leichter Versatz bleibt ist nachwievor die Frage.
 
Es ist grundaätzlich nicht schön, in einer paint...-Methode mehr zu tun, als zu zeichnen.
Irgendwo in diesem Kino liegt wohl auch der Fehler bei dir.
 
Das sind zu wenige Infos, um wirklich was hilfreiches sagen zu können. Das Problem ist: Bei einem KSKB wären es wahrscheinlich "zu viele" Infos, also zu viel Code - schon jetzt weiß man ja nicht, was dort von "MediaGateStatics.mediaGate" bis "refreshEvent" so alles gemacht wird...
 
Das ist richtig, der Code ist complex.
Was ich nur nicht verstehe, ist die Tatsache, dass es auf dem "alten Board" mit der "alten CPU" super lief.
Erst nach dem Einbau eines Gigabyte Boards mit Quard CPU habe ich diesen Quereffekt.
Die Querstreifen, die sich abzeichnen, kommen definitiv nicht vom code. Wenn ich einen Thread.sleep einbaue, sind diese Streifen z.B. weg.
 
ohne mich auf dein projekt direkt zu beziehen : hast du ähnliche phänomene auch in anderen anwendungen ? das klingt nämlich nach hardware-fehlern ... würde hier sogar mal weg vom board zur grafikkarte gehen ... könnte nämlich sein das wenn du deine alte karte weiterhin nutzt diese noch schäden davon getragen hat und nun das neue system ebenfalls bedroht ...

[ot]kenne mich in punkto hardware nicht ganz so super genau aus ... dafür aber in software ... um sagen zu können das die auftretenen fehler nicht vom code stammen sollten ...
ich würde daher mal versuchen das programm auf einem komplett anderen rechner zu testen welcher keine komponenten deines alten oder neuen systems beinhaltet ...
zum übertragen würde ich persönlich netzwerk vor usb-stick vorziehen ... ist aber nicht immer umsetzbar[/ot]
 
Das kann 1000 Gründe haben. Schon allein weil auf der alten CPU vielleicht nur ein Code war, und jetzt vier, und es deswegen zu Concurrency-Problemen kommt...
 
Was ich bis jetzt sagen kann, es muss wohl scheinbar etwas mit der CPU zu tun haben?! Habe es jetzt wieder auf einem Dual-Core-Prozessor aufgespielt und es schnurrt wie ein Kätzchen.
Jetzt bleibt die Frage - wie kann man Code oder Animationen so bauen, dass man genau das Problem mit den verschiedenen Core's nicht hat?!

Danke für die zahlreichen Antworten bis jetzt!
 
Hallo - ich denke ich habe den Fehler gefunden!
Das Problem, welches ich jetzt übersehen habe ist das einhänglen des Paint-AWT-Events in die Cue.
Aufgrund dass mein neuer Rechner so schnell ist, wurden mehr Rechenoperationen durchgeführt als die Repaint-Methode in der Lage war auszuführen. Daher wurden immer wieder vereinzelt mehrere Repaint-Events hintereinander verworfen. Daher kam es am Ende zu diesem schrecklichen Versatz und ruckeln der Bilder.
Hier hat mir das Stichwort passive-painting und active-painting sehr geholfen.
Siehe Thread http://www.java-forum.org/spiele-multimedia-programmierung/134167-2d-spiel-vollbild-langsamer-fenster.html

Ich denke - das war es. Es läuft jetzt auch auf dem neuen Rechner flüssig aber schnell ;o)
Danke für die zahlreichen Informationen die mich letzten Endes auf den richtigen Weg gebracht haben.

cu
Uwe
 

Zurück
Oben