# Methode die (Graphics g)  benötigt von Thread ausführen lass



## Joetempes (14. Apr 2005)

Folgendes Problem hab ich, wo ich nicht weiter komm:

Ich hab ein Programm wo auf einem JPanel etwas gezeichnet wird.
Das funktioniert auch (public void paintComponent(Graphics g){...}.

Teile davon hab ich in extra Methoden ausgelagert, welche dann immer das Graphics g übergeben bekommen.
Das funktioniert auch (public void drawLeitung(Graphics g){...}

Nun will ich aber das eine dieser ausgelagerten Methoden (die ein Graphics g als Parameter benötigen)von einem extra Thread ausgeführt werden, weil diese in einer Endloschleife laufen soll bis zum Abbruch...

Also initialisiere ich den Thread, starte ihn, der Thread ruft seine run()-Methode auf, und da beginnt mein Problem:

Ich hab ja in der run()-Methode kein Zugriff auf mein Graphic g aus der painComponent()-Methode um zum Beispiel die Methode: public void drawLeitung(Graphics g){...} aufzurufen, da ich die run()-Methode ja nicht überschreiben kann mit einem Parameter.

???
Hab ich ein Denkfehler ? 
Kann man das Graphics g global initialisieren ?
Ist das überhaupt lösbar, jemand ne Idee ?


Vorab vielen Dank!

Joetempes


----------



## Wildcard (14. Apr 2005)

Du hast die paintComponent in mehrere Methoden aufgeteilt (was ich übrigens nicht machen würde)
und willst jetzt das ein Teil davon in einem anderern Thread ausgeführt wird???????
Vergiss es!
Ich glaub du machst einen großen Denkfehler! 
Erklär lieber mal wie das Endergebniss aussehen soll(das hab ich nämlich nicht ganz verstanden), dann finden
wir eine vernünftige Lösung  :wink:


----------



## Roar (14. Apr 2005)

äh warum nich einfach repaint() aufrufen?


----------



## Joetempes (14. Apr 2005)

Ja ich habe wie gesagt Teile ausgelagert, in extra Methoden, diese werden dann aus paintComponent() herraus aufgerufen. Ganz normal denk ich.  So brauch ich zeug davon nicht doppelt schreiben, wenn ich die gleiche Sache zeichnen lassen will, aber nur die Farbe anders sein soll. Dann übergeb ich der Methode einfach noch die entsprechende Farbe mit... Aber das ist nicht das Problem.
Und ein Teil würde ich gern extra von einem Thread ausführen lassen.
Das Ergebniss soll sein, das ein Teil permanent in einer endlosschleife ge- repaint()tet wird und der Rest 
ganz normal läuft.

CodeSchnipsel:


```
public void paintComponent(Graphics g){
		
		super.paintComponent(g);
		
		drawLeitungsRamenWeiss(g); //ausgelagert 

		if(strom == false){
		
		    drawLeiterInsAquarium(g,Color.RED); // ausgelagert
		    
		    stromThread = new Thread(this);
		    stromThread.start();    // ruft run() auf

		 }
} //paintC. zu

public void run(){

	    drawStromSchlag(g); // funktioniert so nicht
	}
```

Und das funktioniert so natürlich nicht, weil run() nicht auf 'g' zu greifen kann.

Hoffe mein Problem wird jetzt etwas deutlicher.

Meinst Du echt das geht gar nicht ???


----------



## Joetempes (14. Apr 2005)

@Roar

Weil mit repaint() wieder die ganze paintComponent()-Methode ausgeführt wird !


----------



## Wildcard (14. Apr 2005)

Joetempes hat gesagt.:
			
		

> @Roar
> 
> Weil mit repaint() wieder die ganze paintComponent()-Methode ausgeführt wird !


Und was passt dir daran nicht?
Ich bin gegen das auslagern aus paint-Methoden weil sie sehr oft aufgerufen werden, und deshalb so
minimalistisch wie irgend möglich sein sollten.
Ausserdem einen anderen Thread nicht IN der paintComponent aufrufen  :roll: 


> stromThread = new Thread(this);
> stromThread.start();    // ruft run() auf


Ist etwa die Klasse in der du zeichnest selbst das Runnable???


----------



## Kian (14. Apr 2005)

```
public void run(){

       drawStromSchlag(g);

   }
```

Von wo kommt das 'g' her, hast du eine Graphics-Var(g) extern deklariert?


----------



## Joetempes (14. Apr 2005)

@WildCard
1. Also den Thread muss ich nicht in der paintComponent()-Methode erstellen, das würde auch woanders gehen.
2. Ja.Die Klasse die ich zeichne implementerit das Runnable-Interface!
3. Ich will nicht repaint machen, weill ich nur einen ganz bestimmten Abschnitt repainten will.

Also ich meine, es kann jeder alles finden was er möchte und jeder hat seine Vorlieben aus Erfahrung und anderen Gründen herraus.
Aber das ist nicht meine Frage !

Es funtieniert ja alles, bis an die Stelle wo ich mein Problem beschreibe, Ihr habt ja mein Problem verstanden denk ich, meine Frage ist ob es möglich ist es  zu lösen oder zu umgehen ???


----------



## Joetempes (14. Apr 2005)

@KIAN

Genau das ist ja das Problem !!!
Das geht so nicht, weil ich das 'g' ja von nirgens her bekomme, da ich ja run() nicht überschreiben darf um es als Parameter mit zu geben !

Kann man eine Graphics g - Variable global definieren ?
Oder:
Hat man AWT vieleicht extra so konstruiert, das man das nicht machen darf was ich will ???


----------



## Wildcard (14. Apr 2005)

Wenn du nur einen ganz bestimmten Abschnitt zeichnen willst, dann benutz dafür JComponents...
Erstell eine Klasse die Runnable implementiert, der gibst du eine Referenz auf die Component mit.
In der run methode dieser Klasse rufst du dann auf der Component repaint auf...


----------



## Joetempes (14. Apr 2005)

@Wildcard

Hast Du es ein bischen genauer, das wäre nett ?!


----------



## Roar (14. Apr 2005)

Joetempes hat gesagt.:
			
		

> @Roar
> 
> Weil mit repaint() wieder die ganze paintComponent()-Methode ausgeführt wird !


jo ich dacht das soll so, wenn nicht setz doch einfach flags in der klasse oder so...


----------



## Wildcard (14. Apr 2005)

```
class Foobar extends Thread
{
    private MyFooBarComponent component;

    public Foobar(MyFooBarComponent component)
    {
        this.component=component;
    }
    run() 
    {
        while(true)
        {
            component.repaint();
        }
    }

}
```


----------



## Kian (15. Apr 2005)

Joetempes hat gesagt.:
			
		

> @KIAN
> 
> Genau das ist ja das Problem !!!
> Das geht so nicht, weil ich das 'g' ja von nirgens her bekomme, da ich ja run() nicht überschreiben darf um es als Parameter mit zu geben !
> ...



Bin mir nicht sicher ob das klappt, theorethisch eigentlich schon:


```
Graphics d = null;

public void paintComponent(Graphics g){
      
      super.paintComponent(g);
      
      drawLeitungsRamenWeiss(g); //ausgelagert

      if(strom == false){
      
          drawLeiterInsAquarium(g,Color.RED); // ausgelagert

          d = g;
         
          stromThread = new Thread(this);
          stromThread.start();    // ruft run() auf

       }
} //paintC. zu

public void run(){

       drawStromSchlag(d); // funktioniert so vielleicht
   }
```

Damit das klappt muss paintCom...(...) die run() starten, was vermutlich bei dir der fFall ist.


----------



## Wildcard (15. Apr 2005)

argh!  :autsch:


----------



## Guest (16. Apr 2005)

entweder habe ich etwas nicht verstanden, oder du übergibst das Graphics g eifach dem Konstruktor vom Thread...

```
stromThread = new Thread(this,g); //<- dann hast du's im Thread zur verfügung...
```


----------



## Beni (16. Apr 2005)

@gast Du hast was nicht verstanden :wink:

1. Kannst du dem Konstruktor von Thread nicht einfach was zusätzliches übergeben, da musst du sonstwo eine Variable machen.

2. Ist das Speichern von "Graphics" keine gute Idee: nach einer gewissen Zeit (nur ein paar Sekunden oder Millisekunden) verliert ein Graphics seine Eigenschaft, den Bildschirm zu beeinflussen.

Das beste ist und bleibt in einer Methode, welche von "paint( Graphics g)" aufgerufen wird, zu zeichnen.
Du kannst mit repaint( x, y, w, h) dafür sorgen, dass nur ein Teil der Oberfläche wirklich neu gezeichnet wird.


----------



## Guest (18. Apr 2005)

Also an ALLE erstmal ein fettes Dankeschön für Eure Hilfe !

Ich hab jetzt folgendes gemacht: 
Hab eigene Klasse geschrieben die von Thread erbt, und da den Konstruktor so gebaut das sie das Graphics g über- geben bekommt:

```
import java.awt.Graphics;

public class MyStromThread extends Thread {

    private Graphics g;
    private ActionPanel al;
    
    public MyStromThread(Graphics g,ActionPanel al) {
        
        this.g  = g;
        this.al = al;
    }
    
    public void run(){
        al.drawStromSchlag(g);
    }
}
```
Und in meiner ActionPanel-Klasse, wo die paintComponent- Methode() drin steckt wird dieser Thread instanziert:

```
public void paintComponent(Graphics g){
     
      super.paintComponent(g);
     
      drawLeitungsRamenWeiss(g); //ausgelagert

      if(strom == false){
     
          drawLeiterInsAquarium(g,Color.RED); // ausgelagert

          d = g;
         
          stromThread = new Thread(this);
          stromThread.start();    // ruft run() auf (extra Thread)

       }
} //paintC. zu
```

Die Methode drawStromSchlag(g) sieht so aus:

```
public void drawStromSchlag(Graphics g){
	        
	    while(strom == true){
	        
	        System.out.println("Test");

		    g.setColor(Color.BLACK);
		    g.drawLine(255,155,280,120);
		    g.drawLine(280,120,283,180);
		    g.drawLine(283,180,286,130);
                     repaint();
                    g.setColor(Color.RED);
		    g.drawLine(255,155,280,120);
		    g.drawLine(280,120,283,180);
		    g.drawLine(283,180,286,130);
                     repaint()
		  
           }
}
```

Ihr werdets nicht glauben, technisch siehts wunderbar aus, der "Test" -Ausdruck auf der Konsole funtioniert auch
bestens --> EXTRA THREAD ! Aber er macht kein repaint() und zeichnet diese Linien damit nicht.
Langsam glaub ich Wildcard hat von Anfang an Recht gehabt, das funtioniert einfach nicht!

[/quote]


----------



## Joetempes (18. Apr 2005)

Sorry, das hat kein GAST geschrieben sondern ich --> Joetempes!
Man muss sich ja einloggen, hab nicht beachtet, das man als Gast Beiträge schreiben kann.

Und der Thread wird natürlich so aufgerufen:


```
stromThread = new MyStromThread(g,this);
stromThread.start();
```


----------



## Wildcard (18. Apr 2005)

Joetempes hat gesagt.:
			
		

> Langsam glaub ich Wildcard hat von Anfang an Recht gehabt, das funtioniert einfach nicht!


Es funktioniert schon, du machst es nur nicht richtig. Grundsätzlich nicht aus nebenläufigen Threads zeichnen sondern
nur repaint verwenden. Punkt.


----------



## Bleiglanz (19. Apr 2005)

AWT und SWING sind singlethreaded, du darft auf die Komponenten NUR vom Event-Despatching-Thread zugreifen...

lies mal nach, Threads und Swing sind eine etwas komplizierte Materie (ggf. mal invokeAndWait und invokeLater anschauen)


----------



## Joetempes (19. Apr 2005)

@Wildcard
Mit dem repaint() funktioniert das nicht so einfach!

Hab das mal nach gegoogelt was Bleiglanz schrieb, zum Thema Event-Dispatching Thread gibts ne ganze Menge!
Und es sieht so aus, als wenn da der Haken drin steckt !!!

Hab hier ne Anleitung gefunden:
http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html

...muss ich erstmal durch arbeiten...

Danke noch mal an Euch !!!! :toll:


----------



## Joetempes (19. Apr 2005)

Die paintComponent()- Methode von mehreren Threads ausführen zu lassen, da heißt das mindestens 2 Thread auf ein Graphics g - Object zugreifen, und diese nebenläufig von einander etwas repainten funktioniert nicht.

Ich gebs auf.

Bis zum nächsten mal... :meld:  :autsch:  :applaus:  :lol:


----------



## Wildcard (19. Apr 2005)

Joetempes hat gesagt.:
			
		

> Die paintComponent()- Methode von mehreren Threads ausführen zu lassen, da heißt das mindestens 2 Thread auf ein Graphics g - Object zugreifen, und diese nebenläufig von einander etwas repainten funktioniert nicht.
> 
> Ich gebs auf.


Wie oft denn noch? REPAINT benutzen  :roll:


----------

