2017-08-17 1 views
0

Kurzversion:System.out.println() mit einem einfachen Getter innerhalb macht Swing Repaint nicht wie vorgesehen

Dies funktioniert und ändert die Farbe eines Rechtecks ​​auf dem Bildschirm:

public void test(){ 

    tilePointer.setIcon(Color.RED); 

} 

Dies gilt nicht:

public void test(){ 

    System.out.println("color: " + tilePointer.getIcon());     
    tilePointer.setIcon(Color.RED); 

} 

Lange Version:

Während ich etwas mit Arraylisten und Objekten testete, bemerkte ich ein ziemlich merkwürdiges Verhalten.

Ich habe ein 2D-Array von Fliesen (die Klasse Tile hat nur ein Color-Attribut namens icon).

Dieses 2D-Array von Tiles wird mithilfe einer Klasse, die JPanel erweitert und drawComponent() überschreibt, auf dem Bildschirm gezeichnet. Diese Klasse hat ein anderes 2D-Array, diesmal von Colors. Es zeichnet ein Rechteck für jede Farbe in diesem Array.

Die folgende Methode wird verwendet, um die icon von einem Tile zu dem erweiterten JPanel zu geben. Der Methodenaufruf ist nur etwas wie panel.place(x,y,tiles[y][x].getIcon()).

public void place(int x, int y, Color color){ 
    colors[y][x] = color; 
} 

Ich habe ein anderes Objekt aus der Klasse Tile, tilePointer, das ein "Zeiger" zu einem der Fliesen in der Anordnung ist (so etwas wie tilePointer = Fliese [y] [x]).

Das folgende einfache Codefragment funktioniert einwandfrei und macht genau das, wonach es aussieht. Es ändert nur die Farbe von tilePointer und das Rechteck auf dem Bildschirm entsprechend.

public void test(){ 

    tilePointer.setIcon(Color.RED); 

} 

Jetzt kommt hier der wirklich komische Teil. Wenn ich die test Methode dies zu ändern:

public void test(){ 

    System.out.println("color: " + tilePointer.getIcon());     
    tilePointer.setIcon(Color.RED); 

} 

Das Rechteck einfach einfach nicht die Farbe ändern. Allerdings, wenn eine andere System.out.println("color: " + tilePointer.getIcon()) nach der setIcon(), kann ich sehen, dass der Wert tatsächlich geändert.

Nein, die Methoden getIcon() und setIcon() sind nicht sonderlich komisch. sie sind nur

public Color getIcon() { 
    return icon; 
} 

public void setIcon(Color icon) { 
    this.icon = icon; 
} 

Weiß jemand, was könnte das verursachen? Danke im Voraus.

[EDIT] habe ich vergessen, etwas zu erwähnen wichtig:

Die test() Verfahren in einem anderen Thread aufgerufen wird. Der Grund dafür ist, dass test() einen viel größeren Job haben sollte, als nur einen einzelnen Tile neu einzufärben.

public void startup() { 

    new Thread(() -> { 
     qtd = test(); 
    }).start(); 

} 

Wenn ich es auf dem gleichen Thread laufen zu lassen, wie der Rest der Anwendung tut es beheben.

public void startup() { 

    qtd = test(); 

} 

Aber immer noch, das erklärt nicht, was das Problem verursacht. Dies hängt jedoch wahrscheinlich damit zusammen. Ich entschuldige mich, dass ich das nicht früher erwähnt habe.

+2

Es ist schwer zu überprüfen, was das Problem ist, ohne es reproduzieren zu können. Vielleicht ist es Variation des Problems, das in https://stackoverflow.com/questions/25425130/loop-doesnt-see-changed-value-without-a-print-statement beschrieben wird. Um die richtige Antwort zu bekommen, brauchen wir [mcve]. – Pshemo

Antwort

0

Ich stimme nur mit meinen Erfahrungen hier (und auf keinen Fall sollten Sie dies als eine gut recherchierte Antwort betrachten). Meine Erfahrung mit Swing (und den meisten anderen Frameworks) ist, dass Sie, sobald Sie einen einzelnen Thread verlassen, diesen Staat selbst verwalten müssen. Swing weiß nicht wirklich, ob es aktualisiert werden muss, bis die Ereignisschleife etwas hat, das es aktualisiert.

Ohne ein vollständiges Beispiel diese nur schwer zu reproduzieren, aber da du schon bist Sprung in Multithreading Sie eines davon auf Schwingen Muster lesen, sollten, wenn Ihre Änderung Im Falle des Codes SwingUtilities.invokeLater(Runnable)

ist Die GUI passiert in einem anderen Thread. Sie müssen den Main Swing-Thread erneut über SwingUtilities verbinden, um sicherzustellen, dass Ihr Code in dieser Ereignisschleife passiert.

Ich vermute, dass, wenn Sie einen Handler hinzufügen würden, der etwas anderes (wie eine Schaltfläche) änderte und dann auf das Symbol traf, würde Ihr rotes Symbol mit dieser Schaltfläche angezeigt werden.

lange Geschichte kurz Sie wollen wahrscheinlich etwas Ähnliches wie folgt aus:

/* Forgive me, I'm jumping between five languages 
right now and this might not be the correct syntax for 
creating an anonymous threads */ 

SwingUtilities.invokeLater(()-> { 
    //All this code will run on the Swing Thread 
    System.out.println("color: " + tilePointer.getIcon());     
    tilePointer.setIcon(Color.RED); 
})