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.
JavaFX unterschiedliche (mehrere Fenster) in seperater Main Methode
Ich habe folgendes vor. Ich habe eine unabhängige Main Klasse in der mittels OPCUA Variablen aus einer S7 Steuerung abgefragt werden.
Anhand eines Wertes einer dieser Variable muss ich nun unterschiedliche Fenster öffnen/schließen können.
Ich habe kein treffendes Problem beim googlen gefunden und absolut keinen Ansatz wie ich da beginnen soll.
Kann mir jemand helfen?
Da würde ich einfach mal zurückfragen: Was ist denn da Dein Problem? Mehrere Fenster in JavaFX zu öffnen ist ja unproblematisch.
Was du mit separater main Methode meinst ist mir aber unklar. Die main Methode ist ein Startpunkt einer Java Applikation. Da hast Du genau eines. Und das ist vollkommen unabhängig von JavaFX Fenstern.
Es wird in der Regel ja Application.launch aufgerufen, was dann ein erstes Fenster öffnet. Aber was da dann für ein Inhalt kommt, ist ja vollkommen nebensächlich.
Du hast also sehr viele Möglichkeiten eben das zu machen, was auch immer du machen willst. Man kann dann maximal überlegen, ob das erste Fenster dann sowas wie ein Splash Screen wird, während du Daten von der "S7 Steuerung" abfragst um dann weitere Fenster zu öffnen und dieses Fenster zu schließen oder so ...
Das Problem ist so dürftig beschrieben, dass man nur eine simple Gegenfrage stellen kann. Was hindert dich daran ein Switch Case , If Else Konstrukt aufzubauen und dann die entsprechenden Fenster zu öffnen und zu schließen?
Muss man wissen was ein S7 und/oder OPCUA ist um das Problem zu lösen, wenn sowieso nur Variablen ausgelesen werden über die Main? Sonst würde ich detaillierter erklären was das überhaupt ist. Ein S7 ist für mich ein Samsung Modell, ist aber bestimmt in deinem Fall eine Abkürzung für etwas ganz anderes oder?
erst einmal danke für die Antworten.
Ich erkläre das ganze mal etwas genauer.
Ich bin kein Profi in Java ich lerne noch.
Ich habe genau eine Main Methode in der ich noch keinerlei JavaFX habe und das sollte denke ich auch so bleiben.
nun habe ich eine Variable die mittels OPCUA ausgelesen wurde. Wenn diese Variable den Wert 3 annimmt muss ich ein JavaFX Fenster öffnen.
Wenn die Variable den Wert 4 hat ein völlig anderes... und soweiter
Meine Kenntnisse reichen bisher eine JavaFX Anwendung zu schreiben. Vielleicht könnt ihr mir mittels eines kleinen Codeschnipsels auf die Sprünge helfen.
Das kannst Du gerne so handhaben. Das ist relativ egal. Der übliche Ansatz ist aber, dass Du eine Klasse hast, die von Application erbt und die dann launch aufruft.
Für was wird genau ein Codeschnipsel benötigt? Eine typische JavaFX Applikation findet sich (incl. Maven Projekt mit allem drum und dran) z.B. auf https://github.com/kneitzel/JavaFXMavenApp
Diesen Startweg würde ich - gerade am Anfang - immer benutzen und nicht selbst irgendwas basteln. Beim Start werden halt gewisse Dinge initialisiert wie ein Thread, der dann Events bearbeitet und so. Da kann man prinzipiell auch mit Platform.startup und so hantieren, aber das verkompliziert alles nur unnötig.
Neue Fenster sind generell immer einfach per Stage newStage = new Stage(); erstellbar, daher ist das auch sehr unkompliziert - so halt die JavaFX Runtime bereits initialisiert wurde.
Das kannst Du gerne so handhaben. Das ist relativ egal. Der übliche Ansatz ist aber, dass Du eine Klasse hast, die von Application erbt und die dann launch aufruft.
Für was wird genau ein Codeschnipsel benötigt? Eine typische JavaFX Applikation findet sich (incl. Maven Projekt mit allem drum und dran) z.B. auf https://github.com/kneitzel/JavaFXMavenApp
Diesen Startweg würde ich - gerade am Anfang - immer benutzen und nicht selbst irgendwas basteln. Beim Start werden halt gewisse Dinge initialisiert wie ein Thread, der dann Events bearbeitet und so. Da kann man prinzipiell auch mit Platform.startup und so hantieren, aber das verkompliziert alles nur unnötig.
Neue Fenster sind generell immer einfach per Stage newStage = new Stage(); erstellbar, daher ist das auch sehr unkompliziert - so halt die JavaFX Runtime bereits initialisiert wurde.
ich poste mal eine sehr vereinfachte Main Methode wie meine in etwa arbeitet.
Java:
package lagerverwaltung;
import lagerverwaltung.Lagerverwaltung_MainGUI;
public class Test {
private static boolean connected; // Diese Variable wird auf true gesetzt wenn man mittels OPCUA an einem Server verbunden ist
private static int benötigtesBild; // Diese Variable wird ebenfalls über OPCUa ausgelesen.
public static void main(String[] args) {
while (connected) {
if (benötigtesBild == 1) {
// hier scheitere ich jetzt
}
}
}
}
Die while schleife darf nicht unterbrochen werden. Also muss ich bestimmt über Threads arbeiten aber ich habe keinen Plan wie ich jetzt meine JavaFX anwendung in der If Anweisung ausführen kann.
Trenne Dich von dem Gedanken, sowas in der main Methode machen zu wollen. Und Du solltest trennen zwischen dem Auslesen irgendwelcher Dinge und dem, was dann passiert. Das sind zwei paar Schuhe!
Du hast also einen Thread, der die Überprüfung in so einem Thread macht. Dabei stellt er dann irgendwas fest, was er nach außen melden kann - für wen auch immer das interessant sein mag. Das Ganze ist vom Aufbau her im Observer Pattern beschrieben (Und entspricht auch genau dem, was Du z.B. auch von den Events bei den UI Elementen kennst).
Und wenn dann diese Überwachung etwas feststellt, dann kann eine andere Klasse darauf reagieren.
Die Klasse, die von Application erbt, kann dann verwalten, was es so alles gibt:
die Klasse, die diese Überwachung macht
weiss, welche Fenster es derzeit so alles gibt
ggf. Instanzen von Klassen, die irgendwas aktiv tun.
Konkretes kann ich dazu aber nicht sagen, denn wir haben ja keine Ahnung, was da überhaupt so für Anforderungen sind.
Aber was Du wirklich im Hinterkopf behalten solltest: Separation of Concerns - teile den Code auf, so dass Du Aufgaben vernünftig aufgeteilt hast. Das Observable Pattern habe ich bereits genannt, aber für die UI wird dann MVC, MVP oder MVVM wichtig, damit es möglichst übersichtlich bleibt.
Trenne Dich von dem Gedanken, sowas in der main Methode machen zu wollen. Und Du solltest trennen zwischen dem Auslesen irgendwelcher Dinge und dem, was dann passiert. Das sind zwei paar Schuhe!
Du hast also einen Thread, der die Überprüfung in so einem Thread macht. Dabei stellt er dann irgendwas fest, was er nach außen melden kann - für wen auch immer das interessant sein mag. Das Ganze ist vom Aufbau her im Observer Pattern beschrieben (Und entspricht auch genau dem, was Du z.B. auch von den Events bei den UI Elementen kennst).
Und wenn dann diese Überwachung etwas feststellt, dann kann eine andere Klasse darauf reagieren.
Die Klasse, die von Application erbt, kann dann verwalten, was es so alles gibt:
die Klasse, die diese Überwachung macht
weiss, welche Fenster es derzeit so alles gibt
ggf. Instanzen von Klassen, die irgendwas aktiv tun.
Konkretes kann ich dazu aber nicht sagen, denn wir haben ja keine Ahnung, was da überhaupt so für Anforderungen sind.
Aber was Du wirklich im Hinterkopf behalten solltest: Separation of Concerns - teile den Code auf, so dass Du Aufgaben vernünftig aufgeteilt hast. Das Observable Pattern habe ich bereits genannt, aber für die UI wird dann MVC, MVP oder MVVM wichtig, damit es möglichst übersichtlich bleibt.
Verstehe ich das jetzt erst einmal Richtig das meine Main Methode in etwa dann so aussehen soll?
Java:
public static void main(String[] args) {
startMain = new Lagerverwaltung_MainProgramm();
Thread t = new Thread(startMain); // create thread
t.start(); // start thread
launch(args);
}
Damit könnte ich zwar erst einmal anfangen, verstehe aber dann nicht wie ich verschiedene Fenster mit jeweils eigenen Controllern aufrufen kann.
Also wenn die Variable sich ändert müsste ich ja ein anderes Bild laden. Wer und wie handelt das dann? Ein Controller oder in der Start Methode?
Ich versteh das ganze noch nicht so genau. Meine JavaFX Kenntnisse gehen da noch nicht so tief.
Und immer auf die verwendeten Namen achten - was genau macht denn die Klasse "Lagerverwaltung_MainProgramm"?
Was passiert da in dem Thread, den du da startest? Finde einen Namen, der das möglichst gut ausdrückt. Lagerverwaltung ist ja wohl dein ganzes Projekt.
Dann ist der Thread ja wohl in der Verantwortung dieser Klasse. Die Klasse Überwacht etwas und diese Überwachung kann man starten. Also ist da dann etwas wie:
Java:
public class Ueberwachung {
private Thread ueberwachungThread;
private volatile boolean shouldRun;
protected void ueberwache() {
while (shouldRun) {
// mache die Überwachung....
}
}
public void start() {
if (thread != null && thread.isRunning()) throw new InvalidStateException("Überwachung läuft schon!");
shouldRun = true;
ueberwachungThread = new Thread (this::ueberwache);
ueberwachungThread.start();
}
}
Das kannst Du in der Application Klasse dann tatsächlich erstellen und starten.
Dann hatte ich ja schon auf ein Observer Pattern hingewiesen. Die Klasse will ja andere informieren. Da kann man dann eigene Interfaces und so verwenden oder man nutzt, was es schon gibt, z.B. PropertyChangedListener, PropertyChangedEvent, ...
Die oben genannte Klasse bekommt also zusätzlich noch:
Java:
private List<PropertyChangeListener> listeners = new ArrayList<>();
public synchronized void addListener(PropertyChangeListener listener) {
listeners.add(listener);
}
private void sendInfo(String property, Object oldValue, Object newValue) {
List<PropertyChangeListener> currentListeners;
synchronized(this) {
currentListeners = listeners.stream().toList();
}
PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue);
for (PropertyChangeListener listener : currentListeners) {
listener.propertyChange(event);
}
}
// Irgendwo in Deiner Schleife dann ein Aufruf wie:
sendInfo("Whatever", oldValue, newValue);
// um die "Interessierten" zu informieren.
Das einfach nur einmal so im Forum auf die Schnelle geschrieben. Evtl. haben sich dabei Fehler eingeschlichen.
Aber mit diesen Konzepten solltest Du Dich etwas mehr auseinander setzen.
Und immer auf die verwendeten Namen achten - was genau macht denn die Klasse "Lagerverwaltung_MainProgramm"?
Was passiert da in dem Thread, den du da startest? Finde einen Namen, der das möglichst gut ausdrückt. Lagerverwaltung ist ja wohl dein ganzes Projekt.
Dann ist der Thread ja wohl in der Verantwortung dieser Klasse. Die Klasse Überwacht etwas und diese Überwachung kann man starten. Also ist da dann etwas wie:
Java:
public class Ueberwachung {
private Thread ueberwachungThread;
private volatile boolean shouldRun;
protected void ueberwache() {
while (shouldRun) {
// mache die Überwachung....
}
}
public void start() {
if (thread != null && thread.isRunning()) throw new InvalidStateException("Überwachung läuft schon!");
shouldRun = true;
ueberwachungThread = new Thread (this::ueberwache);
ueberwachungThread.start();
}
}
Das kannst Du in der Application Klasse dann tatsächlich erstellen und starten.
Dann hatte ich ja schon auf ein Observer Pattern hingewiesen. Die Klasse will ja andere informieren. Da kann man dann eigene Interfaces und so verwenden oder man nutzt, was es schon gibt, z.B. PropertyChangedListener, PropertyChangedEvent, ...
Die oben genannte Klasse bekommt also zusätzlich noch:
Java:
private List<PropertyChangeListener> listeners = new ArrayList<>();
public synchronized void addListener(PropertyChangeListener listener) {
listeners.add(listener);
}
private void sendInfo(String property, Object oldValue, Object newValue) {
List<PropertyChangeListener> currentListeners;
synchronized(this) {
currentListeners = listeners.stream().toList();
}
PropertyChangeEvent event = new PropertyChangeEvent(this, property, oldValue, newValue);
for (PropertyChangeListener listener : currentListeners) {
listener.propertyChange(event);
}
}
// Irgendwo in Deiner Schleife dann ein Aufruf wie:
sendInfo("Whatever", oldValue, newValue);
// um die "Interessierten" zu informieren.
Das einfach nur einmal so im Forum auf die Schnelle geschrieben. Evtl. haben sich dabei Fehler eingeschlichen.
Aber mit diesen Konzepten solltest Du Dich etwas mehr auseinander setzen.
Ein neues Fenster kannst Du immer mittels Stage stage = new Stage(); erstellen. Da dann halt die üblichen Dinge wie Titel und Scene setzen - das ist aber genau so, wie in der start Methode in der halt die Stage als Parameter übergeben wurde.
Ein neues Fenster kannst Du immer mittels Stage stage = new Stage(); erstellen. Da dann halt die üblichen Dinge wie Titel und Scene setzen - das ist aber genau so, wie in der start Methode in der halt die Stage als Parameter übergeben wurde.
Ok wie gesagt das mein Programm nicht das beste ist, ist mir klar. Das da viel Luft nach oben ist...
Was ich aber halt ganz und gar nicht verstehe ist das mit dem JavaFX. Ich kenne das nur so:
Und da verstehe ich nicht wie ich zwischen 2 Fenstern und 2 Controllern hin und herswitche. Genauso verstehe ich dann nicht wo ich das launch aufrufe wenn nicht in der Main.
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import lagerverwaltung.lager.Lagerplatz;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class Lagerverwaltung_MainGUI extends Application{
private static Lagerverwaltung_MainProgramm startMain;
static Lagerplatz [] [] [] lagerplatz = new Lagerplatz[10][100][10];
@Override
public void start(Stage mainStage) throws Exception {
// eine Instanz von FXMLLoader erzeugen
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
// die Datei laden
Parent root = meinLoader.load();
// den Controller beschaffen
Main_Controller meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
// die Szene erzeugen
Scene mainScene = new Scene(root, 1000, 600);
// den Titel über stage setzen
mainStage.setTitle("Main Lagerverwaltung");
// die Scene setzen
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent windowEvent) {
close();
}
});
//
int aktuellesBild = Lagerverwaltung_MainProgramm.getAktuellesBild();
int hilfsbild = Lagerverwaltung_MainProgramm.getHilfsbild();
System.out.println(" HilfsbildNr: " + hilfsbild);
// Größe nicht veränderbar und ohne Menüleiste anzeigen
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
// und anzeigen
mainStage.show();
}
// on close
public static void close() {
startMain.stop();
Platform.exit();
}
public static void main(String[] args) {
startMain = new Lagerverwaltung_MainProgramm();
Thread t = new Thread(startMain); // create thread
t.start(); // start thread
launch(args);
}
}
Du hast da alles in eine Klasse gequetscht - das macht wenig Sinn, da Du so nur die Übersicht verlieren kannst.
Ja, das launch ist und bleibt in der main Methode.
Und das ist die Klasse der Applikation - daher erbt diese auch von Application. Da kommt aber sonst auch nicht wirklich weitere Funktionalität rein.
Du willst da irgend einen Thread der irgendwas überwacht oder so? Dann mach eine separate Klasse. Habe ich in #9 gezeigt, wie sowas aufgebaut sein könnte.
Und bei dem launch Aufruf wird auch eine Instanz der Klasse erzeugt -> Das musst Du also nicht mehr machen! (So hast Du hinterher mehrere Instanzen...)
Statische Variablen solltest Du sein lassen - das führt meist nur zu Problemen.
Dann hast Du ggf. etwas wie:
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class LagerVerwaltungApp extends Application{
private Main_Controller meinController;
@Override
public void start(Stage mainStage) throws Exception {
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
Parent root = meinLoader.load();
meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
Scene mainScene = new Scene(root, 1000, 600);
mainStage.setTitle("Main Lagerverwaltung");
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest( () -> close() ); // Ist sowas notwendig?
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
mainStage.show();
}
public static void close() {
Platform.exit();
}
public static void main(String[] args) {
launch(args);
}
}
als ersten JavaFX Startpunkt.
So eine Überwachung oder was auch immer der Thread macht, hast Du dann in einer anderen Klasse, also z.B. wie von mir skizziert in einer Klasse Ueberwachung. Das kannst Du dann mit einbauen:
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class LagerVerwaltungApp extends Application{
private Main_Controller meinController;
private Uberwachung ueberwachung;
@Override
public void start(Stage mainStage) throws Exception {
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
Parent root = meinLoader.load();
meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
Scene mainScene = new Scene(root, 1000, 600);
mainStage.setTitle("Main Lagerverwaltung");
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest( () -> close() ); // Ist sowas notwendig?
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
mainStage.show();
ueberwachung = new Ueberwachung();
ueberwachung.start();
ueberwachung.addPropertyListener(meinController::bearbeiteUeberwachungsPropertyChanges);
}
public static void close() {
Platform.exit();
}
public static void main(String[] args) {
launch(args);
}
}
Das setzt jetzt voraus, dass der Controller eine Methode bearbeiteUeberwachungsPropertyChanges hat, die ein PropertyChangeEvent als Parameter entgegen nimmt.
==> Da hast Du dann im Controller eine Stelle, die auf erkannte Veränderungen reagieren kann.
Was ich auch raus genommen habe, ist Dein Array mit irgendwelchen Daten. Daten sind ordentlich, unabhängig von JavaFX Applikation / Controllern und Co zu verwalten. Also auch eine eigene Klasse mit einer eigenen Instanz. Die kannst Du da auch in start dann initialisieren und Du kannst die dann z.B. an den Controller geben oder so. Aber das ist nicht in der Application Klasse.
Du hast da alles in eine Klasse gequetscht - das macht wenig Sinn, da Du so nur die Übersicht verlieren kannst.
Ja, das launch ist und bleibt in der main Methode.
Und das ist die Klasse der Applikation - daher erbt diese auch von Application. Da kommt aber sonst auch nicht wirklich weitere Funktionalität rein.
Du willst da irgend einen Thread der irgendwas überwacht oder so? Dann mach eine separate Klasse. Habe ich in #9 gezeigt, wie sowas aufgebaut sein könnte.
Und bei dem launch Aufruf wird auch eine Instanz der Klasse erzeugt -> Das musst Du also nicht mehr machen! (So hast Du hinterher mehrere Instanzen...)
Statische Variablen solltest Du sein lassen - das führt meist nur zu Problemen.
Dann hast Du ggf. etwas wie:
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class LagerVerwaltungApp extends Application{
private Main_Controller meinController;
@Override
public void start(Stage mainStage) throws Exception {
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
Parent root = meinLoader.load();
meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
Scene mainScene = new Scene(root, 1000, 600);
mainStage.setTitle("Main Lagerverwaltung");
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest( () -> close() ); // Ist sowas notwendig?
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
mainStage.show();
}
public static void close() {
Platform.exit();
}
public static void main(String[] args) {
launch(args);
}
}
als ersten JavaFX Startpunkt.
So eine Überwachung oder was auch immer der Thread macht, hast Du dann in einer anderen Klasse, also z.B. wie von mir skizziert in einer Klasse Ueberwachung. Das kannst Du dann mit einbauen:
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class LagerVerwaltungApp extends Application{
private Main_Controller meinController;
private Uberwachung ueberwachung;
@Override
public void start(Stage mainStage) throws Exception {
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
Parent root = meinLoader.load();
meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
Scene mainScene = new Scene(root, 1000, 600);
mainStage.setTitle("Main Lagerverwaltung");
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest( () -> close() ); // Ist sowas notwendig?
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
mainStage.show();
ueberwachung = new Ueberwachung();
ueberwachung.start();
ueberwachung.addPropertyListener(meinController::bearbeiteUeberwachungsPropertyChanges);
}
public static void close() {
Platform.exit();
}
public static void main(String[] args) {
launch(args);
}
}
Das setzt jetzt voraus, dass der Controller eine Methode bearbeiteUeberwachungsPropertyChanges hat, die ein PropertyChangeEvent als Parameter entgegen nimmt.
==> Da hast Du dann im Controller eine Stelle, die auf erkannte Veränderungen reagieren kann.
Was ich auch raus genommen habe, ist Dein Array mit irgendwelchen Daten. Daten sind ordentlich, unabhängig von JavaFX Applikation / Controllern und Co zu verwalten. Also auch eine eigene Klasse mit einer eigenen Instanz. Die kannst Du da auch in start dann initialisieren und Du kannst die dann z.B. an den Controller geben oder so. Aber das ist nicht in der Application Klasse.
Du hast in der Regel pro Scene einen Controller. Wenn Du in einer Scene ein anderes fxml lädst, dann kannst Du das als eine Einheit ansehen, die einen eigenen Controller hat. Aber das Übliche ist - gerade am Anfang - ein Controller pro Scene.
public class Lagerverwaltung_MainGUI extends Application{
private static Lagerverwaltung_MainProgramm startMain;
public static void main(String[] args) {
startMain = new Lagerverwaltung_MainProgramm(); // würde auch nicht in der start Mehode gehen static und new past nicht zusammen.
Thread t = new Thread(startMain); // create thread
t.start(); // start thread
launch(args);
}
}
Kannst Du Dir angewöhnen, bitte klare Aussagen zu machen? Hier muss man raten, was Du überhaupt sagen willst.
a) Natürlich geht das - Du kannst in einer nicht statischen Methode einer statischen Variable eine neue Instanz zuweisen. Daher ist die Aussage, dass sowas in der start Methode nicht geht, schlicht falsch.
b) wenn es sich auf meine Aussagen bezieht: Da ist klar gesagt, dass die Variable eben nicht statisch sein sollte:
Was ich auch raus genommen habe, ist Dein Array mit irgendwelchen Daten. Daten sind ordentlich, unabhängig von JavaFX Applikation / Controllern und Co zu verwalten. Also auch eine eigene Klasse mit einer eigenen Instanz. Die kannst Du da auch in start dann initialisieren und Du kannst die dann z.B. an den Controller geben oder so. Aber das ist nicht in der Application Klasse.
Bei der Aussage ist es irrelevant, was genau das für Daten sind. Daten sollten in einem Programm ordentlich verwaltet werden. Und das ist unabhängig von einer JavaFX Applikations Klasse. Damit gehört das von mir aus in eine Klasse Lager a.la.
Java:
public class Lager {
public final static int LAGER_BREITE = 10;
public final static int LAGER_LAENGE = 100;
public final static int LAGER_HOEHE = 10;
private Lagerplatz[][][] lagerplaetze = new Lagerplatz[LAGER_BREITE][LAGER_LAENGE][LAGER_HOEHE];
// Methoden zum Zugriff die eben diese physische Speicherung der Daten kapseln.
}
Das die Dimensionen sowas wie Breite, Länge und Höhe sind, ist jetzt einfach mal eine wilde Unterstellung. Das kann irgendwas sein, dann werden die Konstanten halt umbenannt zu LAGER_WAS_AUCH_IMMER und so ...
Aber deutlich wird hoffentlich, dass hier Daten sauber gekapselt werden und Zugriffe über definierte Schnittstellen erfolgen.
Bei der Aussage ist es irrelevant, was genau das für Daten sind. Daten sollten in einem Programm ordentlich verwaltet werden. Und das ist unabhängig von einer JavaFX Applikations Klasse. Damit gehört das von mir aus in eine Klasse Lager a.la.
Das hat keiner angezweifelt. Das war nur ein Hinweis was die Daten bedeuten sollen zu dir. Mehr nicht.
Das sie an der stelle falsch sind , ist klar hattest du ja schon gesagt.
Etwa mit den flaschen Bein aufgestanden. 😀
Nicht aufregen immer weiter atmen würden Taucher sagen. 🤿 🐟🐬
Sorry, aber ich rege mich nicht auf. Ich verstehe nur eben in keiner Weise, was Du beitragen willst.
Bei #19 hast Du einfach einen kleinen Kommentar im Code hinzugefügt - worauf Du hinaus wolltest, weiss ich immer noch nicht und Du willst das nicht erläutern.
Dein Hinweis in #22 zitiert meine Aussage, die in erster Linie aussagt, dass da etwas sauber getrennt werden soll. Das ist die Aussage. Nichts anderes. Das sind irgendwelche Daten. Was, spielt keine Rolle. Und nein - ich bezweifle, dass da die SPS Daten rein schreibt. Denn er will ja in einem Thread die SPS auswerten. Also wird da eher eine Komponente Daten aus der SPS auslesen, diese irgendwohin geben damit diese dann im Datenbestand abgelegt werden. Das sind und bleiben aber irgendwelche Daten (die Klasse Lagerplatz kennen wir halt nicht).
Ich sehe also bei Deinem Hinweis auch hier nicht wirklich einen besonderen Sinn. Ich bezweifle, dass dies dem TE weiter helfen wird. Wenn Du mir irgendwie hier weiter helfen wolltest mit irgendwelchen Informationen, dann muss ich Dich auch enttäuschen. Auch das ist nicht der Fall.
Alles, was Du mit Deinen Kommentaren in #19 und #22 erreicht hast: Du hast es geschafft, mich in so fern zu triggern, das ich darüber nachgedacht habe, was Du evtl. meinen könntest. Um das dann zu hinterfragen (worauf von Dir keine Antwort gekommen ist) bzw. meine Aussage noch einmal zu erläutern (Weil Du da ja etwas von mir zitiert hast und ich davon ausgegangen bin, dass sich Deine neue Aussage auf meine Aussage bezieht). Um dann so einen Kommentar, wie da oben zitiert, zu bekommen? Ich bin weder mit dem falschen Bein aufgestanden noch rege ich mich auf. Ich frage mich aber: Denkst Du nicht darüber nach, was Du wem genau mitteilen willst? Was hilfreich sein könnte (oder eben nicht)? Um dann eine verständliche Antwort zu schreiben? Das wäre etwas, das ich mir von Dir etwas mehr wünschen würde.
Mit #19 gebe ich dir recht habe ja auch ein "oh" gegeben. Ja man kann eine static variable mit einen new initialisiert.
Und sein Code Versuch sieht für mich so aus als ob er die Sps in das Array schreiben lassen will oder wollte tut.
Da es static ist und somit auch aus einer anderen Klasse, Thread... Benutzt werden kann. Ja Package ich weiß.
Ob das wirklich so ist er so wollte, solte der TE beantworten. Hier weiter zu spekulieren macht keinen Sinn.
Wenn es die Daten von der Sps sind. Dann wäre es sinnvoll zu zeigen wie mit welchen Möglichkeiten er sie beobachten kann und bei Veränderung anzuzeigen.
Ansatz weise hast du das ja getan.
Am Beispiel PropertyListener.
Ok wie gesagt das mein Programm nicht das beste ist, ist mir klar. Das da viel Luft nach oben ist...
Was ich aber halt ganz und gar nicht verstehe ist das mit dem JavaFX. Ich kenne das nur so:
Und da verstehe ich nicht wie ich zwischen 2 Fenstern und 2 Controllern hin und herswitche. Genauso verstehe ich dann nicht wo ich das launch aufrufe wenn nicht in der Main.
Java:
package lagerverwaltung;
import lagerverwaltung.hmi.Main_Controller;
import lagerverwaltung.lager.Lagerplatz;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.WindowEvent;
public class Lagerverwaltung_MainGUI extends Application{
private static Lagerverwaltung_MainProgramm startMain;
static Lagerplatz [] [] [] lagerplatz = new Lagerplatz[10][100][10];
@Override
public void start(Stage mainStage) throws Exception {
// eine Instanz von FXMLLoader erzeugen
FXMLLoader meinLoader = new FXMLLoader(getClass().getResource("/lagerverwaltung/hmi/Main.fxml"));
// die Datei laden
Parent root = meinLoader.load();
// den Controller beschaffen
Main_Controller meinController = meinLoader.getController();
meinController.setMeineStage(mainStage);
// die Szene erzeugen
Scene mainScene = new Scene(root, 1000, 600);
// den Titel über stage setzen
mainStage.setTitle("Main Lagerverwaltung");
// die Scene setzen
mainStage.setScene(mainScene);
mainStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent windowEvent) {
close();
}
});
//
int aktuellesBild = Lagerverwaltung_MainProgramm.getAktuellesBild();
int hilfsbild = Lagerverwaltung_MainProgramm.getHilfsbild();
System.out.println(" HilfsbildNr: " + hilfsbild);
// Größe nicht veränderbar und ohne Menüleiste anzeigen
mainStage.initStyle(StageStyle.UNDECORATED);
mainStage.setResizable(true);
// und anzeigen
mainStage.show();
}
// on close
public static void close() {
startMain.stop();
Platform.exit();
}
public static void main(String[] args) {
startMain = new Lagerverwaltung_MainProgramm();
Thread t = new Thread(startMain); // create thread
t.start(); // start thread
launch(args);
}
}
also ich habe z.B. nur eine Stage in welcher ich unterschiedliche StackPanes per "visible" Eigenschaft anzeige. Das könnte dir die Sache eventuell auch erleichtern. Funktioniert relativ einfach sofern die anzuzeigenden Oberflächen die gleiche Größe und nur unterschiedlichen Inhalt besitzen.
Arbeitest du mit dem Scenebuilder ist es etwas umständig, da du hier die "visible" Eigenschaft immer händisch setzen musst um die einzelenen Panes zu bearbeiten und diese auch nicht übereinander gelegt angezeigt zu bekommen.