JavaFX Rechtecke werden nicht neu gezeichnet

Diskutiere Rechtecke werden nicht neu gezeichnet im AWT, Swing, JavaFX & SWT Bereich.
ronbot77

ronbot77

Hallo,
wenn ich die Methode testSwap(3,4) aufrufe, werden die Rechtecke brav auf die neue Länge gesetzt. Tue ich das ganze in einer Schleife, so läuft erst die gesamte Schleife durch.
Ursprünglich war meine Idee, ein Array von Rechtecken zu zeichnen, diese zu mixen und anschließend mit unterschiedlichen Sortierverfahren zu sortieren. Hierfür möchte ich gerne nach jedem Schritt unterbrechen können - deshalb der Scanner.

|
Java:
import java.util.Scanner;
import javafx.application.Application; 
import java.util.Random;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Scene; 
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*; //Blur
import javafx.scene.layout.GridPane;
import javafx.scene.shape.*; // Rectangle und Circle
import javafx.animation.*; // TimeLine und KeyFrame
import javafx.stage.Stage; 
import javafx.geometry.VPos;
import javafx.geometry.Insets;
import java.util.Date; // for sleep function

public class LinesFX extends Application{
    int [] werte;
    public Rectangle[] rect;
    private Scanner s;
    GridPane gridPane = new GridPane();
    //Stage primaryStage;
    private int factor = 20;
    public LinesFX(int [] pWerte) {
        werte = pWerte;
        rect = new Rectangle[werte.length];
        start(new Stage());
        s = new Scanner(System.in);
    }

    public LinesFX() {
        werte = new int[]{1,3,4,6,7,11,14,2,5,8,9,10,12,13,15};
        rect = new Rectangle[werte.length];
        s = new Scanner(System.in);
        start(new Stage());
    }

    @Override
    public void start(Stage primaryStage) //throws Exception
    {

        for (int i=0; i < werte.length; i++) {
            rect[i] = new Rectangle(10+factor*i, 10, 20, factor*werte[i]);
            rect[i].setArcWidth(5);
            rect[i].setArcHeight(5);
            rect[i].setStrokeWidth(2);
            rect[i].setStroke(Color.BLUE);
            rect[i].setFill(Color.DODGERBLUE);
            //rect[i].setEffect(new Lighting());

            GridPane.setConstraints(rect[i],i,0); //Set row and column
            GridPane.setValignment(rect[i], VPos.TOP);
        }

        gridPane.setPadding(new Insets(10,10,10,10));
        gridPane.setHgap(10);
        gridPane.getChildren().addAll(rect);

        primaryStage.setScene(new Scene(gridPane, factor*werte.length*2, factor*werte.length*1.5));
        primaryStage.setTitle(this.getClass().getSimpleName()); // set window title
        primaryStage.show();
    } 

    @Override public void stop() {
    }

    public void testSwap(int index1, int index2) {
        double helper = rect[index1].getHeight();
        rect[index1].setHeight(rect[index2].getHeight());
        rect[index2].setHeight(helper);
    }

    public void mixen() {
        int index1, index2;
        for (int i = 0 ; i < werte.length*1; i++) {
            index1 = (int)(Math.random()*(werte.length));
            index2 = (int)(Math.random()*(werte.length));
            testSwap(index1,index2);
            s.next();
        }
    }



//...

    public static void main(String args[]){ 
        launch(args); 
    } 
}
 
dzim

dzim

Erst einmal sehe ich einen Fehler: Du rufst die Start-Methode in deinem primären Constructor auf. Macht man nicht, macht die API.
Was du machen kannst, ist die Initialisierung in der init-Methode zu machen (dazu diese overriden). Du hast da auch Zugriff auf die Argumente, mit denen die Applikation gestartet wurde (via getParameter() oder so...).

Dein Problem mit der Schleife ist ein anderes: In jeder Doku zu UI-Code (auch bei JavaFX) wirst du lesen, dass du keine Berechnungsintensiven oder Resourcenabhängigen Operationen auf dem UI-Thread machen solltest, da dies sonst zu einer (temporär) verklemmten Anwendung führt.
Sprich: Du machst Berechnungen direkt auf dem UI-Thread und erwartest, dass dieser gleichzeitig die notwendigen Updates am UI machen soll. Das geht (zumindest bei JavaFX und einer Reihe anderer Frameworks) nicht.

Lager das neuberechnen in einen separaten Thread aus und aktualisiere den UI-Thread (also die setHeight-Operationen) mittels Platform#runLater.
 
ronbot77

ronbot77

Hallo, vielen Dank für die Antwort.

In einem ersten Versuch habe ich versucht, die JavaFX-Klasse, die das Zeichnen der Rechtecke übernimmt, von außen zu steuern. Das brachte aber dieselben Probleme mit sich. Ich habe schon versucht, in das Thema Threads einzusteigen, aber so ganz erschließt sich mir das nicht. Die Lösung ist also, die Schleife in einen Thread zu packen, aus dieser Schleife heraus dann das Zeichnen in der FX-Klasse aufzurufen, und das Betriebssystem kümmert sich um den Rest? Ich versuche mich mal, in das Thema Concurrency einzuarbeiten..

Wichtig ist mir, dass ich eben die Abarbeitung der Schleife unterbrechen kann, um vor dem nächsten Schritt die Rechtecke neu zu zeichnen.
 
ronbot77

ronbot77

Jetzt habe ich einen Thread, der unendlich lange läuft. Allerdings ist ja eine Aufgabe auch mal erledigt - und nu?

Java:
import java.util.Scanner;
import javafx.application.Application; 
import javafx.application.Platform;
import java.util.Random;
import javafx.util.Duration;
import javafx.scene.Group;
import javafx.scene.Scene; 
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*; //Blur
import javafx.scene.layout.GridPane;
import javafx.scene.shape.*; // Rectangle und Circle
import javafx.animation.*; // TimeLine und KeyFrame
import javafx.stage.Stage; 
import javafx.geometry.VPos;
import javafx.geometry.Insets;
import java.util.Date; // for sleep function

public class LinesFX extends Application{
    int [] werte;
    public Rectangle[] rect;
    private Scanner s;
    Thread thread;
    GridPane gridPane = new GridPane();
    private int factor = 20; // Skalierung der Rechtecke
    public LinesFX(int [] pWerte) {
        werte = pWerte;
        rect = new Rectangle[werte.length];
        //start(new Stage());
        //s = new Scanner(System.in);
    }

    public LinesFX() {
        werte = new int[]{1,3,4,6,7,11,14,2,5,8,9,10,12,13,15};
        rect = new Rectangle[werte.length];
        //s = new Scanner(System.in);
        //start(new Stage());
    }

    @Override
    public void start(Stage primaryStage) //throws Exception
    {
        for (int i=0; i < werte.length; i++) {
            rect[i] = new Rectangle(10+factor*i, 10, 20, factor*werte[i]);
            rect[i].setArcWidth(5);
            rect[i].setArcHeight(5);
            rect[i].setStrokeWidth(2);
            rect[i].setStroke(Color.BLUE);
            rect[i].setFill(Color.DODGERBLUE);
            GridPane.setConstraints(rect[i],i,0); //Set row and column
            GridPane.setValignment(rect[i], VPos.TOP);
        }
        gridPane.setPadding(new Insets(10,10,10,10));
        gridPane.setHgap(10);
        gridPane.getChildren().addAll(rect);
        
        // Das Mixen laeuft in einer Schleife und wird daher in einen
        // separaten Thread ausgelagert
        thread  = new Thread (new Runnable() 
            {
                @Override
                public void run() {
                    Runnable updater = new Runnable() 
                        {
                            @Override
                            public void run() {
                                mixen();
                            }
                        };
                    while (true) {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException ex) {
                        }
                        Platform.runLater(updater);
                    }
                }
            });

        primaryStage.setScene(new Scene(gridPane, factor*werte.length*2, factor*werte.length*1.5));
        primaryStage.setTitle(this.getClass().getSimpleName()); // set window title
        primaryStage.show();
    } 

    @Override public void stop() {
    }

    public void testSwap(int index1, int index2) {
        double helper = rect[index1].getHeight();
        rect[index1].setHeight(rect[index2].getHeight());
        rect[index2].setHeight(helper);
    }

    private void mixen() {
        int index1, index2;
        for (int i = 0 ; i < werte.length*1; i++) {
            index1 = (int)(Math.random()*(werte.length));
            index2 = (int)(Math.random()*(werte.length));
            testSwap(index1,index2);
            //s.next();
        }
    }

    public void mix2() {
        thread.start();
    }



    public static void main(String args[]){ 
        launch(args); 
    } 
}
 
ronbot77

ronbot77

Ich habe was gefunden, aber noch nicht umgesetzt. Ich würde meinen letzten Post ja auch löschen, aber das kann ich nicht.
(Der Scanner ist raus, der Thread kann ja auch schlafen für eine gegebene Zeit. Das war eigentlich das, was ich brauchte.)
 
ronbot77

ronbot77

Ich komme doch nicht weiter. Packe ich meine Schleife in ein runnable(), dann läuft sie ewig. Packe ich sie in einen einzelnen Thread, läuft sie nur einmal. Muss ich für meine Mix-Methode eine eigene Klasse einrichten, die dann runnable implementiert?
 
ronbot77

ronbot77

Ich habe es gelöst!
Java:
import javafx.application.Application; 
import java.util.Random;
import javafx.scene.Scene; 
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*; //Blur
import javafx.scene.layout.GridPane;
import javafx.scene.shape.*; // Rectangle 
import javafx.stage.Stage; 
import javafx.geometry.VPos;
import javafx.geometry.Insets;

public class LinesFX extends Application{
    int [] werte;
    public Rectangle[] rect;
    Thread mixThread;
    GridPane gridPane = new GridPane();
    private int factor = 20; // Skalierung der Rechtecke
    public LinesFX(int [] pWerte) {
        werte = pWerte;
        rect = new Rectangle[werte.length];
    }

    public LinesFX() {
        werte = new int[]{1,3,4,6,7,11,14,2,5,8,9,10,12,13,15};
        rect = new Rectangle[werte.length];
    }

    @Override
    public void start(Stage primaryStage) //throws Exception
    {
        for (int i=0; i < werte.length; i++) {
            rect[i] = new Rectangle(10+factor*i, 10, 20, factor*werte[i]);
            rect[i].setArcWidth(5);
            rect[i].setArcHeight(5);
            rect[i].setStrokeWidth(2);
            rect[i].setStroke(Color.BLUE);
            rect[i].setFill(Color.DODGERBLUE);
            GridPane.setConstraints(rect[i],i,0); //Set row and column
            GridPane.setValignment(rect[i], VPos.TOP);
        }
        gridPane.setPadding(new Insets(10,10,10,10));
        gridPane.setHgap(10);
        gridPane.getChildren().addAll(rect);
        primaryStage.setScene(new Scene(gridPane, factor*werte.length*2, factor*werte.length*1.5));
        primaryStage.setTitle(this.getClass().getSimpleName()); // set window title
        primaryStage.show();
    } 

    @Override public void stop() {
    }


    public void mixIt() {
        mixThread = new Thread("Mixer") {
            public void run() {
                int index1, index2;
                for (int i = 0 ; i < werte.length*10; i++) {
                    index1 = (int)(Math.random()*(werte.length));
                    index2 = (int)(Math.random()*(werte.length));
                    double helper = rect[index1].getHeight();
                    rect[index1].setHeight(rect[index2].getHeight());
                    rect[index2].setHeight(helper);
                    //System.out.println(getName()+ " Durchlauf Nr. "+i);
                    try {
                        Thread.sleep(30);
                    } catch(InterruptedException e) {
                        System.out.println(getName()+" wurde unterbrochen");
                    }
                }
            }

        };
        mixThread.start();
    }

}
 
M

MayorB26

Ich habe es gelöst!
Java:
import javafx.application.Application;
import java.util.Random;
import javafx.scene.Scene;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.scene.effect.*; //Blur
import javafx.scene.layout.GridPane;
import javafx.scene.shape.*; // Rectangle
import javafx.stage.Stage;
import javafx.geometry.VPos;
import javafx.geometry.Insets;

public class LinesFX extends Application{
    int [] werte;
    public Rectangle[] rect;
    Thread mixThread;
    GridPane gridPane = new GridPane();
    private int factor = 20; // Skalierung der Rechtecke
    public LinesFX(int [] pWerte) {
        werte = pWerte;
        rect = new Rectangle[werte.length];
    }

    public LinesFX() {
        werte = new int[]{1,3,4,6,7,11,14,2,5,8,9,10,12,13,15};
        rect = new Rectangle[werte.length];
    }

    @Override
    public void start(Stage primaryStage) //throws Exception
    {
        for (int i=0; i < werte.length; i++) {
            rect[i] = new Rectangle(10+factor*i, 10, 20, factor*werte[i]);
            rect[i].setArcWidth(5);
            rect[i].setArcHeight(5);
            rect[i].setStrokeWidth(2);
            rect[i].setStroke(Color.BLUE);
            rect[i].setFill(Color.DODGERBLUE);
            GridPane.setConstraints(rect[i],i,0); //Set row and column
            GridPane.setValignment(rect[i], VPos.TOP);
        }
        gridPane.setPadding(new Insets(10,10,10,10));
        gridPane.setHgap(10);
        gridPane.getChildren().addAll(rect);
        primaryStage.setScene(new Scene(gridPane, factor*werte.length*2, factor*werte.length*1.5));
        primaryStage.setTitle(this.getClass().getSimpleName()); // set window title
        primaryStage.show();
    }

    @Override public void stop() {
    }


    public void mixIt() {
        mixThread = new Thread("Mixer") {
            public void run() {
                int index1, index2;
                for (int i = 0 ; i < werte.length*10; i++) {
                    index1 = (int)(Math.random()*(werte.length));
                    index2 = (int)(Math.random()*(werte.length));
                    double helper = rect[index1].getHeight();
                    rect[index1].setHeight(rect[index2].getHeight());
                    rect[index2].setHeight(helper);
                    //System.out.println(getName()+ " Durchlauf Nr. "+i);
                    try {
                        Thread.sleep(30);
                    } catch(InterruptedException e) {
                        System.out.println(getName()+" wurde unterbrochen");
                    }
                }
            }

        };
        mixThread.start();
    }

}
So, nu müsstest du das ganze nur noch compilieren, so dass daraus ne app wird , bzw mir sage mit welcher app oder ide app ich das auf meinem handy. In ne app compiliert kriege, dann wird daraus n schuh,..
Mfg

Gunnar
 
ronbot77

ronbot77

Nachdem es geklappt hat habe ich das erst mal ruhen lassen. Für eine App wäre das doch noch etwas zu dürftig - ich stelle mir vor, noch Buttons einzubauen, um auch andere Sortierverfahren zu simulieren. Allerdings gibt es so viel Zeug zu dem Thema bei Youtube.. mir ging es eher um den "sportlichen" Character, nach dem Motto: "Bekomme ich das hin?".

Viele Grüße
R.
 
Thema: 

Rechtecke werden nicht neu gezeichnet

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben