Dynamische ListView-Größe, die bei Fenstergrößenänderung sich anpasst

BigMemo007

Aktives Mitglied
Hallo liebe Comunity,

habe folgendes Projekt in JafaFX gemacht:

Java:
package gui;

import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.control.TextField;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

public class CreateGUIBooking {

    private Scene scene;
    private BorderPane layout;

    private VBox vBoxTop;
    private VBox vBoxBottom;
    private VBox vBoxLeft;
    private VBox vBoxRight;
    private VBox vBoxCenter;
    
    private Font fontLabel;
    
    private Label labelAmount;
    private TextField tfAmount;
    private Separator separator;
    private Button btn_buchen;
    private ListView<String> outgoings;
    private ListView<String> income;
    private Label labelOutgoings;
    private Label labelIncome;
    
    private String txtLabelAmount = "Betrag eingeben";
    private String txtLabelOutgoings = "Ausgaben";
    private String txtLabelIncome = "Einnahmen";
    private String txtBtn_buchen = "Buchen";
    
    public CreateGUIBooking() {
        layout = new BorderPane();
        scene = new Scene(layout, 700, 600);

        vBoxTop = new VBox();
        vBoxLeft = new VBox();
        vBoxCenter = new VBox();
        vBoxRight = new VBox();
        vBoxBottom = new VBox();
        
        fontLabel = Font.font("sans-serif", FontWeight.BOLD, 15);
        
        labelAmount = new Label();
        
        tfAmount = new TextField();
        separator = new Separator();
        btn_buchen = new Button();
        labelOutgoings = new Label();
        outgoings = new ListView<String>();
        labelIncome = new Label();
        income = new ListView<String>();
        
        setPostions();
    }

    private void setPostions() {

        // vBoxTop
        labelAmount.setFont(fontLabel);
        labelAmount.setText(txtLabelAmount);

        tfAmount.setAlignment(Pos.CENTER);
        tfAmount.setPrefSize(100, 25);
        tfAmount.setMinSize(100, 25);
        tfAmount.setMaxSize(100, 25);
        
        VBox.setMargin(labelAmount, new Insets(20, 0, 0, 0));
        VBox.setMargin(tfAmount, new Insets(5,0,0,0));
        vBoxTop.setAlignment(Pos.CENTER);
        
        vBoxTop.getChildren().addAll(labelAmount, tfAmount);
        layout.setTop(vBoxTop);

        
        
        // Separator
        separator.setOrientation(Orientation.VERTICAL);
        separator.setMinSize(10, 300);
        separator.setPrefSize(10, 300);
        separator.setMaxSize(10, 300);
        vBoxCenter.getChildren().add(separator);
        vBoxCenter.setAlignment(Pos.CENTER);
        layout.setCenter(vBoxCenter);

        //vBoxLeft
        labelIncome.setFont(fontLabel);
        labelIncome.setText(txtLabelIncome);
        
        income.setMinSize(300, 420);
        //vBoxLeft.setBackground(new Background(new BackgroundFill(Color.AQUA,
        //        CornerRadii.EMPTY, Insets.EMPTY)));
        
        vBoxLeft.setAlignment(Pos.CENTER);
        VBox.setMargin(income, new Insets(0, 0, 0, 20));

        vBoxLeft.getChildren().addAll(labelIncome, income);
        layout.setLeft(vBoxLeft);

        
        // vBoxRight
        labelOutgoings.setFont(fontLabel);
        labelOutgoings.setText(txtLabelOutgoings);
        
        outgoings.setMinSize(300, 420);
        
        vBoxRight.setAlignment(Pos.CENTER);
        VBox.setMargin(outgoings, new Insets(0, 20, 0, 0));

        vBoxRight.getChildren().addAll(labelOutgoings, outgoings);
        layout.setRight(vBoxRight);

        
        // vBoxBottom
        btn_buchen.setFont(fontLabel);
        btn_buchen.setText(txtBtn_buchen);
        btn_buchen.setAlignment(Pos.CENTER);
        btn_buchen.setMinSize(120, 25);
        
        vBoxBottom.setAlignment(Pos.CENTER);
        VBox.setMargin(btn_buchen, new Insets(0,0,20,0));

        vBoxBottom.getChildren().add(btn_buchen);
        layout.setBottom(vBoxBottom);


    }

    public Scene getScene() {
        return scene;
    }


}


Ich habe eine ListView<String> erstellt, die in eine VBox reingepackt und die wiederum in die layout.setLeft (BorderPane) reingetan. Links und Rechts jeweils eine.
Wenn ich aber von der Stage die Fenstergröße ändere, also mit der Maus größer kleiner ziehe, passt sich die größe der ListVievs leider nicht an. Ich habe verschiedene Propertys probiert, mit ChangeListeners gearbeitet, alles leider ohne Erfolg. Nur mein Kopf rauch immer mehr.

Kann man das in dieser Konstellation überhaupt realsieren und wenn ja, am Besten wie? :))
 

lam_tr

Top Contributor
Vielleicht kannst du die ListView noch mit weitere settings machen.

Code:
ListView.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);

VBox.setVgrow(ListView, Priority.ALWAYS);

somit sollte an sich die Listview immer an der VBox ausdehnen.
 

BigMemo007

Aktives Mitglied
Vielen Dank. Hat super funtkioniert. In der Höhe ist es jetzt schon dynamisch. Aber in der Breite geht es nicht. Weder die VBox noch die ListViw haben eine setHgrow Methode. Gibt es dafür auch eine Möglichkeit?
 

BigMemo007

Aktives Mitglied
Kommst du mit control.setMaxWidth(Double.MAX_VALUE) nicht zum Ziel?

Leider nicht. Das Problem ist, dass beim ändern der Breite des Fensters, das borderPane.CENTER breiter oder schmaler wird, also sich anpasst.
Die LEFT und RIGHT, da sind meine ListViews jeweils drin, reagieren auf die Breitenveränderung nicht. Die reagieren auf die Höhenänderung.
Eine Möglichkeit der BorderLayout mitzuteilen, dass die Breite des CENTERs fest bleiben soll und die des LEFTs und RIGHTs dynamsich sein soll, würde das Problem lösten. Aber ich habe bis jetzt nichts gefunden.
 

lam_tr

Top Contributor
Leider nicht. Das Problem ist, dass beim ändern der Breite des Fensters, das borderPane.CENTER breiter oder schmaler wird, also sich anpasst.
Die LEFT und RIGHT, da sind meine ListViews jeweils drin, reagieren auf die Breitenveränderung nicht. Die reagieren auf die Höhenänderung.
Eine Möglichkeit der BorderLayout mitzuteilen, dass die Breite des CENTERs fest bleiben soll und die des LEFTs und RIGHTs dynamsich sein soll, würde das Problem lösten. Aber ich habe bis jetzt nichts gefunden.

Okay ich habe mir mal dein Code angeschaut, es ist echt ein komisches Verhalten, so habe ich das auch noch nicht gemacht. Wieso verpackst du nicht alle zwei listViews mit dem Separator in eine HBox und stellst sie in den Center von der BorderPane.

Das sollte auf jeden Fall funktionieren.
 

lam_tr

Top Contributor
Ich habe jetzt nicht alles nachgebaut sondern nur auf die ListView und Separator mich beschränkt. Hier das passende Snipptet dazu basierend auf deinen Code

Code:
import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class CreateGUIBooking extends Application {

    private Scene scene;

    public CreateGUIBooking() {
        BorderPane parent = new BorderPane();
        HBox hbox = new HBox(5);
        VBox vbox = createPane("Einnahmen");
        hbox.getChildren().add(vbox);

        Separator separator = new Separator();
        separator.setOrientation(Orientation.VERTICAL);
        hbox.getChildren().add(separator);
        hbox.getChildren().add(createPane("Ausgaben"));
        parent.setCenter(hbox);
        scene = new Scene(parent, 700, 600);
    }

    private VBox createPane(String name) {
        VBox vbox = new VBox(5);
        ListView<Object> listview = new ListView<>();
        VBox.setVgrow(listview, Priority.ALWAYS);
        Label label = new Label(name);
        label.setMaxWidth(Double.MAX_VALUE);
        label.setAlignment(Pos.CENTER);
        vbox.getChildren().add(label);
        vbox.getChildren().add(listview);
        HBox.setHgrow(vbox, Priority.ALWAYS);
        return vbox;
    }

    public Scene getScene() {
        return scene;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        CreateGUIBooking creator = new CreateGUIBooking();
        primaryStage.setScene(creator.getScene());
        primaryStage.show();
    }

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

}
 

BigMemo007

Aktives Mitglied
Vielen Dank an euch. Das mit dem dynamischen Anpassen an Fenstergröße vertikal sowie horizontal klappt jetzt super.

Nun möchte ich in den Bottom des BorderPanes 3 Buttons reinpacken. Eins soll ganz links, eins in der mitte und das dritte ganz rechts platziert werden. Ich möchte eigentlich auf Margin verzichten. Mit Position habe ich es leider nicht hinbekommen. Was mache ich falsch?

Java:
package gui;

import java.time.LocalDate;

import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

public class CreateGUIBooking {

    private Scene scene;
    private BorderPane layout;

    private VBox vBoxDate;
    private HBox hBoxTop;
    private HBox hBoxCenter;
    private VBox vBoxCenterRight;
    private VBox vBoxCenterLeft;
    private VBox vBoxCenterMiddle;
    private HBox hBoxBottom;
    
    private Font fontLabel;
    
    private DatePicker datePicker;
    private Label labelDate;
    
    private Label labelAmount;
    private MyNumTextField tfAmount;
    private Separator separator;
    private Button btnBooking;
    private Button btnAnalyseBookings;
    private Button btnEditBookings;
    private ListView<String> outgoings;
    private ListView<String> income;
    private Label labelOutgoings;
    private Label labelIncome;
    
    private String txtLabelAmount = "Betrag eingeben";
    private String txtLabelOutgoings = "Ausgaben";
    private String txtLabelIncome = "Einnahmen";
    private String txtBtn_buchen = "Buchen";
    private String txtLabelDate = "Tag der Buchung";
    
    public CreateGUIBooking() {
        layout = new BorderPane();
        scene = new Scene(layout, 700, 600);
        
        vBoxDate = new VBox();
        vBoxCenterMiddle = new VBox();
        hBoxTop = new HBox();
        hBoxCenter = new HBox();
        vBoxCenterLeft = new VBox();
        vBoxCenterRight = new VBox();
        hBoxBottom = new HBox();
        
        fontLabel = Font.font("sans-serif", FontWeight.BOLD, 15);
        labelDate = new Label();
        labelAmount = new Label();
        labelIncome = new Label();
        labelOutgoings = new Label();
        
        tfAmount = new MyNumTextField();
        datePicker = new DatePicker();
        separator = new Separator();
        
        outgoings = new ListView<String>();
        income = new ListView<String>();
        
        btnBooking = new Button();
        btnAnalyseBookings = new Button();
        btnEditBookings = new Button();
        
        setSettings();
        setPostions();
    }
    
    private void setSettings() {
        labelDate.setText(txtLabelDate);
        labelDate.setFont(fontLabel);
        labelAmount.setFont(fontLabel);
        labelAmount.setText(txtLabelAmount);
        labelIncome.setFont(fontLabel);
        labelIncome.setText(txtLabelIncome);
        labelOutgoings.setFont(fontLabel);
        labelOutgoings.setText(txtLabelOutgoings);
        
        btnBooking.setFont(fontLabel);
        btnBooking.setText(txtBtn_buchen);
        
        btnAnalyseBookings.setFont(fontLabel);
        btnAnalyseBookings.setText("Auswertung ansehen");
        btnEditBookings.setFont(fontLabel);
        btnEditBookings.setText("Buchungen editieren");
        
        datePicker.setShowWeekNumbers(true);
        datePicker.setValue(LocalDate.now());
        //datePicker.setEffect(new SepiaTone());
        
    }

    private void setPostions() {

        // setup BorderPane TOP       
        vBoxDate.setAlignment(Pos.CENTER);
        vBoxDate.getChildren().addAll(labelDate, datePicker);
        
        hBoxTop.setAlignment(Pos.CENTER);
        hBoxTop.getChildren().addAll(vBoxDate);
        layout.setTop(hBoxTop);

        
        // setup BorderPane CENTER
            // setup income
        VBox.setVgrow(income, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterLeft.setAlignment(Pos.CENTER);  //zentriert labelIncome
        VBox.setMargin(income, new Insets(0, 20, 20, 20));
        vBoxCenterLeft.getChildren().addAll(labelIncome, income);
        
            // setup outgoings
        VBox.setVgrow(outgoings, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterRight.setAlignment(Pos.CENTER);    //zentriert labelOutgoings
        VBox.setMargin(outgoings, new Insets(0, 20, 20, 20));
        vBoxCenterRight.getChildren().addAll(labelOutgoings, outgoings);
        

             //setup AmountField and Separator
        tfAmount.setMinSize(100, 25);
        tfAmount.setMaxSize(100, 25);
        tfAmount.setPadding(new Insets(5,0,0,10));
        
        separator.setOrientation(Orientation.VERTICAL);
        separator.setPadding(new Insets(30,0,50,0)); //Strich unten sieht schöner aus
        
        vBoxCenterMiddle.getChildren().addAll(labelAmount, tfAmount, separator);
        VBox.setMargin(labelAmount, new Insets(20,0,10,0));
        VBox.setVgrow(separator, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        VBox.setVgrow(vBoxCenterMiddle, Priority.ALWAYS); //und separator wird angezeigt
        vBoxCenterMiddle.setAlignment(Pos.CENTER);       
        
            // merge the nodes in CENTER
        HBox.setHgrow(vBoxCenterLeft, Priority.ALWAYS);
        HBox.setHgrow(vBoxCenterRight, Priority.ALWAYS);
        hBoxCenter.getChildren().addAll(vBoxCenterLeft, vBoxCenterMiddle, vBoxCenterRight);
        layout.setCenter(hBoxCenter);
        
        
  [B]      // setup BorderPane BOTTOM
        btnAnalyseBookings.setMinSize(150, 25);
        btnBooking.setMinSize(150, 25);
        btnEditBookings.setMinSize(150, 25);
        
        VBox vBoxEdit = new VBox();
        VBox vBoxBooking = new VBox();
        VBox vBoxAnalyse = new VBox();
        
        vBoxAnalyse.getChildren().add(btnAnalyseBookings);
        vBoxBooking.getChildren().add(btnBooking);
        vBoxEdit.getChildren().add(btnEditBookings);
        
        VBox.setMargin(btnBooking, new Insets(0, 50, 0, 50));
        BorderPane.setMargin(hBoxBottom, new Insets(0,0,20,0));
        hBoxBottom.setAlignment(Pos.CENTER);
        
        
        //btnAnalyseBookings.setMaxWidth(Double.MAX_VALUE);
        //btnBooking.setMaxWidth(Double.MAX_VALUE);
        //btnEditBookings.setMaxWidth(Double.MAX_VALUE);
        
        //BorderPane.setAlignment(vBoxEdit, Pos.CENTER_LEFT);
        //BorderPane.setAlignment(vBoxBooking, Pos.CENTER);
        //BorderPane.setAlignment(vBoxAnalyse, Pos.CENTER_RIGHT);
        
        //vBoxAnalyse.setAlignment(Pos.BASELINE_LEFT);
        //vBoxBooking.setAlignment(Pos.BASELINE_CENTER);
        //vBoxEdit.setAlignment(Pos.BASELINE_RIGHT);
        
        
        //hBoxBottom.getChildren().addAll(btnAnalyseBookings, btnBooking, btnEditBookings);
        hBoxBottom.getChildren().addAll(vBoxEdit, vBoxBooking, vBoxAnalyse);
        layout.setBottom(hBoxBottom);[/B]

    }

    public Scene getScene() {
        return scene;
    }


}
 

BigMemo007

Aktives Mitglied
Java:
// setup BorderPane BOTTOM
        btnAnalyseBookings.setMinSize(150, 25);
        btnBooking.setMinSize(150, 25);
        btnEditBookings.setMinSize(150, 25);
        

        BorderPane.setMargin(hBoxBottom, new Insets(20,20,20,20));

        Label l1 = new Label();
        l1.setMinWidth(20);
        l1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l1, Priority.ALWAYS);
        
        Label l2 = new Label();
        l2.setMinWidth(20);
        l2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l2, Priority.ALWAYS);
        
        hBoxBottom.getChildren().addAll(btnAnalyseBookings, l1, btnBooking, l2, btnEditBookings);
        layout.setBottom(hBoxBottom);
    

    }

Mit diesem Code gehts. :))

Schade, dass die BorderPane und die HBox nicht mit Positions das auch lösen können. Habe 2 Stunden meines Lebens verschwendet :(. AnchoPane war auch keine Hilfe.
 

BigMemo007

Aktives Mitglied
Vielen Dank schonmal für eure Hilfen. Ich habe folgenden Code zusammengestellt. Er sieht schrecklich aus, finde ich. Wie kann ich besser aufräumen? Soll ich eine Klasse erstellen, die mir die gewünschten und dort formatierten ListViews gibt? Oder wie schreibt man denn übersichtlierech Code?

Java:
package gui;

import java.time.LocalDate;

import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

public class CreateGUIBooking {

    private Scene scene;
    private BorderPane layout;

    private VBox vBoxDate;
    private HBox hBoxTop;
    private HBox hBoxCenter;
    private VBox vBoxCenterRight;
    private VBox vBoxCenterLeft;
    private VBox vBoxCenterMiddle;
    private HBox hBoxBottom;
    
    private Font font1;
    private Font font2;
    
    private Label labelOutgoings;
    private Label labelIncome;
    private Label labelDate;
    private Label labelAmount;
    
    private DatePicker datePicker;
    private MyNumTextField tfAmount;
    private Separator separator;
    private ListView<String> outgoings;
    private ListView<String> income;
    
    private Button btnBooking;
    private Button btnAnalyseBookings;
    private Button btnEditBookings;
    private Button btnAddIncome;
    private Button btnRemoveIncome;
    private Button btnAddOutgoing;
    private Button btnRemoveOutgoing;
    
    private String txtLabelAmount = "Betrag eingeben";
    private String txtLabelOutgoings = "Ausgaben";
    private String txtLabelIncome = "Einnahmen";
    private String txtBtn_buchen = "Buchen";
    private String txtLabelDate = "Tag der Buchung";
    
    public CreateGUIBooking() {
        layout = new BorderPane();
        scene = new Scene(layout, 800, 600);
        
        vBoxDate = new VBox();
        vBoxCenterMiddle = new VBox();
        hBoxTop = new HBox();
        hBoxCenter = new HBox();
        vBoxCenterLeft = new VBox();
        vBoxCenterRight = new VBox();
        hBoxBottom = new HBox();
        
        font1 = Font.font("sans-serif", FontWeight.BOLD, 15);
        font2 = Font.font("sans-serif", FontWeight.BOLD, 12);
        
        labelDate = new Label();
        labelAmount = new Label();
        labelIncome = new Label();
        labelOutgoings = new Label();
        
        tfAmount = new MyNumTextField();
        datePicker = new DatePicker();
        separator = new Separator();
        
        outgoings = new ListView<String>();
        income = new ListView<String>();
        
        btnBooking = new Button();
        btnAnalyseBookings = new Button();
        btnEditBookings = new Button();
        btnAddIncome = new Button();
        btnAddOutgoing = new Button();
        btnRemoveIncome = new Button();
        btnRemoveOutgoing = new Button();
        
        setSettings();
        setPostions();
    }
    
    private void setSettings() {
        labelDate.setText(txtLabelDate);
        labelDate.setFont(font1);
        labelAmount.setFont(font1);
        labelAmount.setText(txtLabelAmount);
        labelIncome.setFont(font1);
        labelIncome.setText(txtLabelIncome);
        labelOutgoings.setFont(font1);
        labelOutgoings.setText(txtLabelOutgoings);
        
        btnBooking.setFont(font1);
        btnBooking.setText(txtBtn_buchen);
        
        btnAddIncome.setFont(font2);
        btnAddIncome.setText("+");
        btnAddOutgoing.setFont(font2);
        btnAddOutgoing.setText("+");
        btnRemoveIncome.setFont(font2);
        btnRemoveIncome.setText("-");
        btnRemoveOutgoing.setFont(font2);
        btnRemoveOutgoing.setText("-");
        btnAnalyseBookings.setFont(font2);
        btnAnalyseBookings.setText("Auswertung ansehen");
        btnEditBookings.setFont(font2);
        btnEditBookings.setText("Buchungen editieren");
        
        datePicker.setShowWeekNumbers(true);
        datePicker.setValue(LocalDate.now());
        //datePicker.setEffect(new SepiaTone());
        
    }

    private void setPostions() {

        // setup BorderPane TOP       
        vBoxDate.setAlignment(Pos.CENTER);
        vBoxDate.getChildren().addAll(labelDate, datePicker);
        
        hBoxTop.setAlignment(Pos.CENTER);
        BorderPane.setMargin(hBoxTop, new Insets(10,0,10,0));
        hBoxTop.getChildren().addAll(vBoxDate);
        layout.setTop(hBoxTop);

        
        // setup BorderPane CENTER
            // setup income
        HBox hBoxIncome = new HBox();
        HBox.setMargin(btnRemoveIncome, new Insets(0, 20, 5, 30));
        HBox.setMargin(btnAddIncome, new Insets(0, 30, 5, 0));
        
        Label spaceLabelIncome1 = new Label();
        spaceLabelIncome1.setMinWidth(20);
        spaceLabelIncome1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelIncome1, Priority.ALWAYS);

        Label spaceLabelIncome2 = new Label();
        spaceLabelIncome2.setMinWidth(20);
        spaceLabelIncome2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelIncome2, Priority.ALWAYS);

        hBoxIncome.getChildren().addAll(btnRemoveIncome, spaceLabelIncome1, labelIncome,
                spaceLabelIncome2, btnAddIncome);
            
        VBox.setVgrow(income, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterLeft.setAlignment(Pos.CENTER);  //zentriert labelIncome
        VBox.setMargin(income, new Insets(0, 20, 0, 20));
        vBoxCenterLeft.getChildren().addAll(hBoxIncome, income);
        
            // setup outgoings
        HBox hBoxOutgoing = new HBox();
        HBox.setMargin(btnRemoveOutgoing, new Insets(0, 20, 5, 30));
        HBox.setMargin(btnAddOutgoing, new Insets(0, 30, 5, 0));
        
        Label spaceLabelOutgoing1 = new Label();
        spaceLabelOutgoing1.setMinWidth(20);
        spaceLabelOutgoing1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelOutgoing1, Priority.ALWAYS);

        Label spaceLabelOutgoing2 = new Label();
        spaceLabelOutgoing2.setMinWidth(20);
        spaceLabelOutgoing2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelOutgoing2, Priority.ALWAYS);

        hBoxOutgoing.getChildren().addAll(btnRemoveOutgoing, spaceLabelOutgoing1, labelOutgoings,
                spaceLabelOutgoing2, btnAddOutgoing);
        
        
        VBox.setVgrow(outgoings, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterRight.setAlignment(Pos.CENTER);    //zentriert labelOutgoings
        VBox.setMargin(outgoings, new Insets(0, 20, 0, 20));
        vBoxCenterRight.getChildren().addAll(hBoxOutgoing, outgoings);
        

             //setup AmountField and Separator
        tfAmount.setMinSize(100, 25);
        tfAmount.setMaxSize(100, 25);
        
        separator.setOrientation(Orientation.VERTICAL);
        separator.setPadding(new Insets(30,0,50,0)); //Strich unten sieht schöner aus
        
        vBoxCenterMiddle.getChildren().addAll(labelAmount, tfAmount, separator);
        VBox.setMargin(labelAmount, new Insets(20,0,5,0));
        VBox.setVgrow(separator, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        VBox.setVgrow(vBoxCenterMiddle, Priority.ALWAYS); //und separator wird angezeigt
        vBoxCenterMiddle.setAlignment(Pos.CENTER);       
        
            // merge the nodes in CENTER
        HBox.setHgrow(vBoxCenterLeft, Priority.ALWAYS);
        HBox.setHgrow(vBoxCenterRight, Priority.ALWAYS);
        hBoxCenter.getChildren().addAll(vBoxCenterLeft, vBoxCenterMiddle, vBoxCenterRight);
        layout.setCenter(hBoxCenter);
        
        
        // setup BorderPane BOTTOM
        btnAnalyseBookings.setMinSize(150, 25);
        btnBooking.setMinSize(150, 25);
        btnEditBookings.setMinSize(150, 25);
        

        BorderPane.setMargin(hBoxBottom, new Insets(20,20,20,20));

        Label l1 = new Label();
        l1.setMinWidth(20);
        l1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l1, Priority.ALWAYS);
        
        Label l2 = new Label();
        l2.setMinWidth(20);
        l2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l2, Priority.ALWAYS);
        
        hBoxBottom.getChildren().addAll(btnAnalyseBookings, l1, btnBooking, l2, btnEditBookings);
        layout.setBottom(hBoxBottom);
    

    }

    public Scene getScene() {
        return scene;
    }


}


Allein für diese Gui habe ich 2 Tage gebraucht. Ist das normal beim Programmieren? Wenn es an die Logik geht, werde ich wahrscheinlich 2 Jahre brauchen.
 

lam_tr

Top Contributor
Vielen Dank schonmal für eure Hilfen. Ich habe folgenden Code zusammengestellt. Er sieht schrecklich aus, finde ich. Wie kann ich besser aufräumen? Soll ich eine Klasse erstellen, die mir die gewünschten und dort formatierten ListViews gibt? Oder wie schreibt man denn übersichtlierech Code?

Java:
package gui;

import java.time.LocalDate;

import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

public class CreateGUIBooking {

    private Scene scene;
    private BorderPane layout;

    private VBox vBoxDate;
    private HBox hBoxTop;
    private HBox hBoxCenter;
    private VBox vBoxCenterRight;
    private VBox vBoxCenterLeft;
    private VBox vBoxCenterMiddle;
    private HBox hBoxBottom;
   
    private Font font1;
    private Font font2;
   
    private Label labelOutgoings;
    private Label labelIncome;
    private Label labelDate;
    private Label labelAmount;
   
    private DatePicker datePicker;
    private MyNumTextField tfAmount;
    private Separator separator;
    private ListView<String> outgoings;
    private ListView<String> income;
   
    private Button btnBooking;
    private Button btnAnalyseBookings;
    private Button btnEditBookings;
    private Button btnAddIncome;
    private Button btnRemoveIncome;
    private Button btnAddOutgoing;
    private Button btnRemoveOutgoing;
   
    private String txtLabelAmount = "Betrag eingeben";
    private String txtLabelOutgoings = "Ausgaben";
    private String txtLabelIncome = "Einnahmen";
    private String txtBtn_buchen = "Buchen";
    private String txtLabelDate = "Tag der Buchung";
   
    public CreateGUIBooking() {
        layout = new BorderPane();
        scene = new Scene(layout, 800, 600);
       
        vBoxDate = new VBox();
        vBoxCenterMiddle = new VBox();
        hBoxTop = new HBox();
        hBoxCenter = new HBox();
        vBoxCenterLeft = new VBox();
        vBoxCenterRight = new VBox();
        hBoxBottom = new HBox();
       
        font1 = Font.font("sans-serif", FontWeight.BOLD, 15);
        font2 = Font.font("sans-serif", FontWeight.BOLD, 12);
       
        labelDate = new Label();
        labelAmount = new Label();
        labelIncome = new Label();
        labelOutgoings = new Label();
       
        tfAmount = new MyNumTextField();
        datePicker = new DatePicker();
        separator = new Separator();
       
        outgoings = new ListView<String>();
        income = new ListView<String>();
       
        btnBooking = new Button();
        btnAnalyseBookings = new Button();
        btnEditBookings = new Button();
        btnAddIncome = new Button();
        btnAddOutgoing = new Button();
        btnRemoveIncome = new Button();
        btnRemoveOutgoing = new Button();
       
        setSettings();
        setPostions();
    }
   
    private void setSettings() {
        labelDate.setText(txtLabelDate);
        labelDate.setFont(font1);
        labelAmount.setFont(font1);
        labelAmount.setText(txtLabelAmount);
        labelIncome.setFont(font1);
        labelIncome.setText(txtLabelIncome);
        labelOutgoings.setFont(font1);
        labelOutgoings.setText(txtLabelOutgoings);
       
        btnBooking.setFont(font1);
        btnBooking.setText(txtBtn_buchen);
       
        btnAddIncome.setFont(font2);
        btnAddIncome.setText("+");
        btnAddOutgoing.setFont(font2);
        btnAddOutgoing.setText("+");
        btnRemoveIncome.setFont(font2);
        btnRemoveIncome.setText("-");
        btnRemoveOutgoing.setFont(font2);
        btnRemoveOutgoing.setText("-");
        btnAnalyseBookings.setFont(font2);
        btnAnalyseBookings.setText("Auswertung ansehen");
        btnEditBookings.setFont(font2);
        btnEditBookings.setText("Buchungen editieren");
       
        datePicker.setShowWeekNumbers(true);
        datePicker.setValue(LocalDate.now());
        //datePicker.setEffect(new SepiaTone());
       
    }

    private void setPostions() {

        // setup BorderPane TOP      
        vBoxDate.setAlignment(Pos.CENTER);
        vBoxDate.getChildren().addAll(labelDate, datePicker);
       
        hBoxTop.setAlignment(Pos.CENTER);
        BorderPane.setMargin(hBoxTop, new Insets(10,0,10,0));
        hBoxTop.getChildren().addAll(vBoxDate);
        layout.setTop(hBoxTop);

       
        // setup BorderPane CENTER
            // setup income
        HBox hBoxIncome = new HBox();
        HBox.setMargin(btnRemoveIncome, new Insets(0, 20, 5, 30));
        HBox.setMargin(btnAddIncome, new Insets(0, 30, 5, 0));
       
        Label spaceLabelIncome1 = new Label();
        spaceLabelIncome1.setMinWidth(20);
        spaceLabelIncome1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelIncome1, Priority.ALWAYS);

        Label spaceLabelIncome2 = new Label();
        spaceLabelIncome2.setMinWidth(20);
        spaceLabelIncome2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelIncome2, Priority.ALWAYS);

        hBoxIncome.getChildren().addAll(btnRemoveIncome, spaceLabelIncome1, labelIncome,
                spaceLabelIncome2, btnAddIncome);
           
        VBox.setVgrow(income, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterLeft.setAlignment(Pos.CENTER);  //zentriert labelIncome
        VBox.setMargin(income, new Insets(0, 20, 0, 20));
        vBoxCenterLeft.getChildren().addAll(hBoxIncome, income);
       
            // setup outgoings
        HBox hBoxOutgoing = new HBox();
        HBox.setMargin(btnRemoveOutgoing, new Insets(0, 20, 5, 30));
        HBox.setMargin(btnAddOutgoing, new Insets(0, 30, 5, 0));
       
        Label spaceLabelOutgoing1 = new Label();
        spaceLabelOutgoing1.setMinWidth(20);
        spaceLabelOutgoing1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelOutgoing1, Priority.ALWAYS);

        Label spaceLabelOutgoing2 = new Label();
        spaceLabelOutgoing2.setMinWidth(20);
        spaceLabelOutgoing2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(spaceLabelOutgoing2, Priority.ALWAYS);

        hBoxOutgoing.getChildren().addAll(btnRemoveOutgoing, spaceLabelOutgoing1, labelOutgoings,
                spaceLabelOutgoing2, btnAddOutgoing);
       
       
        VBox.setVgrow(outgoings, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        vBoxCenterRight.setAlignment(Pos.CENTER);    //zentriert labelOutgoings
        VBox.setMargin(outgoings, new Insets(0, 20, 0, 20));
        vBoxCenterRight.getChildren().addAll(hBoxOutgoing, outgoings);
       

             //setup AmountField and Separator
        tfAmount.setMinSize(100, 25);
        tfAmount.setMaxSize(100, 25);
       
        separator.setOrientation(Orientation.VERTICAL);
        separator.setPadding(new Insets(30,0,50,0)); //Strich unten sieht schöner aus
       
        vBoxCenterMiddle.getChildren().addAll(labelAmount, tfAmount, separator);
        VBox.setMargin(labelAmount, new Insets(20,0,5,0));
        VBox.setVgrow(separator, Priority.ALWAYS); //passt vertikal an Fenstergröße an
        VBox.setVgrow(vBoxCenterMiddle, Priority.ALWAYS); //und separator wird angezeigt
        vBoxCenterMiddle.setAlignment(Pos.CENTER);      
       
            // merge the nodes in CENTER
        HBox.setHgrow(vBoxCenterLeft, Priority.ALWAYS);
        HBox.setHgrow(vBoxCenterRight, Priority.ALWAYS);
        hBoxCenter.getChildren().addAll(vBoxCenterLeft, vBoxCenterMiddle, vBoxCenterRight);
        layout.setCenter(hBoxCenter);
       
       
        // setup BorderPane BOTTOM
        btnAnalyseBookings.setMinSize(150, 25);
        btnBooking.setMinSize(150, 25);
        btnEditBookings.setMinSize(150, 25);
       

        BorderPane.setMargin(hBoxBottom, new Insets(20,20,20,20));

        Label l1 = new Label();
        l1.setMinWidth(20);
        l1.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l1, Priority.ALWAYS);
       
        Label l2 = new Label();
        l2.setMinWidth(20);
        l2.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l2, Priority.ALWAYS);
       
        hBoxBottom.getChildren().addAll(btnAnalyseBookings, l1, btnBooking, l2, btnEditBookings);
        layout.setBottom(hBoxBottom);
   

    }

    public Scene getScene() {
        return scene;
    }


}


Allein für diese Gui habe ich 2 Tage gebraucht. Ist das normal beim Programmieren? Wenn es an die Logik geht, werde ich wahrscheinlich 2 Jahre brauchen.

Ich finde komplexe UIs sollte man lieber in FXML machen, da hat man wenigsten noch eine Übersicht. Aber das ist Geschmackssache. Mit FXML bin ich in der Regel viel schnell dran als wenn ich alles programmatisch hinklatsche. Außerdem wird mir die Kontroller Klasse auch generiert was sehr praktisch ist.

Ich denke es ist normal wenn du mehr Zeit zum programmieren brauchst, wenn ich auf ein Problem stoße dann muss es zuerst gelöst werden, was wiederum Zeit braucht.
 

BigMemo007

Aktives Mitglied
Ich habe versucht meinen Code aufzuräumen und in Klassen unterteilt. Ich würde mich sehr freuen, wenn ihr Profis drüber schaut und mir Tipps gibt, wie ich es besser machen kann. FXML habe ich nicht so viel die Ahnung, aber ich will erstmal die Pike besser verstehen. Dann gehe ich in FXML über.
Würden Profis ohne FXML diese GUI auch so ähnlich schreiben, oder gibt es bessere Metholden? Über jeden Feedback und Tipp freue ich mich sehr.

Java:
package application;

import guiBooking.CreateGUIBooking;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Start extends Application {

    CreateGUIBooking guiBooking;
    Scene sceneGUIBooking;

    public Start() {
        guiBooking = new CreateGUIBooking();
        sceneGUIBooking = guiBooking.getScene();

    }

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

    }

    @Override
    public void start(Stage stage) throws Exception {

        stage.setScene(sceneGUIBooking);
        stage.setTitle("Einnahmen-Ausgaben APP");
        stage.show();

    }

}

Java:
package objects;

import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

public class Var {

    public static final Font fontBig = Font.font("sans-serif", FontWeight.BOLD, 15);
    public static final Font fontSmall = Font.font("sans-serif", FontWeight.BOLD, 12);
    public static final Font fontExtraBig = Font.font("sans-serif", FontWeight.BOLD, 18);

    public static final Label mySpace() {
        Label l = new Label();
        l.setMinWidth(20);
        l.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l, Priority.ALWAYS);

        return l;

    }

}// end class

Java:
package guiBooking;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import objects.Var;

public class BPTop {

    private Label labelDate;
    private DatePicker datePicker;

    private String txtLabelDate = "Tag der Buchung";

    private VBox vBox;

    public BPTop() {

        labelDate = new Label(txtLabelDate);
        labelDate.setFont(Var.fontBig);
        datePicker = new DatePicker();

        vBox = new VBox();

        createVBox();
    }

    // datepicker and its labeling
    private void createVBox() {
        vBox.setAlignment(Pos.BASELINE_CENTER);
        BorderPane.setMargin(vBox, new Insets(5, 0, 25, 0));

        vBox.getChildren().addAll(labelDate, datePicker);

    }

    public VBox getvBox() {
        return vBox;
    }

}// end class

Java:
package guiBooking;

import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import objects.Var;

public class BPBottom {

    private final Button btnAnalyseBookings;
    private final Button btnBooking;
    private final Button btnEditBookings;

    private final String txtBtnAnalyseBookings = "Auswertung ansehen";
    private final String txtBtnBooking = "Buchen";
    private final String txtBtnEditBookings = "Buchungen editieren";

    HBox hbox;

    public BPBottom() {

        btnAnalyseBookings = new Button(txtBtnAnalyseBookings);
        btnBooking = new Button(txtBtnBooking);
        btnEditBookings = new Button(txtBtnEditBookings);

        btnAnalyseBookings.setFont(Var.fontSmall);
        btnBooking.setFont(Var.fontExtraBig);
        btnEditBookings.setFont(Var.fontSmall);

        btnAnalyseBookings.setMinSize(150, 25);
        btnBooking.setMinSize(150, 25);
        btnEditBookings.setMinSize(150, 25);

        hbox = new HBox();

        createHBox();

    }

    public void createHBox() {
        BorderPane.setMargin(hbox, new Insets(0, 20, 10, 20));

        hbox.getChildren().addAll(btnAnalyseBookings, Var.mySpace(), btnBooking, Var.mySpace(), btnEditBookings);
    }

    public HBox getHbox() {
        return hbox;
    }

}// end class

Java:
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;

public class MyItemList {

    private String listID;
    private String labelTxt;
    private String addButtonTxt;
    private String remButtonTxt;
    private ListView<String> listView;

    // includes remButton, label and addButton
    private HBox hBox;

    // includes hBox and listView and is to return
    private VBox vBox;

    public MyItemList(String labelTxt, String addButtonTxt, String remButtonTxt) {
        super();

        this.labelTxt = labelTxt;
        this.addButtonTxt = addButtonTxt;
        this.remButtonTxt = remButtonTxt;

        listView = new ListView<String>();
        listView.setId(listID);

        createHBox();
        createVbox();

    }

    // for the Buttons to add or remove items and the label of list
    private void createHBox() {
        hBox = new HBox();
        Label label = new Label(labelTxt);
        Button addBtn = new Button(addButtonTxt);
        Button remBtn = new Button(remButtonTxt);

        label.setFont(Var.fontBig);
        addBtn.setFont(Var.fontSmall);
        remBtn.setFont(Var.fontSmall);

        hBox.getChildren().addAll(remBtn, Var.mySpace(), label, Var.mySpace(), addBtn);

    }

    // contains hBox and listview and adjusting placing
    private void createVbox() {

        vBox = new VBox();
        vBox.getChildren().addAll(hBox, listView);

        HBox.setHgrow(vBox, Priority.ALWAYS);
        VBox.setVgrow(listView, Priority.ALWAYS);

        VBox.setMargin(hBox, new Insets(0, 10, 2, 10));
        vBox.setPadding(new Insets(10));

    }

    public VBox getListViewAsVBox() {
        return vBox;
    }

}// class

Java:
package guiBooking;

import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import objects.MyNumTextField;
import objects.Var;

public class BPCenterMiddle {

    private Separator sep;
    private Label labelAmount;
    private MyNumTextField tfAmount;

    private final String txtLabelAmount = "Betrag eingeben";

    private VBox vBox;

    public BPCenterMiddle() {
        sep = new Separator();
        labelAmount = new Label(txtLabelAmount);
        tfAmount = new MyNumTextField();
        vBox = new VBox();

        createVBox();
    }

    // for amountfield and its labeling
    private void createVBox() {

        labelAmount.setFont(Var.fontExtraBig);

        tfAmount.setMinSize(110, 28);
        tfAmount.setMaxSize(110, 28);

        sep.setOrientation(Orientation.VERTICAL);
        VBox.setVgrow(sep, Priority.ALWAYS);
        sep.setPadding(new Insets(30, 0, 50, 0)); // Strich unten sieht schöner aus

        vBox.setAlignment(Pos.BASELINE_CENTER);
        VBox.setVgrow(vBox, Priority.ALWAYS);
        vBox.getChildren().addAll(labelAmount, tfAmount, sep);

    }

    public VBox getvBox() {
        return vBox;
    }

}// end class

Java:
package guiBooking;

import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import objects.MyItemList;


public class CreateGUIBooking {

    private Scene scene;
    private BorderPane layout;

    MyItemList itemListIncome; // Einnahmen-Liste
    MyItemList itemListOutgoing; // Ausgaben-Liste
    BPTop bpTop;
    BPCenterMiddle bpCenterMiddle;
    BPBottom bpBottom;

    public CreateGUIBooking() {
        layout = new BorderPane();
        scene = new Scene(layout, 800, 600);

        itemListIncome = new MyItemList("Einnahmen", "+", "-");
        itemListOutgoing = new MyItemList("Ausgaben", "+", "-");

        bpTop = new BPTop();
        bpCenterMiddle = new BPCenterMiddle();
        bpBottom = new BPBottom();

        setPostions();
    }

    private void setPostions() {

        // setup BorderPane TOP
        layout.setTop(bpTop.getvBox());

        // setup BorderPaneCenter
        VBox vBoxincome = itemListIncome.getListViewAsVBox();
        VBox vBoxOutgoing = itemListOutgoing.getListViewAsVBox();

        BPCenterMiddle borderCenter = new BPCenterMiddle();
        VBox vBoxCenter = borderCenter.getvBox();

        HBox hBoxCenter = new HBox();
        hBoxCenter.getChildren().addAll(vBoxincome, vBoxCenter, vBoxOutgoing);

        layout.setCenter(hBoxCenter);

        // setup BorderPane BOTTOM
        layout.setBottom(bpBottom.getHbox());

    }

    public Scene getScene() {
        return scene;
    }

}// end class


Wie gesagt, ich bin für alles dankbar :))
 

dzim

Top Contributor
Würde sagen: Grundsätzlich OK.
Kompliziert wird es jetzt nur mit der GUI-Logik. So wie du es aufgebaut hast, wirst du vermutlich später (erst einmal) viel Logik in die Klassen der, was eher schlecht ist. Beschäftige dich daher als nächstes mal mit Konzepten wie MVC (ist einfacher, reicht mir aber häufig) oder MVVN (ist sauberer und besser zu testen!). Damit dir nicht erst schlechte Angewohnheiten zu eigen werden.
Ich habe am Anfang (wo ich aber schon recht gut mit Java zurecht kam und AWT/Swing und SWT/JFace kannte) erst einmal *alle* GUIs mit FXML gebaut. Ich fand es tatsächlich dort leichter alle Komponenten kennen zu lernen und die deklarative Strukturierung eines XMLs hat mir da sehr geholfen. Im Code hatte ich gerade mit den Grössen und den Positionierungen tatsächlich anfangs auch grössere Probleme. Und IntelliJ hat (jedenfalls in der Ultimate Edition) recht gute Java/JavaFX-Unterstützung für FXMLs.
Erst jetzt, wo ich fast alles mit Kotlin mache, bin ich wieder zurück auf einen Code-First-Ansatz und verwende kaum noch FXMLs.
 

BigMemo007

Aktives Mitglied
@dzim
danke für deine Antwort. Ich habe meinen Code meiner Meinung nach verbessert. Sieh unten. Werde aber mir MVC und MVVN näher anschauen.

Main-Klasse
Java:
public class RunEinnAusgApp extends Application {
    
    Scene sceneGUIBooking;
    GUIBooking guiBooking;
    
    String titleApp = "Einnahmen-Ausgaben APP";
    
    public RunEinnAusgApp() {
        guiBooking = new GUIBooking();
        sceneGUIBooking = guiBooking.getSceneGUIBooking();
    }
    
    
    @Override
    public void start(Stage primaryStage) {
        try {
            
            sceneGUIBooking.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(sceneGUIBooking);
            primaryStage.setTitle(titleApp);
            primaryStage.show();
            
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Meine Objekte werden hier kreiert:
Java:
public class MyObjects {

    private MyActionHandler myActionHandler;
    
    private DatePicker datePicker;
    private MyNumTextField amountField;
    
    private ListView<String> incomeListView;
    private ListView<String> outgoingsListView;
    
    private Separator separator;
    
    private Label lblDatePicker;
    private Label lblAmountField;
    private Label lblIncome;
    private Label lblOutgoings;
    
    private Button btnRemItemIncome;
    private Button btnAddItemIncome;
    private Button btnRemItemOutgoings;
    private Button btnAddItemOutgoings;
    
    private Button btnAnalyse;
    private Button btnBooking;
    private Button btnEdit;
    
    private int btnWidth;
    private int btnHeight;
    
    private String txtLabDatePicker = "Tag der Buchung";
    private String txtLabAmountField = "Betrag eingeben";
    private String txtLabIncome = "Einnahmen";
    private String txtLabOutgoings = "Ausgaben";
    
    private String txtBtnRemItemIncome = "-";
    private String txtBtnAddItemIncome = "+";
    private String txtBtnRemItemOutgoings = "-";
    private String txtBtnAddItemOutgoings = "+";
    
    private String txtBtnAnalyse = "Auswertung ansehen";
    private String txtBtnBooking = "Buchen";
    private String txtBtnEdit = "Buchungen editiren";
    

    public MyObjects() {
        myActionHandler = new MyActionHandler();
        
        datePicker = new DatePicker();
        amountField = new MyNumTextField();
        
        incomeListView = new ListView<String>();
        outgoingsListView = new ListView<String>();
        
        separator = new Separator();
        
        btnWidth = 100;
        btnHeight = 25;
        
        lblDatePicker = new Label(txtLabDatePicker);
        lblAmountField = new Label(txtLabAmountField);
        lblIncome = new Label(txtLabIncome);
        lblOutgoings = new Label(txtLabOutgoings);
        
        btnRemItemIncome = new Button(txtBtnRemItemIncome);
        btnAddItemIncome = new Button(txtBtnAddItemIncome);
        btnRemItemOutgoings = new Button(txtBtnRemItemOutgoings);
        btnAddItemOutgoings = new Button(txtBtnAddItemOutgoings);
        
        btnAnalyse = new Button(txtBtnAnalyse);
        btnBooking = new Button(txtBtnBooking);
        btnEdit = new Button(txtBtnEdit);
        
        
        setSettings();
        
    }//end construktor

    
    private void setSettings() {
        //datePicker-Settings
        
        
        //amountField-Settings
        amountField.setMinSize(50, 28);
        amountField.setPrefSize(128, 28);
        amountField.setMaxSize(128, 28);
        amountField.setAlignment(Pos.CENTER); //zentriert Cursor
        amountField.setFont(Var.fontBig);
        
        //LiswView-Settings
        VBox.setVgrow(incomeListView, Priority.ALWAYS);     //lässt income VERTIKAL wachsen
        VBox.setVgrow(outgoingsListView, Priority.ALWAYS);  //lässt outgoing VERTIKAL wachsen
        
        //Separator-Settings
        VBox.setMargin(separator,new Insets(30, 0, 50, 0)); //verkleinert Separator
        separator.setOrientation(Orientation.VERTICAL); //setzt Strich Vertikal
        VBox.setVgrow(separator, Priority.ALWAYS);      //Separator wächst VERTIKAL mit
        
    
        //Label-Settings (Fonts)
        lblDatePicker.setFont(Var.fontBig);
        lblAmountField.setFont(Var.fontExtraBig);
        lblIncome.setFont(Var.fontBig);
        lblOutgoings.setFont(Var.fontBig);
        
        //Button-Settings (Fonts, addActionListener)
        HBox.setMargin(btnRemItemIncome, new Insets(0, 30, 0, 0)); //Abstand zum Label lblIncome links
        btnRemItemIncome.setFont(Var.fontSmall);
        btnRemItemIncome.setOnAction(myActionHandler);
        HBox.setMargin(btnAddItemIncome, new Insets(0, 0, 0, 30)); //Abstand zum Label lblIncome rechts
        btnAddItemIncome.setFont(Var.fontSmall);
        btnAddItemIncome.setOnAction(myActionHandler);
        
        HBox.setMargin(btnRemItemOutgoings, new Insets(0, 30, 0, 0)); //Abstand zum Lable lblOutgoings links
        btnRemItemOutgoings.setFont(Var.fontSmall);
        btnRemItemOutgoings.setOnAction(myActionHandler);
        HBox.setMargin(btnAddItemOutgoings, new Insets(0, 0, 0, 30)); //Abstand zum Lable lblOutgoings rechts
        btnAddItemOutgoings.setFont(Var.fontSmall);
        btnAddItemOutgoings.setOnAction(myActionHandler);
        
        btnAnalyse.setMinSize(btnWidth, btnHeight);
        btnAnalyse.setFont(Var.fontSmall);
        btnAnalyse.setOnAction(myActionHandler);
        btnBooking.setMinSize(btnWidth, btnHeight);
        btnBooking.setFont(Var.fontExtraBig);
        btnBooking.setOnAction(myActionHandler);
        btnEdit.setMinSize(btnWidth, btnHeight);
        btnEdit.setFont(Var.fontSmall);
        btnEdit.setOnAction(myActionHandler);
        
    }
    

    public ListView<String> getIncomeListView() {
        return incomeListView;
    }



    public void setIncomeListView(ListView<String> incomeLV) {
        this.incomeListView = incomeLV;
    }



    public ListView<String> getOutgoingsListView() {
        return outgoingsListView;
    }



    public void setOutgoingsListView(ListView<String> outgoingsLV) {
        this.outgoingsListView = outgoingsLV;
    }



    public DatePicker getDatePicker() {
        return datePicker;
    }



    public MyNumTextField getAmountField() {
        return amountField;
    }



    public Label getLblDatePicker() {
        return lblDatePicker;
    }


    public Label getLblAmountField() {
        return lblAmountField;
    }
    

    public Label getLblIncome() {
        return lblIncome;
    }



    public Label getLblOutgoings() {
        return lblOutgoings;
    }



    public Button getBtnRemItemIncome() {
        return btnRemItemIncome;
    }



    public Button getBtnAddItemIncome() {
        return btnAddItemIncome;
    }



    public Button getBtnRemItemOutgoings() {
        return btnRemItemOutgoings;
    }



    public Button getBtnAddItemOutgoings() {
        return btnAddItemOutgoings;
    }



    public Button getBtnAnalyse() {
        return btnAnalyse;
    }



    public Button getBtnBooking() {
        return btnBooking;
    }



    public Button getBtnEdit() {
        return btnEdit;
    }


    public Separator getSeparator() {
        return separator;
    }

}//end class


Die Gui für Bookings wird hier gemacht
Java:
public class GUIBooking {
    
    private BorderPane layout;
    private Scene sceneGUIBooking;
    
    private static MyObjects myObjects;
    
    private VBox vBoxTop;
    private HBox hBoxCenLeftTop;
    private VBox vBoxCenterLeft;
    private HBox hBoxCenRightTop;
    private VBox vBoxCenterRight;
    private VBox vBoxCenterMiddle;
    private HBox hBoxCenter;
    private HBox hBoxBottom;
    
    
    public GUIBooking() {
        layout = new BorderPane();
        sceneGUIBooking = new Scene(layout, 800, 600);
        myObjects = new MyObjects();
        
        vBoxTop = new VBox(0);
        hBoxCenLeftTop = new HBox();
        vBoxCenterLeft = new VBox();
        hBoxCenRightTop = new HBox();
        vBoxCenterRight = new VBox();
        vBoxCenterMiddle = new VBox();
        hBoxCenter = new HBox();
        hBoxBottom = new HBox();
        
        createBoxes();
        setSettings();
        setPositions();
    }
    
    
    public void createBoxes() {
        //for BorderPane-TOP
        vBoxTop.getChildren().addAll(myObjects.getLblDatePicker(), myObjects.getDatePicker());
        
        //for BorderPane-CENTER_LEFT_TOP
        hBoxCenLeftTop.getChildren().addAll(myObjects.getBtnRemItemIncome(),
                myObjects.getLblIncome(),  myObjects.getBtnAddItemIncome());
    
        //for BorderPane-CENTER_LEFT
        vBoxCenterLeft.getChildren().addAll(hBoxCenLeftTop, myObjects.getIncomeListView());
        
        //for BorderPane-CENTER_RIGHT_TOP
        hBoxCenRightTop.getChildren().addAll(myObjects.getBtnRemItemOutgoings(),
                myObjects.getLblOutgoings(), myObjects.getBtnAddItemOutgoings());
        
        //for BorderPane-CENTER_RIGHT
        vBoxCenterRight.getChildren().addAll(hBoxCenRightTop, myObjects.getOutgoingsListView());
        
        //for BorderPane-CENTER_Middle
        vBoxCenterMiddle.getChildren().addAll(myObjects.getLblAmountField(),
                myObjects.getAmountField(), myObjects.getSeparator());

        //for BorderPane-CENTER - merging privious Boxes
        hBoxCenter.getChildren().addAll(vBoxCenterLeft, vBoxCenterMiddle, vBoxCenterRight);       
                
        //for BorderPane-BOTTOM
        hBoxBottom.getChildren().addAll(myObjects.getBtnAnalyse(), Var.mySpace(),
                myObjects.getBtnBooking(), Var.mySpace(), myObjects.getBtnEdit());
                
        
    }//end createBoxes

    private void setSettings() {
        //BorderPane-TOP Content
        BorderPane.setMargin(vBoxTop, new Insets(5, 0, 0, 0)); //setzt Top etwas tiefer
        vBoxTop.setAlignment(Pos.CENTER);
        
        //BorderPane-CENTER Content
        hBoxCenLeftTop.setAlignment(Pos.CENTER);
        hBoxCenRightTop.setAlignment(Pos.CENTER);
        vBoxCenterMiddle.setAlignment(Pos.CENTER);
        
        BorderPane.setMargin(vBoxCenterMiddle, new Insets(0, 10, 0, 10)); //Abstand amountField nach rechts und links
        BorderPane.setMargin(hBoxCenter, new Insets(10)); //Abstand Center zu den Rändern
        
        HBox.setHgrow(vBoxCenterLeft, Priority.ALWAYS);  //lässt income HORIZONTAL mitwachsen
        HBox.setHgrow(vBoxCenterRight, Priority.ALWAYS); //lässt outgoings HORIZONTAL mitwachsen
        
        //BorderPane-BOTTOM Content
        BorderPane.setMargin(hBoxBottom, new Insets(0, 20, 10, 20));
        
    }
    
    
    public void setPositions() {
        //Top
        layout.setTop(vBoxTop);
        
        //Center
        layout.setCenter(hBoxCenter);
        
        //Bottom
        layout.setBottom(hBoxBottom);
    }
    
    
    public Scene getSceneGUIBooking() {
        return sceneGUIBooking;
    }

    
    //consign (übergeben, aushändigen) in static way myObjects to MyActionHandler. Solve problem
    //with identifying the buttons as same objects (now event.getSourche() returns same JVM-adress)
    public static MyObjects getMyObjects() {
        return myObjects;
    }

}//end outer class


Variablen und Konstanten
Java:
public class Var {

    public static final Font fontBig = Font.font("sans-serif", FontWeight.BOLD, 15);
    public static final Font fontSmall = Font.font("sans-serif", FontWeight.BOLD, 12);
    public static final Font fontExtraBig = Font.font("sans-serif", FontWeight.BOLD, 18);

    public static final Label mySpace() {
        Label l = new Label();
        l.setMinWidth(20);
        l.setMaxWidth(Double.MAX_VALUE);
        HBox.setHgrow(l, Priority.ALWAYS);

        return l;

    }

}// end class


Mein ActionEvent
Java:
public class MyActionHandler implements EventHandler<ActionEvent>{
    
    
    @Override
    public void handle(ActionEvent event) {
    
        Object o = event.getSource();
        MyObjects myObjects = GUIBooking.getMyObjects();
        
        if (o == myObjects.getBtnRemItemIncome()) {
            System.out.println("Einnahmen-Eintrag löschen");
            
        } else if (o == myObjects.getBtnAddItemIncome()) {
            System.out.println("Einnahmen-Eintrag hinzufügen");
        
        } else if (o == myObjects.getBtnRemItemOutgoings()) {
            System.out.println("Ausgaben-Eintrag löschen");
            
        } else if (o == myObjects.getBtnAddItemOutgoings()) {
            System.out.println("Ausgaben-Eintrag hinzufügen");
        }
        
        //Buttons im BorderPane.Bottom
        else if (o == myObjects.getBtnAnalyse()) {
            System.out.println("Daten werden analysiert...");
        
        } else if (o == myObjects.getBtnBooking()) {
            System.out.println("Buchung wird vorgenommen...");
            
        } else if (o == myObjects.getBtnEdit()) {
            System.out.println("Buchung editieren.");
        }
        
    
    
    }


}//end class


Mein TextField damit es nur Zahlen und Zahlen mit Komma annimmt
Java:
public class MyNumTextField extends TextField {

     @Override
     public void replaceText(int start, int end, String text) {
         if (text.matches("[0-9]") || text.matches(",") || text == "") {
             super.replaceText(start, end, text);
         }
     }
  
     @Override
     public void replaceSelection(String text) {
         if (text.matches("[0-9]") || text.matches(",") || text == "") {
             super.replaceSelection(text);
         }
     }
    
}

Ist dies schon ein besser lesbarer und verwendbarer Code? Geht dies schon in Richtung MVC?
 

dzim

Top Contributor
Also lesbar ist er schon. Vor allem, da du dir schon mal Mühe gegeben hast, es zu kapseln.

Es geht auch schon in Richtung MVC, nur das statische MyObjects-Konstrukt finde persönlich ich noch etwas unschön.
Besser wäre hier ein echtes Model anzulegen, in dem du den Zustand deiner Anwendung vorhältst. Dieser Zustand muss dann halt als Dependency immer mit überreicht werden (und ja, zur Not könnte es Anfangs auch statisch sein, aber das ist eine Unart, die man leider später schwer los wird – ist mir auch passiert) und der Controller macht updates daran und das UI bindet sich daran.

Les dich erst mal in Ruhe in die Themen MVC/MVVM und Dependency Injection ein. Das sollte dich dann schon etwas voran bringen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Dynamische Zellengröße und Zeilenumbruch AWT, Swing, JavaFX & SWT 7
M Java FX dynamische Diagramme AWT, Swing, JavaFX & SWT 0
Q-bert Dynamische Komponente erzeugen AWT, Swing, JavaFX & SWT 6
4a61766120617274697374 dynamische Tree View AWT, Swing, JavaFX & SWT 2
P JavaFX Dynamische TableView AWT, Swing, JavaFX & SWT 14
G Dynamische ComboBox AWT, Swing, JavaFX & SWT 3
B Swing Dynamische JList mit Bildern AWT, Swing, JavaFX & SWT 4
S Jtable dynamische Spaltenbreite AWT, Swing, JavaFX & SWT 5
B SWT Dynamische GUI (Layoutmanager?) AWT, Swing, JavaFX & SWT 2
P Dynamische Seite zum basteln für den User AWT, Swing, JavaFX & SWT 8
B SWT TreeViewer dynamische Anzeige von Icons AWT, Swing, JavaFX & SWT 3
J Java - dynamische Anpassung an Fenstergröße? AWT, Swing, JavaFX & SWT 4
B Swing Dynamische JMenuBar AWT, Swing, JavaFX & SWT 2
C Swing Dynamische JComboBox (Filter) AWT, Swing, JavaFX & SWT 28
W "Dynamische JComboBoxes" AWT, Swing, JavaFX & SWT 5
N Swing Dynamische Controls AWT, Swing, JavaFX & SWT 5
C JTable dynamische erweitern AWT, Swing, JavaFX & SWT 2
T 2D-Grafik Statisches Hintergrundbild, dynamische Bilder drüber AWT, Swing, JavaFX & SWT 2
N Dynamische JFreechart updated UI nicht AWT, Swing, JavaFX & SWT 5
G Große dynamische ContextMenus erzeugen (Eclipse RCP) AWT, Swing, JavaFX & SWT 4
F Swing Dynamische Größenanpassung AWT, Swing, JavaFX & SWT 4
trash Dynamische JTable (SQL) AWT, Swing, JavaFX & SWT 5
L Dynamische Textgröße bei Buttons AWT, Swing, JavaFX & SWT 3
lordcarlos Dynamische und interaktive grafik AWT, Swing, JavaFX & SWT 5
T Swing JTable dynamische Zeilenhöhe AWT, Swing, JavaFX & SWT 5
U Dynamische Panel hinzufügen AWT, Swing, JavaFX & SWT 6
N Swing Dynamische JRadioButtons und Visual Editor AWT, Swing, JavaFX & SWT 4
Q Dynamische Zahl und Positionierung von Objekten AWT, Swing, JavaFX & SWT 5
S Swing Dynamische JPanels: Vertikales Strecken verhindern AWT, Swing, JavaFX & SWT 4
hdi dynamische Iteration über Components AWT, Swing, JavaFX & SWT 3
E Dynamische JComboBox AWT, Swing, JavaFX & SWT 3
F dynamische Ausgabe eines extenen Programms umleiten AWT, Swing, JavaFX & SWT 6
F Dynamische Swing Elemente AWT, Swing, JavaFX & SWT 10
G Dynamische JMenuBar AWT, Swing, JavaFX & SWT 2
T Dynamische Anpassung einer jCheckBox AWT, Swing, JavaFX & SWT 11
O Bindings, dynamische Verbindung (Vorbau mit Netbeans) AWT, Swing, JavaFX & SWT 10
G Dynamische Menüs mit Liste von MRU Dateien AWT, Swing, JavaFX & SWT 2
X Dynamische linien (Position und Länge) AWT, Swing, JavaFX & SWT 4
L Dynamische Buttons erstellt, aber wie ein Event zuweisen? AWT, Swing, JavaFX & SWT 11
T dynamische anzeige? AWT, Swing, JavaFX & SWT 4
S Dynamische Ausgabe im JTextField AWT, Swing, JavaFX & SWT 7
K dynamische jlabels AWT, Swing, JavaFX & SWT 21
M dynamische Grafik in JFrame einbetten AWT, Swing, JavaFX & SWT 2
G JTable dynamische Darstellung der ankommenden Daten AWT, Swing, JavaFX & SWT 19
G JTextField & Dynamische Grössenänderung? AWT, Swing, JavaFX & SWT 8
K TableLayout - dynamische Elemente zu spät ge-updated AWT, Swing, JavaFX & SWT 3
O Dynamische Checkboxen AWT, Swing, JavaFX & SWT 21
T Dynamische GUI's AWT, Swing, JavaFX & SWT 10
T Dynamische Look&Feels AWT, Swing, JavaFX & SWT 4
K dynamische Bilder laden AWT, Swing, JavaFX & SWT 5
MiMa Obseved List mit ListView (Dateiliste) AWT, Swing, JavaFX & SWT 4
H JavaFX ListView MultipleSelection AWT, Swing, JavaFX & SWT 9
AmsananKING ListView Drag And Drop AWT, Swing, JavaFX & SWT 0
AmsananKING Drag And Drop Filenames Inside A Listview AWT, Swing, JavaFX & SWT 1
D Layout einer scene mit ListView Elementen und Zwei Textfeldern AWT, Swing, JavaFX & SWT 1
TheWhiteShadow JavaFX ListView Problem beim Entfernen von Elementen AWT, Swing, JavaFX & SWT 1
Davee JavaFX ListView = null wenn ich sie in Laufzeit ändern will! AWT, Swing, JavaFX & SWT 16
G Eintrag soll nur einmal in Listview zu sehen sein AWT, Swing, JavaFX & SWT 3
T ListView nach Erweiterung Fehler in CellFactory AWT, Swing, JavaFX & SWT 8
T ListView in TableCell AWT, Swing, JavaFX & SWT 4
MiMa File Dateien im ListView als Name anzeigen? AWT, Swing, JavaFX & SWT 6
B JavaFX ListView in Kombination mit TextField AWT, Swing, JavaFX & SWT 5
B JavaFX das richtige ListView filtern AWT, Swing, JavaFX & SWT 2
S JavaFX ListView Inhalte während Laufzeit ändern AWT, Swing, JavaFX & SWT 23
karlmasutra JavaFX ListView zeigt Einträge nicht an AWT, Swing, JavaFX & SWT 11
B Textfelder in einer ListView ausgeben AWT, Swing, JavaFX & SWT 13
J CheckBoxListCell auf click event in listView reagieren AWT, Swing, JavaFX & SWT 1
karlmasutra JavaFX Listenelemente bearbeiten Listview AWT, Swing, JavaFX & SWT 1
D JavaFX Listview mit observableList AWT, Swing, JavaFX & SWT 6
MiMa Selektion aus einer ListView AWT, Swing, JavaFX & SWT 5
N Frage zu ListView AWT, Swing, JavaFX & SWT 11
L JavaFX ListView Größe anpassen AWT, Swing, JavaFX & SWT 1
F JavaFX ListView füllen in Controller Class AWT, Swing, JavaFX & SWT 12
F JavaFX In SampleController ObservableList zu ListView hinzufügen AWT, Swing, JavaFX & SWT 0
D JavaFX ListView & TabelView AWT, Swing, JavaFX & SWT 9
F JavaFX Custom ListView erstellt ghost Element AWT, Swing, JavaFX & SWT 3
F JavaFX Von Datenbank in ListView AWT, Swing, JavaFX & SWT 4
F JavaFX ListView Zeilenhöhe AWT, Swing, JavaFX & SWT 2
M Auswahl aus einer ListView AWT, Swing, JavaFX & SWT 3
F Icons neben Text in Listview setzen AWT, Swing, JavaFX & SWT 2
K ListView right click AWT, Swing, JavaFX & SWT 1
Y Listview Textfield vergrößern, Schrift anpassen AWT, Swing, JavaFX & SWT 0
C Liste - ListView wird nicht angezeigt AWT, Swing, JavaFX & SWT 15
L JavaFX ListView oder TableView Style überschreiben? AWT, Swing, JavaFX & SWT 6
thobren listview seclect abschalten AWT, Swing, JavaFX & SWT 1
NoXiD Java FX JFX 2 DnD ListView AWT, Swing, JavaFX & SWT 3
T [JavaFX 2.0] ListView editieren AWT, Swing, JavaFX & SWT 2
P JTextField wird nur sehr klein angezeigt und verändert die Größe nicht AWT, Swing, JavaFX & SWT 3
H JDialog in Größe ändern - Resize-Cursor bleibt betreten der Komponente AWT, Swing, JavaFX & SWT 1
H AWT Dialog Größe ändern - Schwarzer Inhalt beim groß ziehen AWT, Swing, JavaFX & SWT 1
Yonnig JavaFX Größe von WebView an Content anpassen AWT, Swing, JavaFX & SWT 3
J Swing Komponente wird unpassend angepasst in der Größe AWT, Swing, JavaFX & SWT 35
FrittenFritze Ein Problem mit der CSSBox, die Größe wird nicht angepasst AWT, Swing, JavaFX & SWT 5
D JavaFX Größe des Bild an ImageView anpassen AWT, Swing, JavaFX & SWT 3
R Swing JTextField - Schriftgröße je nach Länge und Größe ändern AWT, Swing, JavaFX & SWT 0
B veränderte Größe eines Panels im Vorhinein wissen? AWT, Swing, JavaFX & SWT 1
B Größe der Parent-Component dynamisch an children anpassen AWT, Swing, JavaFX & SWT 30
L JavaFX AnchorPane an die Größe der Scene oder Window binden? AWT, Swing, JavaFX & SWT 3
K JavaFX Component Größe an Inhalt anpassen AWT, Swing, JavaFX & SWT 11
S Java GUI durch variable Größe einer Map anpassen AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben