kann ich in einer Klasse stage und scene deklarieren, aber in anderen Klassen Inhalte hinzufügen ?

Vilkazzz

Mitglied
hier ist mein Problem.

Ich will ein Program, welches auf einer Canvas bei gedrückter Maustaste einen Viereck zeichnet,
und wenn ich die Maustaste loslasse, soll anstadt des Vierecks ein Button Erscheinen, mit der Gröse Breite und Position des Vierecks.

das funktioniert jetzt alles bis zu der Stelle wo ich die Maus loslasse und der Button in einer externer Klasse hinzuadiert sein soll.

dies ist übrigens pure Übung und ich wollte daher jeder Aufgabe eine Eigene Klasse schreiben.

mein Problem ist jetzt wie folgt, ich hab eine Klasse wo ich Canvas, Scene, deklariere
und die Stage von der "main" aplication mitgeteilt bekomme (wollte es einfach mal so ausprobieren, wie gesagt, Übung)

Java:
 public void DrawTheButton(final Stage stage){
         BorderPane pane = new BorderPane();
         Scene scene = new Scene(pane, 800,600);
         final Canvas canvas = new Canvas(scene.getWidth(),scene.getHeight());
         canvas.widthProperty().bind(scene.widthProperty());
         canvas.heightProperty().bind(scene.heightProperty());
         final GraphicsContext gc = canvas.getGraphicsContext2D();

         canvas.setOnMousePressed(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {
                //System.out.println("maus klicked");

                MakeRect(event.getX(), event.getY(),canvas, gc);  // 
            }
        });

        pane.getChildren().add(canvas);
        stage.setScene(scene);
        stage.show();

sobald die Maus geklickt wird, wird die Klasse MakeRect ausgerufen,

Java:
  MakeRect(event.getX(), event.getY(),canvas, gc);


in der Klasse MakeRect wird dann ein Viereck gezeichnet solange die Maustaste gedrückt ist,
und sobald die Maustaste losgelassen wird, will ich die nächste Klasse starten, die dann
ein Objekt (button in meinem fall) dort erstellt, wo x,y, Breite und Höhe weitergeleite werden.

Also sehr grob verkürzt

Java:
canvas.setOnMouseReleased(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {

                         MakeButton(xx, yy,width , height);

nun hab ich folgendes Problem, die "MakeButton" klasse hat keine Ahnung von Stage, Scene oder was anderem.

Was wäre denn jetzt die eleganteste Lösung den Knopf mit vorhandenen Maasen auf dem Bildschirm erscheinen zu lassen ?

Musste ich die Information über stage, scene usw immer weiterleiten ?

Kann ich nicht einfach zu dem Zeitpunkt eine neue Scene erstellen und die alte ersetzen ?

Ich gebe zu, ich bin einfach ins JavaFX kopfüber reingesprungen und versuche grade darin zu schwimmen ohne dass ich halbes jahr jede Woche neue Methoden mir einprägen konnte.

Daher klappen manche sachen wie die bind und Propertys sehr gut, aber sowas wie ein Button
erscheinen zu lassen .... da scheitere ich 🙁

damit niemand meckert dass ich zuwenig code gegeben habe, hier die Komplette Baustelle,
sry für viele printlines ... ist eine art mein Debuger seid alten Zeiten 😀

Java:
package sample;


import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;


import static javafx.scene.shape.ArcType.*;

public class Main extends Application {

   
    public void MakeRect(final double x, final double y, final Canvas canvas, final GraphicsContext gc) {
        System.out.println("maus position x = " + x + " y = " + y);

        canvas.setOnMouseDragged(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {
                gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
                double width;
                double height;
                System.out.println("x=" + x + " event" + event.getX());
                width = x - event.getX();
                height = y - event.getY();

                //rect muss mit positiven werden gemacht werden

                if (width < 0) {
                    width = width * (-1);
                }
                ;
                if (height < 0) {
                    height = height * (-1);
                }
                ;

                //rect muss das oberste linke Ecke des Gebildes finden
                // das wird oben links x und y wert.

                double xx;
                double yy;


                if (x > event.getX()) {
                    xx = event.getX();
                } else xx = x;

                if (y > event.getY()) {
                    yy = event.getY();
                } else yy = y;


                gc.strokeRect(xx, yy, width, height);

            }
        });


        canvas.setOnMouseReleased(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {
                System.out.println("maus released");
                double width;
                double height;
                System.out.println("x=" + x + " event" + event.getX());
                width = x - event.getX();
                height = y - event.getY();
                //rect muss mit positiven werden gemacht werden

                if (width < 0) {
                    width = width * (-1);
                }
                ;
                if (height < 0) {
                    height = height * (-1);
                }
                ;

                //rect muss das oberste linke Ecke des Gebildes finden
                // das wird oben links x und y wert.

                double xx;
                double yy;


                if (x > event.getX()) {
                    xx = event.getX();
                } else xx = x;

                if (y > event.getY()) {
                    yy = event.getY();
                } else yy = y;

                gc.strokeRect(xx, yy, width, height);

                MakeButton(xx, yy, width, height);

            }
        });


    }

    public void MakeButton(double x, double y, double width, double height) {

        System.out.println("MAKE BUTTON AKTIVIERT !");
        Pane pane = new Pane();
        Scene scene = new Scene(pane);

        Button scalierButton = new Button("Klick mich an");
        scalierButton.setVisible(false);

        scalierButton.setLayoutX(x);
        scalierButton.setLayoutY(y);
        scalierButton.setPrefWidth(width);
        scalierButton.setPrefHeight(height);
        scalierButton.setVisible(true);
        pane.getChildren().add(scalierButton);

    }

    public void DrawTheButton(final Stage stage) {
        BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, 800, 600);
        final Canvas canvas = new Canvas(scene.getWidth(), scene.getHeight());
        canvas.widthProperty().bind(scene.widthProperty());
        canvas.heightProperty().bind(scene.heightProperty());
        final GraphicsContext gc = canvas.getGraphicsContext2D();
        canvas.setOnMousePressed(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {
                //System.out.println("maus klicked");
                MakeRect(event.getX(), event.getY(), canvas, gc);
            }
        });

        pane.getChildren().add(canvas);
        stage.setScene(scene);
        stage.show();

    }

    @Override
    public void start(Stage stage) {

        DrawTheButton(stage);
    }


    public static void main(String[] args) {
        launch(args);
    }
}
 
Zuletzt bearbeitet:
1) C#/.NET-Entwickler? Der Code sieht eher danach aus, als nach Java. Vielleicht solltest du noch mal schauen, was so die verbreiteten Code-Conventions/Style-Guides sind... (Es liest sich einfach etwas schwer, daher dieser Kommentar.)

2) Also um die Frage kurz zu machen: Wenn du Stage/Scene oder was auch immer mit an die Klasse übergibst (Kontruktor, Setter-Methoden, oder irgendeine Form von Dependecy Injection), kannst du dort damit arbeiten. Wie du es übergibst, bleibt aber eher dir überlassen.
Ich vermute du möchtest das machen, um die Klasse, mit der du gerade arbeitest, übersichtlich zu gestalten. Das ist an und für sich löblich, aber in deinem Fall vielleicht etwas zu umständlich.
Ich glaube, Kopfüber in JavaFX/SWT/Swing ist immer gleich "schwer", wenn man vorher noch nichts damit gemacht hat. Ich hab beim ersten Anschauen von Android auch nicht begriffen, wie deklarative GUIs funktionieren.
Ich bin mir im Moment nur unsicher, ob - und wenn ja: wie - man Buttons auf Canvas zeichnen kann. Ich denke, dass geht nicht (weiss aber auch nicht, wozu du den Button später weiter verwenden möchtest).
 
hi dzim

das Problem hab ich inzwischen gelöst, indem ich alles in die selbe Klasse schreibe 🙁

es funktioniert genauso wie ich es wollte, der Code ist aber Gegenteil von schön 🙁

aber 2 Monate später sich in diesem Programm zurechtzufinden .... wird schwer 🙁

den Code kann man in die IDE reintuhn, dann sieht man was ich versuchte.

wenn also jemand sich anschaut was das Program macht, und mir die grobe Architektur vorschlagen könnte, dafür wäre ich dankbar, ohne exacte codelines, einfach nur "mach in main nur scene, hole dir canvas mit "return" von klasse so und so, mach dann klasse die dieses vererbt und das hier ausspuckt.

So, und jetzt such ich mir ein Muttersprachler der meine Gramatik korrigiert 😀

Java:
package sample;


import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.TextAlignment;
import javafx.stage.Stage;




public class Bewerbung extends Application {

    @Override
    public void start(Stage stage) {
        final BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, 800,600);
        final VBox vBox = new VBox();

        final Label label = new Label("test");
        label.setText("Hallo, hiermit möchte ich kurz meine derzeitigen Java Kentnisse vorzustellen");
        label.setFont(Font.font("Verdana", 16));
        pane.setTop(label);
        BorderPane.setAlignment(label, Pos.CENTER);

        Label labelBot = new Label("bottom");
        String bottomText = new String();
        bottomText = "blabla";


        labelBot.setText("bitte die Maus auf die Mittlere Fläche bewegen, dann  durch klicken der linker Maustaste  \n gefolgt von  bewegung  der  Maus einen Viereck erzeugen, \n welches durch das Loslassen der Maustaste durch ein Button Objekt ausgetauscht wird ");
        labelBot.setFont(Font.font("Verdana", 16));
        labelBot.setTextAlignment(TextAlignment.CENTER);
        BorderPane.setAlignment(labelBot, Pos.CENTER);



       final VBox vBoxBottom = new VBox();
        final Label explainBindings = new Label();
        explainBindings.setText("Durch das scalieren des unten entstandenes Sliders, \n können sie die Gröse des Buttons direkt beeinflussen \n dies wird durch bind Propertys gemacht \n wenn sie auf den Button klicken, wird der Button über den gesammten Fenster instanziert. \n Ergebnisse hängen von der Größe des Fensters und des Buttons.");
        explainBindings.setFont(Font.font("Verdana", 16));
        explainBindings.setTextAlignment(TextAlignment.CENTER);
        vBoxBottom.getChildren().add(explainBindings);

       pane.setBottom(labelBot);

        final Pane pane2 = new Pane();


        //making canvas for center position of borderpane, so i can draw there
       final Canvas canvas = new Canvas(600, 400);
        vBox.getChildren().add(canvas);


        //diese werden später gebraucht, ich deklariere die hier oben, dami tauch submethoden darauf zugreifen können
       pane.setCenter(vBox);
        vBox.setAlignment(Pos.CENTER);

        final Slider slider = new Slider(0, 2, 1);
        slider.setShowTickMarks(true);
        slider.setShowTickLabels(true);
        slider.setMajorTickUnit(0.25f);
        slider.setBlockIncrement(0.1f);
        slider.setVisible(false);//wird noch nicht gebraucht daher unsichtbar

        final Button button = new Button();
        button.setVisible(false);
        button.scaleXProperty().bind(slider.valueProperty());
        button.scaleYProperty().bind(slider.valueProperty());
        //hier wurden grade die propertys festgelegt, für die ellemente die erst später sichtbar werden.




        button.setOnAction(new EventHandler<ActionEvent>() {

            @Override //Hier wird definiert, dass nach dem buttonclick die mittlere fläche voll von buttons gemacht wird
            public void handle(ActionEvent event) {
               double paneW = pane2.getWidth();
               double paneH = pane2.getHeight();
               int xline = (int) (paneW/button.getWidth());
               int yline = (int) (paneH/button.getHeight());
               double exWidth =  button.getWidth();
                double exHeight = button.getHeight();


                pane2.getChildren().remove(button);
                Button[][] buttons = new Button[xline][yline];// sonst wird je dimension 1 zu viel deklariert.
                for (int x=0;x<xline;x++){
                    for(int y=0;y<yline;y++){
                        buttons[x][y] = new Button();
                        buttons[x][y].setPrefWidth(exWidth);
                        buttons[x][y].setPrefHeight(exHeight);
                        buttons[x][y].setLayoutX(x * exWidth);
                        buttons[x][y].setLayoutY(y * exHeight);
                        slider.setMax(1);// der Bildschirm ist bereits voll, es soll nur noch kleiner werden.
                        buttons[x][y].scaleXProperty().bind(slider.valueProperty());
                        buttons[x][y].scaleYProperty().bind(slider.valueProperty());
                        buttons[x][y].setText("Reihe:"+(y+1)+" Nr."+(x+1));
                        pane2.getChildren().add( buttons[x][y]);





                    }
                }
                //das erklärungs kommentar nachdem die for schleifen durchgelaufen sind.
                Label comment3 = new Label();
                comment3.setText("natürlich können sie mit dem Slider immernoch die Größe von allen skalieren");
                comment3.setFont(Font.font("Verdana", 16));
                vBoxBottom.getChildren().removeAll(explainBindings, slider);
                vBoxBottom.getChildren().addAll(comment3,slider);


            }
        });










        final GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.setFill(Color.LIGHTGRAY);
        gc.fillRect(0,0,canvas.getWidth(), canvas.getHeight());
        canvas.setOnMousePressed(new EventHandler<javafx.scene.input.MouseEvent>() {
            @Override
            public void handle(javafx.scene.input.MouseEvent event) {

                //hier werden die aktuell geklickten Mauspositions x und y gespeichert.
                final double x  = event.getX();
                final double y = event.getY();


                canvas.setOnMouseDragged(new EventHandler<javafx.scene.input.MouseEvent>() {
                    @Override
                    public void handle(javafx.scene.input.MouseEvent event) {
                        gc.setFill(Color.LIGHTGRAY);
                        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
                        double width;
                        double height;
                        width = x - event.getX();
                        height = y - event.getY();

                        //rect muss mit positiven werden gemacht werden

                        if (width < 0) {
                            width = width * (-1);
                        }
                        ;
                        if (height < 0) {
                            height = height * (-1);
                        }
                        ;

                        //rect muss das oberste linke Ecke des Gebildes finden
                        // das wird oben links x und y wert.

                        double xx;
                        double yy;


                        if (x > event.getX()) {
                            xx = event.getX();
                        } else xx = x;

                        if (y > event.getY()) {
                            yy = event.getY();
                        } else yy = y;


                        gc.strokeRect(xx, yy, width, height);

                    }
                }); //ende von mause draged

                canvas.setOnMouseReleased(new EventHandler<javafx.scene.input.MouseEvent>() {
                    @Override
                    public void handle(javafx.scene.input.MouseEvent event) {
                        //canvas.setVisible(false);

                        double width;
                        double height;

                        width = x - event.getX();
                        height = y - event.getY();
                        //rect muss mit positiven werden gemacht werden

                        if (width < 0) {
                            width = width * (-1);
                        }
                        ;
                        if (height < 0) {
                            height = height * (-1);
                        }
                        ;

                        //rect muss das oberste linke Ecke des Gebildes finden
                        // das wird oben links x und y wert.

                        double xx;
                        double yy;


                        if (x > event.getX()) {
                            xx = event.getX();
                        } else xx = x;

                        if (y > event.getY()) {
                            yy = event.getY();
                        } else yy = y;
                        // those are xx und yy coordinates on Canvas, now we remove canwas, so we must ajjust x and y

                        xx=xx+canvas.getLayoutX();
                        yy = yy+canvas.getLayoutY();

                        gc.strokeRect(xx, yy, width, height);
                        vBox.getChildren().remove(canvas);

                        pane2.getChildren().add(button);
                        pane.setCenter(pane2);

                        // xx und yy müssen jetzt an die pane2 angepasst werden.
                        xx=xx +pane2.getLayoutX();
                        yy=yy +pane2.getLayoutY();
                        button.setLayoutX(xx);
                        button.setLayoutY(yy);
                        button.setPrefWidth(width);
                        button.setPrefHeight(height);
                        button.setText("klick me");
                        button.setVisible(true);

                        slider.setVisible(true);
                        vBoxBottom.getChildren().add(slider);
                        vBoxBottom.setAlignment(Pos.BOTTOM_CENTER);
                        pane.setBottom(vBoxBottom);
                        BorderPane.setAlignment(vBoxBottom,Pos.BASELINE_CENTER);











                    }
                }); //ende von maus released


            }
        });  //ende von maus pressed










        stage.setScene(scene);
        stage.show();


    }



    public static void main(String[] args) {
        launch(args);
    }
}
 
Mach doch mal nicht so viele Leerzeilen. Und du hättest die GUI selbst schon noch in eine eigene Klasse auslagern können. Du musst nicht alles in die Hauptklasse tun.

Um es zu sortieren: Alles, bis auf die primaryStage und die Scene muss in der Main-Klasse nichts weiter drin sein.
Deine UI-Klasse muss im einfachsten Fall nicht mal etwas im Konstruktor übergeben werden, sondern nur eine "#getContent()"-Methode haben, die ein Pane zurück gibt (könnte also über ein Interface wiederverwendet werden). Letzten Endes wäre sie dann in JavaFX-Terminologie quasi die deklaration der UI, sowie deren Controller in einem, dass kannst du aber gerne noch weiter auseinanderziehen, wenn du willst.

Und wenn du mal Zugriff auf die Scene/Stage brauchst, kann dir Google und StackOverflow weiterhelfen (also um zu vermeiden, diese als Dependency überall hineinreichen zu müssen):
java - How to reference primaryStage - Stack Overflow
 
Schau dir vielleicht auch mal FXMLs an (stellt die UI in XML-form dar). Sog. Controller-Klassen kümmern sich dann um das verhalten. Oder du bettest für einfache Sachen das ganze in JavaScript (oder andere Scriptsprachen, die auf der JVM laufen können) ein.
 
FXML ist als nächstes drann, heute meldet mein Kopf grade "system overload error" 🙁

hast ja bereits im beginner forum die Antwort zu dem thread hier gepostet, somit markiere ich es als erledigt 🙂
 

Zurück
Oben