Erste Schritte Struktur als Anfänger // Von einer Klasse auf ein Objekt einer anderen Klasse zugreifen.

Soranix

Mitglied
Hallo,
ich habe eine Frage bezüglich meines Projekts.
Ich bin totaler Anfänger, was das Coden betrifft. Seid nicht mehr als einer Woche versuche ich es mit Java. Es gibt mehr als genug Inhalte zum Erlernen der Sprache und so taste ich mich Stück für Stück vor. Ich habe bereits ein eigenes Projekt gestartet. Hier stoße ich vermehrt auf das Problem, dass es ein Haufen an Möglichkeit gibt, sein Projekt zu coden.

Ich versuche von Beginn an mit Klassen zu arbeiten. Hier ergibt sich bei mir folgendes Problem:

Ich würde gerne von der Klasse AccErstellFrame ein Objekt der Klasse AnmeldeFrame schließen.


Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AnmeldeFrame extends StandartFrame {

    private JTextField namePwBoxTextfield;
    private JTextField pwBoxTextfield;
    private JButton pwButton;
    private JButton creatAccButton;


    public AnmeldeFrame() {

        setTitle("Loggin");
        setSize(350, 550);
        setBounds(28, 165, 350, 550);
        setForeground(Color.white);

        initOperation();

        add(namePwBoxTextfield);
        add(pwBoxTextfield);
        add(pwButton);
        add(creatAccButton);

        setVisible(true);

    }

    public void initOperation(){

        DerHandlerAnmeldeBox derHandlerAnmeldeBox = new DerHandlerAnmeldeBox();

        namePwBoxTextfield = new JTextField();
        namePwBoxTextfield.setBounds(25, 200, 300, 40);
        namePwBoxTextfield.setBackground(new Color(43, 43, 58));
        namePwBoxTextfield.setForeground(Color.white);


        pwBoxTextfield = new JTextField();
        pwBoxTextfield.setBounds(25, 250, 300, 40);
        pwBoxTextfield.setBackground(new Color(43, 43, 58));
        pwBoxTextfield.setForeground(Color.white);


        pwButton = new JButton("Go");
        pwButton.setBounds(20, 310, 310, 45);
        pwButton.setForeground(Color.BLACK);
        pwButton.addActionListener(derHandlerAnmeldeBox);

        creatAccButton = new JButton("Neuer Account");
        creatAccButton.setBounds(20, 370, 310, 45);
        creatAccButton.addActionListener(derHandlerAnmeldeBox);

    }

    private class DerHandlerAnmeldeBox implements ActionListener{

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource()==pwButton){
                String nameFromTextfield = namePwBoxTextfield.getText();
                String pwFromTextfield = pwBoxTextfield.getText();

                if (nameFromTextfield.equals("Chief1") && pwFromTextfield.equals("nunde")){
                    dispose();
                    // Open MultiBox

                }
            } if (e.getSource()== creatAccButton){
                // Open CreatBox
                AccErstellFrame accErstellFrame = new AccErstellFrame();
            }

        }
    }

}

Die erste Klasse (Anmeldung) mit Button zur Erstellung eines Benutzeraccount. (Keine sinnvollen Funktionen / Neue Daten werde nicht gespeichert etc.)
Passwortabfrage Klartext etc.. Soll für mich aber erstmal ausreichen.

Zweite Klasse:
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class AccErstellFrame extends  StandartFrame {

    private JTextField creatAccUserNameTextfield;
    private JTextField creatAccUserPwTextField;
    private JButton creatAccountButton;


    public  AccErstellFrame(){

        setTitle("Neuer Benutzer");
        setSize(350, 300);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setForeground(Color.white);

        initOperation();


        add(creatAccUserNameTextfield);
        add(creatAccUserPwTextField);
        add(creatAccountButton);

        setVisible(true);
    }


    public void initOperation() {


        creatAccUserNameTextfield = new JTextField("Benutzername");
        creatAccUserNameTextfield.setBounds(25, 65, 300, 40);
        creatAccUserNameTextfield.setBackground(new Color(43, 43, 58));
        creatAccUserNameTextfield.setForeground(Color.white);

        creatAccUserPwTextField = new JTextField("Passwort");
        creatAccUserPwTextField.setBounds(25, 115, 300, 40);
        creatAccUserPwTextField.setBackground(new Color(43, 43, 58));
        creatAccUserPwTextField.setForeground(Color.white);

        creatAccountButton = new JButton("Bestätigen");
        creatAccountButton.setBounds(25, 175, 310, 45);
        creatAccountButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                try {
                    String newUserName = "";
                    String newUserPw = "";
                    newUserName = creatAccUserNameTextfield.getText();
                    newUserPw = creatAccUserPwTextField.getText();

                    if (newUserName.length() >= 7 && newUserPw.length() >= 7) {
                    // Öffne die MultiBox && Schließ das Anmeldefenster.
                        MultiBoxFrame multiBoxFrame = new MultiBoxFrame();
                        anmeldeFrame.dispose();

                    }


                } catch (Exception ex) {
                    //
                }

            }
        });

    }
}

Bei dem ActionListener lässt sich nicht auf die Anmeldebox zugreifen. Also auch nicht durch .dispose() schließen.

Main class:
Java:
import javax.swing.*;



public class Main {

    // static JLabel pwBoxLabel = new JLabel("Bitte geben Sie Ihre Anmeldedaten ein:");

    public static void main(String[] args) {


        AnmeldeFrame anmeldeFrame = new AnmeldeFrame();
        


    }
}

Ich bin seit vier Tagen dabei.. deswegen begreife ich noch viele Zusammenhänge nicht. Vieles dient hier auch erstmal als Platzhalter bis ich die Theorie dazu lerne/ mich damit befasse. Ich könnte jetzt mit Settern und Boolean werten so lange herumbasteln, dass ich vermutlich das LoginFrame auf setVisible(false) kriegen würde, aber ist das wirklich der beste eleganteste Weg oder soll ich mich jetzt noch gar nicht mit einer sinnvollen Struktur befassen?
 
Anfänger, ... Java... Haufen an Möglichkeiten ..
Generell: der Java-Compiler überprüft "nur" die Einhaltung der formellen Syntax (z.B. Datentyp, Variablen/Methoden/.. innerhalb einer Klasse definiert, "public static void main (String[] args)-Methode" vorhanden,...).
Aus menschlicher Sicht geht man aber auf Vorrat von einer (häufig(er)en) Änderung oder Erweiterung der Software (an zentraler Stelle) aus. Von daher machen "Teile-und-Herrsche"-Verhaltensweisen und damit Schlagworte wie "Aufteilung in Schichten", Namenskonventionen, SOLID-Prinzipien (z.B. "encapsulate what varies"), TDD ( Tweet ( nur Grafik) ), Architektur, "pro Klasse eine Aufgabe", Entwurfsmuster, Algorithmen, Datenstrukturen, OOA, OOD... Sinn.

Getter-/Setter-Methoden sind 'passende' Namen für die implementierte Funktionalität.
 
Also generell ist es ratsam, eine sauber Aufteilung zu haben: Wer kann auf was zugreifen?

Es sieht zumindest auf den ersten Blick nicht danach aus, dass es Sinn macht, dass das eine Fenster das andere direkt kennt um dieses dann ggf. zu schließen.

Was man machen kann ist eine zentrale Stelle zu schaffen, die den Ablauf steuert und die dann die einzelnen Klassen bzw. Instanzen kennt. Also sowas wie eine Klasse Steuerung. Diese mag dann bekannt sein (bzw. ein Interface, das nur die benötigte Schnittstelle enthält).

Dann hättest Du in der mainMethode halt nur die Erzeugung dieser Klasse:
Java:
    public static void main(String[] args) {
        CebtralControl centralControl = new CentralControl();
    }

CentralControl kennt dann die einzelnen Fenster und ist zuständig, diese Fenster zu erstellen. Dabei kann auf dem Konstruktor eine Referenz mitgegeben werden.

CentralControl kennt dann die Logik, die notwendig ist. Das AnmeldeFenster kann also z.B. dem CentralControl mitteilen, dass eine Anmeldung erfolgt. Dann kann CentralControl das notwendige machen und dann z.B. ein vorhandenes Fenster schließen (es hat diese Fenster ja geöffnet und sollte es also kennen) und / oder ein neues Fenster öffnen.

Die Idee dabei ist auch, dass man Logik von der UI trennt. Wie ein User angemeldet wird, gehört nicht in ein Fenster. Ein Fenster sollte nur rein die Darstellung übernehmen und User-Aktionen aufnehmen um diese dann an geeignete Stellen zu geben. Da findet sich dann oft Pattern wie MVC oder MVVM.
 
Also generell ist es ratsam, eine sauber Aufteilung zu haben: Wer kann auf was zugreifen?

Es sieht zumindest auf den ersten Blick nicht danach aus, dass es Sinn macht, dass das eine Fenster das andere direkt kennt um dieses dann ggf. zu schließen.

Was man machen kann ist eine zentrale Stelle zu schaffen, die den Ablauf steuert und die dann die einzelnen Klassen bzw. Instanzen kennt. Also sowas wie eine Klasse Steuerung. Diese mag dann bekannt sein (bzw. ein Interface, das nur die benötigte Schnittstelle enthält).

Dann hättest Du in der mainMethode halt nur die Erzeugung dieser Klasse:
Java:
    public static void main(String[] args) {
        CebtralControl centralControl = new CentralControl();
    }

CentralControl kennt dann die einzelnen Fenster und ist zuständig, diese Fenster zu erstellen. Dabei kann auf dem Konstruktor eine Referenz mitgegeben werden.

CentralControl kennt dann die Logik, die notwendig ist. Das AnmeldeFenster kann also z.B. dem CentralControl mitteilen, dass eine Anmeldung erfolgt. Dann kann CentralControl das notwendige machen und dann z.B. ein vorhandenes Fenster schließen (es hat diese Fenster ja geöffnet und sollte es also kennen) und / oder ein neues Fenster öffnen.

Die Idee dabei ist auch, dass man Logik von der UI trennt. Wie ein User angemeldet wird, gehört nicht in ein Fenster. Ein Fenster sollte nur rein die Darstellung übernehmen und User-Aktionen aufnehmen um diese dann an geeignete Stellen zu geben. Da findet sich dann oft Pattern wie MVC oder MVVM.
Ist alles soweit nachvollziehbar. Die Logik sollte ich somit auch auslagern. Dies würde in meinem Text ja bedeuten, dass auch die ActionListener - Bedingungen ausgelagert werden sollten.
Sollten diese Logiken eigene Klassen darstellen oder was wäre dort zu empfehlen?

Heißt:
Ui = Klassen;
Logik = Klassen;
Organisation dieser Klassen = CentralControl Klasse (kennt alle nötigen Klassen und gibt über if else etc. Bedinungen dieses oder jenes Frame an)
Main Klasse = erstellen der orga. Klasse

Kommunikation über Setter/ Getter
 
Generell: der Java-Compiler überprüft "nur" die Einhaltung der formellen Syntax (z.B. Datentyp, Variablen/Methoden/.. innerhalb einer Klasse definiert, "public static void main (String[] args)-Methode" vorhanden,...).
Aus menschlicher Sicht geht man aber auf Vorrat von einer (häufig(er)en) Änderung oder Erweiterung der Software (an zentraler Stelle) aus. Von daher machen "Teile-und-Herrsche"-Verhaltensweisen und damit Schlagworte wie "Aufteilung in Schichten", Namenskonventionen, SOLID-Prinzipien (z.B. "encapsulate what varies"), TDD ( Tweet ( nur Grafik) ), Architektur, "pro Klasse eine Aufgabe", Entwurfsmuster, Algorithmen, Datenstrukturen, OOA, OOD... Sinn.

Getter-/Setter-Methoden sind 'passende' Namen für die implementierte Funktionalität.
Also direkt von Tag 1 umsetzen und beibehalten?
Danke für die Antwort.
 
Also ich würde die Unterteilung anders benennen. Generell ist in Java alles in Klassen. Und der Aufbau ist immer:
  • Es gibt ein Model. Ein Model ist nur die Daten und die Aktionen mit diesen Daten (Oft Business Logik genannt). Da gibt es kein Frontend oder irgend eine Darstellung (aus Anwendersicht - es ist natürlich ratsam, z.B. toString bei Datenklassen zu überschreiben, damit man diese z.B. in ein Log schreiben kann.)
  • Es gibt dann eine Oberfläche. Diese nutzt dann das Model welches Du unabhängig von allem anderen schon gebaut hast.

Dann haben Klassen generell eine klare, spezifische Aufgabe. Du kannst also sowas haben wie eine Datenklasse "User" - Ein User hat ein Name und ein Passwort.

Dann hast Du vielleicht eine Klasse, die dazu dient, einen User anzumelden. Dabei ist erst einmal egal, wie dies statt findet.
Da ist dann z.B. eine Methode "boolean login(User)", die eine User-Instanz nimmt um dann die Daten aus dem User zu nehmen und zu schauen, ob die Angaben schlüssig sind.

Das wäre dann das Model bezüglich der Anmeldung.

Wenn Du da jetzt ein UI bauen willst, dann brauchst Du:
  • Eine Klasse, die dieses Fenster erzeugt und die Daten verwaltet. Also z.B. ein Fenster mit zwei Eingabefeldern für User und Passwort. Diese Klasse interessiert sich aber nur für die EIngabe. Es ist für diese Klasse egal, wie denn nun eine Anmeldung erfolgt und was bei einer Anmeldung genau passiert. Also ob danach das Fenster geschlossen wird oder nicht ist egal. Das ist nicht Sache des Anmeldefensters.
  • Es gibt sowas wie ein Controller. Der Controller kennt die Klasse, die die UI darstellt und der Controller kennt das Model. Das bedeutet, dass der Controller eine Methode bereit stellen kann, die dann user / Passwort entgegen nimmt um dann eine Anmeldung zu machen. Es kennt das Anmeldefenster um dann ggf. eine Meldung anzeigen zu lassen ("User unbekannt oder Passwort falsch!" oder so).

Bei mir hat die UI gewisse Funktionalität:
a) Es hat Methoden um das Model entgegen zu nehmen und Anzuzeigen. Das "Model" für so ein Fenster kann also die Felder beinhalten: Name, Passwort, Meldung, Icon. Da kann also der Controler Daten ins Model schreiben und das verändert die Anzeige (um z.B. eine Nachricht anzuzeigen oder das Icon zu ändern oder oder oder ....)
b) Es kann Daten von den Controls in das Model übertragen. Der Nutzer gibt also Daten in ein Textfeld ein -> Die Daten werden dann übertragen.
(a und b sind dann bei modernen Frameworks sogenannte Bindings - da muss man dann keinen Code für schreiben. Bei Swing wäre das aber notwendig)
c) Es kann auf Nutzereingaben reagieren. Der Nutzer klickt auf einen Button oder nutzt ein Hotkey oder so. Die UI weiss, was da passieren soll. Das sind dann aber reine Aktionen im Controller.
Also wenn der Benutzer auf den Login Knopf drückt, dann werden die Werte aus den EIngabefeldern übertragen und dann dem Controller gesagt, dass ein Login stattfinden soll. (Das wäre, wenn das Model genutzt wird also sozusagen von UI und Controller gemeinsam genutzt wird. Das muss nicht sein, denn weiter oben hatte ich der login Methode die Parameter gegeben. Da würden die Daten über die Parameter an den Controller gegeben und das Model müsste nicht aktualisiert werden.)

Du hast also ganz klare Zuständigkeiten. Jede Klasse hat eine ganz klare Zuständigkeit.
 
Also ich würde die Unterteilung anders benennen. Generell ist in Java alles in Klassen. Und der Aufbau ist immer:
  • Es gibt ein Model. Ein Model ist nur die Daten und die Aktionen mit diesen Daten (Oft Business Logik genannt). Da gibt es kein Frontend oder irgend eine Darstellung (aus Anwendersicht - es ist natürlich ratsam, z.B. toString bei Datenklassen zu überschreiben, damit man diese z.B. in ein Log schreiben kann.)
  • Es gibt dann eine Oberfläche. Diese nutzt dann das Model welches Du unabhängig von allem anderen schon gebaut hast.

Dann haben Klassen generell eine klare, spezifische Aufgabe. Du kannst also sowas haben wie eine Datenklasse "User" - Ein User hat ein Name und ein Passwort.

Dann hast Du vielleicht eine Klasse, die dazu dient, einen User anzumelden. Dabei ist erst einmal egal, wie dies statt findet.
Da ist dann z.B. eine Methode "boolean login(User)", die eine User-Instanz nimmt um dann die Daten aus dem User zu nehmen und zu schauen, ob die Angaben schlüssig sind.

Das wäre dann das Model bezüglich der Anmeldung.

Wenn Du da jetzt ein UI bauen willst, dann brauchst Du:
  • Eine Klasse, die dieses Fenster erzeugt und die Daten verwaltet. Also z.B. ein Fenster mit zwei Eingabefeldern für User und Passwort. Diese Klasse interessiert sich aber nur für die EIngabe. Es ist für diese Klasse egal, wie denn nun eine Anmeldung erfolgt und was bei einer Anmeldung genau passiert. Also ob danach das Fenster geschlossen wird oder nicht ist egal. Das ist nicht Sache des Anmeldefensters.
  • Es gibt sowas wie ein Controller. Der Controller kennt die Klasse, die die UI darstellt und der Controller kennt das Model. Das bedeutet, dass der Controller eine Methode bereit stellen kann, die dann user / Passwort entgegen nimmt um dann eine Anmeldung zu machen. Es kennt das Anmeldefenster um dann ggf. eine Meldung anzeigen zu lassen ("User unbekannt oder Passwort falsch!" oder so).

Bei mir hat die UI gewisse Funktionalität:
a) Es hat Methoden um das Model entgegen zu nehmen und Anzuzeigen. Das "Model" für so ein Fenster kann also die Felder beinhalten: Name, Passwort, Meldung, Icon. Da kann also der Controler Daten ins Model schreiben und das verändert die Anzeige (um z.B. eine Nachricht anzuzeigen oder das Icon zu ändern oder oder oder ....)
b) Es kann Daten von den Controls in das Model übertragen. Der Nutzer gibt also Daten in ein Textfeld ein -> Die Daten werden dann übertragen.
(a und b sind dann bei modernen Frameworks sogenannte Bindings - da muss man dann keinen Code für schreiben. Bei Swing wäre das aber notwendig)
c) Es kann auf Nutzereingaben reagieren. Der Nutzer klickt auf einen Button oder nutzt ein Hotkey oder so. Die UI weiss, was da passieren soll. Das sind dann aber reine Aktionen im Controller.
Also wenn der Benutzer auf den Login Knopf drückt, dann werden die Werte aus den EIngabefeldern übertragen und dann dem Controller gesagt, dass ein Login stattfinden soll. (Das wäre, wenn das Model genutzt wird also sozusagen von UI und Controller gemeinsam genutzt wird. Das muss nicht sein, denn weiter oben hatte ich der login Methode die Parameter gegeben. Da würden die Daten über die Parameter an den Controller gegeben und das Model müsste nicht aktualisiert werden.)

Du hast also ganz klare Zuständigkeiten. Jede Klasse hat eine ganz klare Zuständigkeit.
Es zwar alles noch ein bisschen schwer einzuordnen, bin aber sehr danke für eine generelle Struktur.
 

Zurück
Oben