Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich versuche in meinem ersten großen Übungsprojekt alles schön sauber zu trennen.
So auch die GUI vom Rest des Codes.
Ich habe in meinem GUI Package eine Class Gui erstellt
Darin erstelle ein einen neuen Frame:
JFrame mainframe = new JFrame("Haushaltsbuch");
Er lässt mich aber keine der Funktionen aufrufen. Wenn ich den Code erweitern will
JFrame mainframe = new JFrame("Haushaltsbuch")
mainframe.
Ich erwarte, dass er mir hier jetzt Sachen wie setDefaultCloseOperation anbietet. Macht er aber nicht.
Wenn ich den Code direkt in meine public static void main packe, funktioniert das.
Kann man das nicht so coden wie ich das vorhabe?
Muss die Erstellung des Frames in der Main stattfinden?
Wurde die Methode selbst statisch definiert ? Das könnte zumindest "Code direkt in meine public static void main packe, funktioniert das." erklären.
Weiterhin könnte das Gesamtprojekt zum Nachstellen nicht schaden.
Ich erwarte, dass er mir hier jetzt Sachen wie setDefaultCloseOperation anbietet. Macht er aber nicht.
Wenn ich den Code direkt in meine public static void main packe, funktioniert das.
1. Du brauchst die notwendigen Imports
2. Anweisungen müssen in Methoden (oder static initializer blocks) stehen. Nachtrag (@JensXF): oder in Konstruktoren, die habe ich vergessen
3. Instanzvariablen werden außerhalb von Methoden deklariert (und ggf. initialisiert).
class Test {
JFrame mainframe;
public Test() {
JFrame mainframe = new JFrame("Haushaltsbuch");
}
public static void main(String[] args) {
Test test = new Test();
test.mainframe.getDefaultCloseOperation();
}
sorry es sollte so aussehen "keine neue locale Variable"
Java:
class Test {
JFrame mainframe;
public Test() {
mainframe = new JFrame("Haushaltsbuch");
}
public static void main(String[] args) {
Test test = new Test();
test.mainframe.getDefaultCloseOperation();
}
Nur kleine Zwischenfrage: Das da kein ";" am Ende der ersten Zeile ist, ist nur ein Kopier/Tippfehler?
Ansonsten wäre das ggf. schon der Punkt, der die IDE durcheinander bringt.
Also hier die zwei Codeblöcke.
Der erste ist meine Datei mit der Main Klasse innerhalb meines Main Packages
Wenn ich hier JFrame nutze funktioniert es.
[CODE lang="java" title="Package main -> Main Klasse" highlight="1,6,8,9"]package Main;
import javax.swing.*;
public class Main {
public static void main(String[] args) {
JFrame mainframe = new JFrame("Haushaltsbuch");
mainframe.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}[/CODE]
Der zweite Block ist in einer extra Datei namens Gui
Auch hier sind die imports drin, aber Exit.on.close gibt es hier scheinbar nicht.
[CODE lang="java" title="package gui -> public class Gui" highlight="14"]package gui;
sorry es sollte so aussehen "keine neue locale Variable"
Java:
class Test {
JFrame mainframe;
public Test() {
mainframe = new JFrame("Haushaltsbuch");
}
public static void main(String[] args) {
Test test = new Test();
test.mainframe.getDefaultCloseOperation();
}
Wo in welcher klasse die main Methode ist ist ziemlich unwichtig.
Sie ist static.
Aber was machst du du willst im Klassenrumpf auf die variable zugreifen. Geht nicht. Das erstellen der Variable und auch das Setzen der Variablen geht.
Besser und auch übersichtlicher ist es keine statement im Klassenrumpf zu benutzen.
Dafür ist der Konstruktor sinnvoller .
Zum benutzen musst du dich schon in einer Methode befinden. Oder im Konstruktor.
Wie ja nun schon mehrfach erwähnt wurde: Anweisungen müssen in Methoden/Konstruktoren stehen:
Java:
public class Gui {
// Instanzvariable deklarieren und initialisieren
JFrame mainframe = new JFrame("Haushaltsbuch");
// Konstruktor
public Gui() {
mainframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// ...
}
Oder:
Java:
public class Gui {
// Instanzvariable deklarieren
JFrame mainframe;
// Konstruktor
public Gui() {
// Instanzvariable initialisieren
mainframe = new JFrame("Haushaltsbuch");
mainframe.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// ...
}
OK habe jetzt in der Datei GUI, in der Klasse GUI die Variable und den Konstruktor angelegt und in meiner Main Datei rufe ich es in der Main Klasse auf. Klappt !!
Leider habe ich aber noch arge Probleme mit dem Verständnis.
Was bzw. wie ist es gemeint, wenn man sagt GUI & Code muss getrennt werden.
Wäre das Vorgehen wie ich es mache so richtig ?
Ich mache mir für jede Klasse eine neue Datei auf (siehe Screenshot #14).. oder hat man eine Datei inkl. Main und haut da die unterschiedlichen Klassen rein.
Bin ich vielleicht sogar gerade total lost ?
Leider komme ich mit meinen Büchern nicht sonderlich weiter.
(*)menschliche Faktoren und Herangehensweisen werden so aber vernachlässigt. Genau damit befassen sich Quellen wie software-architektur.tv oder der YT-Kanal von "the native web GmbH"
Bezüglich mehrere Dateien ja/nein:
In Java sollte jede Klasse in einer Datei sein, die genau so heisst wie die Klasse. (So die Klasse "public" ist, ist dies auch Pflicht!)
Daher wäre das so erst einmal korrekt.
Wichtig ist aber dann noch, dass die Klassen ein Objektmodell beschreiben, alsoObjekte mit diesen Klassen erzeugt werden, die dann Status und Verhalten haben und miteinander agieren.
GUI und Code Trennen ist dann vom Wording her auch nicht ganz so, wie ich es ausdrücken würde. Es geht halt darum, eigenständige Verantwortungen zu haben. Eine Klasse (die durchaus aus Code besteht, denn wie erstellst Du sonst die Swing UI? Da muss ja sowas wie new JFrame(), new JLabel, ... vorkommen. Das ist ja auch Code.) sollte also eine Verantwortung haben. So kannst Du in dem Namespace gui eine Klasse haben, die dann das Fenster aufbaut. Diese Klasse sollte aber dann nur für die Oberfläche zuständig sein. Wenn der Benutzer einen Knopf drückt, dann registriert diese Klasse das, aber die Verantwortung, da etwas sinnvolles zu machen, sollte dann bei einer anderen Klasse liegen. In dem MVC Pattern (Model, View, Controller) wäre da dann der Controller dafür zuständig. Aber alle fachliche Logik findet sich auch nicht im Controller sondern die ist im Model.
Also wenn man das ganz kurz umreissen müsste (Adressverwaltung):
- Die View erstellt die Oberfläche. Die Daten dazu kommen aus einem Model. Es könnte also die Anzeige einer Adresse sein: Fenster mit Name, Straße, PLZ, Ort wird angezeigt. Dazu wurde der View eine Instanz der Klasse Address (Model) gegeben. Und die View kennt einen Controller, der wurde auch gegeben (also z.B. eine Instanz von AddressController). Damit kann die View die Daten aus dem Model anzeigen. Wie, ist ganz allein in der Verantwortung der View. Und wenn etwas passiert, dann wird der Controller aufgerufen. Also z.B. clickt der Benutzer auf Save. Dann wird im Controller die Methode save(...) aufgerufen mit den Informationen, die der Controller braucht. Bei einem UI Framework wie Swing habe ich üblicherweise immer zwei Methoden gehabt: Einmal Datentransfer von Model in Controls und zum Anderen in die andere Richtung. Dann wird bei save das Model übergeben oder der Controller hat noch die Instanz vom Model und dann muss nichts übergeben werden.
- Der Controller kennt die Applikation. Wenn also eine Adresse angezeigt werden soll, dann weiss er: Dazu gibt es eine View. Die braucht gewisse Daten. Also holt es die notwendigen Daten (z.B. aus der Datenbank), erstellt das Model für die View und erstellt die View mit den benötigten Informationen.
- Wichtig ist: Wenn das Model schon Business Logik enthält (Die Address Klasse kann sich selbst speichern), dann wird dies nicht von der View aufgerufen! Das ist einfach nicht die Verantwortung von der View! Also immer etwas auf die Zuständigkeiten achten.
Ich versuche mal einigermaßen Verständlich mein Projekt hier zu präsentieren und werde dann meine Probleme/Fragen pro Klasse aufschreiben.
Ich bitte nochmal um Entschuldigung wenn manche Fragen seltsam erscheinen sollten, aber bis dato wurde mir hier am besten geholfen obwohl ich mich Fachlich manchmal eher seltsam ausdrücken mag
Projekt Haushaltsbuch: Es soll mit der Zeit wachsen und später wenn es einen vernünftigen brauchbaren Stand hat, auch genutzt werden.
Es wird mit der Zeit auch mit Sicherheit noch einiges geändert werden (Optik/Anwendungsumfang etc.), aber irgendwo musste ich ja starten.
Zur Zeit gibt es 4 Dateien mit jeweiligen (Klassen)
In einem Udemy Kurs wurde hier mit separaten Paketen gearbeitet (wurde schon hingewiesen, dass dies wohl nicht ganz normal sei.
Main.java (public class Main)
Java:
package Main;
import application.DBStatement;
import gui.Layout;
public class Main {
public static void main(String[] args) {
//Datenbank Verbindung wird aufgebaut
DBStatement dbStatement = new DBStatement();
try {
dbStatement.checkDBConnection();
System.out.println(dbStatement);
} catch (Exception e) {
e.printStackTrace();
}
//GUI wird erstellt
Layout window = new Layout("Haushaltsbuch");
window.setVisible(true);
}
}
DBConnection.java (public class DBConnection)
Java:
package dbUtil;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
//Datenbank Verbindung
public static final String DB_Name = "Haushaltsbuch.db";
public static final String DB_Path = "F:\\Projekte\\Haushaltsbuch\\src\\";
public static final String CONNECTION_STRING = "jdbc:sqlite:" + DB_Path + DB_Name;
public Connection getConnection() throws SQLException {
Connection connection = null;
connection = DriverManager.getConnection(CONNECTION_STRING);
return connection;
}
}
public class Layout extends JFrame {
public Layout(String title) {
super(title);
this.setSize(700, 300);
this.setLocation(100, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
JTextField textAusgabeMonat = new JTextField("Bitte geben Sie den Monat ein");
JTextField textAusgabeArt = new JTextField("Bitte geben Sie die Art der Ausgabe an");
JTextField textAusgabeName = new JTextField("Bitte geben Sie den Namen der Ausgabe an");
JTextField textAusgabeBetrag = new JTextField("Bitte geben Sie den Betrag an");
JButton buttonOk = new JButton("Ok");
In der Klasse Layout habe ich es jetzt hinbekommen -dank eurer Hilfe- , dass ich die Instanz an die Main weitergeben kann und diese dort aufrufbar ist.
Jetzt möchte ich aber auch, dass wenn jemand etwas in die Textfelder schreibt, dieser Text in meine DB geschrieben wird (siehe Zeile 44 -52)
Damit der Text in die DB kommt, muss ich dafür ein Statement bauen. Dieses würde ich in Klasse DBStatement sehen
Insert INTO ............. + textAusgabeMonat + usw...
Mir bereitet es aber ernome Probleme zu verstehen, wie ich jetzt nur den Teil mit dem ActionListener in die DBStatementKlasse bekomme, weil wenn ich jetzt in der Statement Klasse einfach eine Instanz der Layout Klasse aufrufen würde, würde dort ja noch eine komplette GUI erstellt werden !? Das wäre ja falsch.
Für update und delete benötigst Du auf der Datenbank ein Feld als technischen Primary-Key, dessen Wert auch in der Klasse Ausgabe gespeichert werden muss.
Als ich noch JDBC gemacht habe, war dieses Buch meine beste Quelle:
Java-Persistenzstrategien. Datenzugriff in Enterprise-Anwendungen: JDO, JCA, Enterprise Java Beans, JDBC, XML Taschenbuch – 23. März 2004
von Andreas Holubek (Autor), Rudolf Jansen (Autor), Robert Munsky (Autor), Eberhard Wolff (Autor)
Und genau hier kommt mein Problem. Ich bin zu blöd die Variablen samt Wert aus der Layout in die neue Klasse Ausgabe zu bekommen.
Ich wüsste jetzt nur wie ich die komplette Layout Instanz in der neuen Klasse Ausgabe integrieren könnte, sodass mir dort ein weiteres Frame etc generiert werden würde...
Das Problem ist, dass Du die Elemente in lokalen Variablen vorhältst:
Java:
public class Layout extends JFrame {
public Layout(String title) {
super(title);
this.setSize(700, 300);
this.setLocation(100, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
JTextField textAusgabeMonat = new JTextField("Bitte geben Sie den Monat ein");
JTextField textAusgabeArt = new JTextField("Bitte geben Sie die Art der Ausgabe an");
JTextField textAusgabeName = new JTextField("Bitte geben Sie den Namen der Ausgabe an");
JTextField textAusgabeBetrag = new JTextField("Bitte geben Sie den Betrag an");
JButton buttonOk = new JButton("Ok");
Damit existieren die Variablen textAusgabeMonat, textAusgabeArt, .... nur innerhalb des Konstruktors.
Eine Möglichkeit: Erstelle Instanzvariablen:
Java:
public class Layout extends JFrame {
JTextField textAusgabeMonat;
JTextField textAusgabeArt;
JTextField textAusgabeName;
JTextField textAusgabeBetrag;
JButton buttonOk;
public Layout(String title) {
super(title);
this.setSize(700, 300);
this.setLocation(100, 100);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
textAusgabeMonat = new JTextField("Bitte geben Sie den Monat ein");
textAusgabeArt = new JTextField("Bitte geben Sie die Art der Ausgabe an");
textAusgabeName = new JTextField("Bitte geben Sie den Namen der Ausgabe an");
textAusgabeBetrag = new JTextField("Bitte geben Sie den Betrag an");
buttonOk = new JButton("Ok");
Damit sind die Elemente innerhalb der Klasse zugreifbar.
So jetzt ist alles durcheinander und ich komme garnicht mehr klar.
Meine Euphorie weicht langsam der Enttäuschung.
Denke ich werde das Projekt erstmal liegen lassen.
Vielleicht ist es einfach zu viel erwartet, jetzt schon ein Projekt zu schreiben.
Vielleicht sollte ich erstmal beim Hallo Welt bleiben.
Werde wohl nicht drum rum kommen erstmal weiter Kurse und Bücher zu inhalieren.
Danke für die Zeit und Hilfe.. mein Kopf will es einfach nicht schnallen
Ganz grundsätzlich ist so ein Projekt super, fachlich ist das interessant und schön modellierbar und technisch lässt sich das auch super umsetzen – aber, GUIs sind für den Anfang einfach zu viel. Alle Grundlagen müssen wirklich sitzen, bevor man sich daran macht, mit GUIs zu arbeiten.
Daher wäre mein Rat für dieses Projekt: setz es fort, verzichte aber erstmal auf eine grafische Oberfläche und steuere das ganze z.B. über die Kommandozeile.
Ganz grundsätzlich ist so ein Projekt super, fachlich ist das interessant und schön modellierbar und technisch lässt sich das auch super umsetzen – aber, GUIs sind für den Anfang einfach zu viel. Alle Grundlagen müssen wirklich sitzen, bevor man sich daran macht, mit GUIs zu arbeiten.
Daher wäre mein Rat für dieses Projekt: setz es fort, verzichte aber erstmal auf eine grafische Oberfläche und steuere das ganze z.B. über die Kommandozeile.
Trotzdem gibt es auch mit alleiniger Kommandozeilen-Implementierung einige (längerfristig) zu beachtende Prinzipien bei der Organisation. Z.B. kann es vorteilhafter sein, wenn eine Erweiterung / Änderung nur an einer (zentralen) Stelle im Code erfolgt.
Bzgl. GUI-Programmierung sollte man auf GUI-Builder erstmal verzichten, da diese Aspekte wie Wiederverwertbarkeit, Erweiterbarkeit,... (mangels Kenntnis der Zusammenhänge) aussen vor lassen (könn(t)en). Ein Beispiel aus der .NET-Welt: MyCSharp - Variablennamen zur Laufzeit... (wobei sich nicht alles 1:1 auf die Java-Welt übertragen lässt, "ArrayList" ist in Java das neuere)