repaint() in run-Methode funktioniert nicht

MK234

Aktives Mitglied
Hallo,

ich habe zwei Klassen eine enthält eine paintComponent-Methode und die andere
einen Thread, in dessen run-Methode die paintComponent-Methode der anderen Klasse
durch repaint() aufgerufen werden soll. Leider funktioniert dies nicht.
Ich kann in der run-Methode sehrwohl andere Methoden der anderen Klasse aufrufen, aber paintComponent nicht.

Code-Fragment der Thread-Klasse
Java:
   public void run() {    
        while(!isInterrupted()) {          
            boolean angekommen = true; l                 
            try {               
                zeichenfl.repaint();                   
                Thread.sleep(300);  
                for(int i=0; i < zeichenfl.index_zu_Stelle.size(); i++) {
                    //wenn Marke noch nicht an Zielstelle angekommen
                    if(!zeichenfl.stellePressed(zeichenfl.markenX.get(i), 
                            zeichenfl.markenY.get(i), 
                            model.Stellen_Liste.get(zeichenfl.index_zu_Stelle.get(i)))) {
                       
                        angekommen = false;


Code-Fragmente der Klasse mit paintComponent und in welcher der obige Thread erzeugt wird:

Java:
 public void paintComponent (Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        setPreferredSize(new Dimension(panelWidth, panelHeight));        
        
        //Linienstärke und Unschärfe einstellen
        Stroke s = new BasicStroke((3*model.groesseWidth)/40);
        g2.setStroke(s);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                                RenderingHints.VALUE_ANTIALIAS_ON);





Java:
public void mousePressed(MouseEvent e) {           
         x = e.getX();
         y = e.getY();         
         
         //wenn aktivierte Transition geschaltet wurde
         if(e.isMetaDown() && !model.getLoeschKenn() && !model.getVerschKenn() &&
                         !model.getMehrVerschieben()) {                  
                 
                 //prüfen ob mit rechter Maustaste auf eine Transition geklickt wurde
                 for(int i=0; i < model.Trans_Liste.size(); i++) { 
                         if(!model.Trans_Liste.get(i).geloescht && transitionPressed(x, y, model.Trans_Liste.get(i))) {
                                 
                                 //prüfen ob Transition auch aktiviert ist
                                 if(model.Trans_Liste.get(i).trans_aktiv) {  
                                    
                                         
                                         //alle Ein- und Ausgangsstellen der Transition zwischenspeichern
                                         speichereEinAusStellen(i);     
                                
                                //Anzahl der Marken der Eingangsstellen werden jeweils um 1 reduziert
                                for(int l=0; l < index_von_Stelle.size(); l++) {                                                                                
                                         int index1 = index_von_Stelle.get(l);
                                         model.Stellen_Liste.get(index1).anzahl_Marken = 
                                                         model.Stellen_Liste.get(index1).anzahl_Marken - 1;
                                }
                                
                               
                                th = new Simulation(model, this, model.Trans_Liste.get(i).trans_x_kor,
                                        model.Trans_Liste.get(i).trans_y_kor, i);
                               
                                th.start();                                
                                simuLaeuft = true;                               
                             
                                //warten bis Marken Ziel erreicht haben                      
                                
                                while(simuLaeuft) { 
                                                            
                                    //do nothing
                                }              
                                  
                                
                                th.interrupt();


Hat jemand einen Tipp?

Danke im voraus
 
Ist deine Klasse, bei der du versuchst paintComponent aufzurufen anonym?

Wenn du sowas machst:
Java:
JPanel zeichenfl = new JPanel(){

public void paintComponent(...)
{
...
}
};

Dann wirst du die Methode nicht aufrufen können. Dazu muss es schon eine eigene Klasse sein (Innere würde auch gehen).
 
Ist deine Klasse, bei der du versuchst paintComponent aufzurufen anonym?

Wenn du sowas machst:
Java:
JPanel zeichenfl = new JPanel(){

public void paintComponent(...)
{
...
}
};

Dann wirst du die Methode nicht aufrufen können. Dazu muss es schon eine eigene Klasse sein (Innere würde auch gehen).

Nö, wie kommst du auf diesen Schluss? Eine anonyme Klasse ist auch eine echte eigene Klasse...
 
Also ich nehme mal an, dass du von der Variable "zeichenfl" die paintComponent aufrufen willst.
Es wäre wohl hilfreich einmal zu sehen, wo du die Variable initialisierst und deklarierst.
 
Eine anonyme Klasse ist auch eine echte eigene Klasse...

Das ist soweit ja auch richtig, nur sie definiert ja keinen eigenen Datentyp. Eine Anonyme Klasse welche von JPanel erbt, wird von Java immer noch wie ein JPanel behandelt. Wenn du ich nun meinem anonymen JPanel Methoden gebe, die JPanel eben nicht hat, kann ich diese auch nicht aufrufen 🙂

Java:
JPanel panel = new JPanel() {
			public void wouldLikeToCallIt()
			{}
		};
panel.wouldLikeToCallIt(); // Geht somit nicht
 
zeichenfl ist ein Objekt der Klasse Zeichenflaeche welche eine Erweiterung von JPanel ist, sie wird in einer Klasse Start durch die main-Methode erzeugt:

Java:
 public static void main(String[] args) {
                Model model = new Model();              
                NetzSpeichern dateiKlasse = new NetzSpeichern();
                Zeichenflaeche zeichenfl = new Zeichenflaeche(model);
                Oberflaeche oberflaeche = new Oberflaeche(zeichenfl, model, dateiKlasse);
                oberflaeche.setVisible(true);
        }

Die Klasse Oberflache ist eine Erweiterung von JFrame, in welches das JPanel eingefügt wird.


In zeichenfl wird ein Objekt der Klasse Simulation erzeugt, welche die run-Methode enthält (siehe auch das erste Code-Fragment):

Java:
public class Simulation extends Thread {

    Zeichenflaeche zeichenfl;
    
    Model model;
    
    /**
     * x Position der geschalteten Transition
     */
    int x;
    
    /**
     * y Position der geschalteten Transition
     */
    int y; 
    
    
    int indexTrans;
    
    public Simulation(Model model, Zeichenflaeche zeichenfl, int x, int y, int indexTrans) {  
        this.model = model;
        this.zeichenfl = zeichenfl;       
        this.x = x;
        this.y = y;
        this.indexTrans = indexTrans;
               
        //x-Position der wandernden Marken zu Beginn
        for(int i=0; i < zeichenfl.index_zu_Stelle.size(); i++) {
            zeichenfl.markenX.addLast(x);
        }
        
        //y-Position der wandernden Marken zu Beginn
        for(int i=0; i < zeichenfl.index_zu_Stelle.size(); i++) {
            zeichenfl.markenY.addLast(y);
        }
    }    
    
    
    public void run() {    
        while(!isInterrupted()) {          
            boolean angekommen = true; l                 
            try {               
                zeichenfl.repaint();                   
                Thread.sleep(300);  
                for(int i=0; i < zeichenfl.index_zu_Stelle.size(); i++) {
                    //wenn Marke noch nicht an Zielstelle angekommen
                    if(!zeichenfl.stellePressed(zeichenfl.markenX.get(i), 
                            zeichenfl.markenY.get(i), 
                            model.Stellen_Liste.get(zeichenfl.index_zu_Stelle.get(i)))) {
                       
                        angekommen = false;
                        
                        //einen Pixel in der x-Koordinate weiter
                        zeichenfl.markenX.set(i, zeichenfl.markenX.get(i) + 1);
                        
                        //y-Koordinate berechnen
                        double a = model.Stellen_Liste.get(zeichenfl.index_zu_Stelle.get(i)).stelle_y_kor;
                        double b = model.Trans_Liste.get(indexTrans).trans_y_kor;
                        double c = model.Stellen_Liste.get(zeichenfl.index_zu_Stelle.get(i)).stelle_x_kor;
                        double d = model.Trans_Liste.get(indexTrans).trans_x_kor;
                        double y1 = (a-b)/(c-d);
                        double y2 = y1 * zeichenfl.markenX.get(i) + b - y1*d;
                        int y3 = (int) y2;                   
                        
                        //einen Pixel in der y-Koordinate weiter
                        zeichenfl.markenY.set(i, y3);
                    }
                    //wenn Marke an Zielstelle angekommen
                    else {                       
                        //do nothing
                    }                   

                
                }
                //wenn alle Marken an ihren Zielen angekommen sind, dann Abbruch
                if(angekommen) {                  
                    interrupt();
                }     
                         
            } catch (InterruptedException e) {
                interrupt();               
            }          
        }
        zeichenfl.simuLaeuft = false;
    }
 
@njans: paintComponent ist schon eine Methode von JPanel (bzw. JComponent) aber ...

das Problem ist wohl das hier
Java:
public void mousePressed(MouseEvent e) {           
...

// Viele irrelevante Zeilen und tiefe Verschachtlungen später:
                                th.start();                                
                                simuLaeuft = true;                               
                             
                                //warten bis Marken Ziel erreicht haben                      
                                
                                while(simuLaeuft) { 
                                                            
                                    //do nothing
                                }

Durch das Warten wird der Event-Dispatch-Thread (EDT) blockiert, der sowohl für die Mauseingaben-Verarbeitung als auch das Zeichnen verantwortlich ist. Ein KSKB WILL ich in diesem Fall gar nicht sehen. Schau halt mal ob du dieses Warten da rausbringst....
 
@njans: paintComponent ist schon eine Methode von JPanel (bzw. JComponent) aber ...

Das die Methode von JComponent kommt, war auch nie bezweifelt worden. Es ging lediglich um das folgende:
Java:
JPanel panel = new JPanel() {
			
			@Override
			public void paintComponent(Graphics g)
			{
				super.paintComponent(g);
			}
		};
		panel.paintComponent(...); // Diese Public Methode hat JPanel nicht

Da das Problem aber anderen Ursprungs ist, ist diese Diskussion wohl obsolet.


das Problem ist wohl das hier
Java:
public void mousePressed(MouseEvent e) {           
...

// Viele irrelevante Zeilen und tiefe Verschachtlungen später:
                                th.start();                                
                                simuLaeuft = true;                               
                             
                                //warten bis Marken Ziel erreicht haben                      
                                
                                while(simuLaeuft) { 
                                                            
                                    //do nothing
                                }

Durch das Warten wird der Event-Dispatch-Thread (EDT) blockiert, der sowohl für die Mauseingaben-Verarbeitung als auch das Zeichnen verantwortlich ist. Ein KSKB WILL ich in diesem Fall gar nicht sehen. Schau halt mal ob du dieses Warten da rausbringst....

Hmm habe ich das Problem falsch verstanden?
@TO bitte erkläre doch einmal genau, was das Pronlem ist.

Ich bin bis eben davon ausgegangen, dass dir der Aufruf der Methode unmöglich ist, insofern, dass du vom Compiler bereits eine Fehlermeldung bekommst.
Aber Marco sieht da nun eher einen blockierten EDT. Demnach kannst du schon versuchen das aufzurufen, allerdings setzt das Programm den Aufruf niemals um, da es in der while-Schleife hängt.
 
ich habe dieses Warten entfernt und jetzt funktioniert es.

Es war wie Marco es vermutet hatte, es lag an der while-Schleife.

Vielen Dank in alle Helfer
 

Zurück
Oben