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.
Zugriff auf Bildschirmobjekte aus einem anderen Programm
Hallo,
habe in einem Programm Bildschirmobjekte wie Label, Textfield usw.
private Label anzeige
private Textfield eingabe
Besteht eine Möglichkeit von einem zweiten Programm auf diese Objekte
zu zugreifen?
Also z.B. den Text des Labels zu ändern oder so, mit anzeige.setText().
Einfach auf public setzen geht nicht.
Erst einmal gehe ich davon aus, dass Du nicht Programm sondern Fenster meinst. (So wie Du in Deiner Anwendung Vital 4 weitere Fenster hast, die Du bei Bedarf modal öffnest. Es ist alles ein Programm aber Du hast mehrere Fenster.)
Ja, prinzipiell kannst Du auch auf Elemente von anderen Fenstern zugreifen. Dazu brauchst Du prinzipiell nur eine Referenz auf den entsprechenden Controller und die Elemente müssten public sein.
Aber: Das ist nichts, das man machen sollte! Eigentlich sollte die eigentlichen Daten und die Logik unabhängig von der Oberfläche sein. Dann können sich die Daten ändern und Komponenten, die sich für eine solche Information interessieren, werden dann informiert (Das wäre dann das Observer Pattern). In JavaFX ist da schon sehr viel vorhanden für. So kannst Du z.B. hin gehen und eine Klasse haben, dass die Daten hält. Nehmen wir einfach nur ein kleines Beispiel:
Java:
public class Model {
private StringProperty vorname = new SimpleSringProperty();
public StringProperty getVornameProperty() {
returnvorname;
}
}
Wenn Du nun irgendwo ein Fenster erzeugst, dann hast Du bei Dir immer mehrere Schritte beim Laden:
FXMLLoader erzeugen
fxml laden
Controller geben lassen.
Da würdest Du halt dann noch im Controller eine Methode haben setModel(Model) oder so in dem DU das model setzt.
Zusätzlich kannst Du dann noch ein sogenanntes Binding zu einem Control machen. Du kannst also etwas sagen wie:
Wenn sich das Eine ändert, dann soll sich auch das Andere ändern (Dann gehen Änderungen nur in eine Richtung)
Änderung in beide Richtungen: Egal was sich ändert: Es soll sich auch der andere Wert ändern.
Wenn Du jetzt zwei Fenster hast, die beide den Vorname anzeigen: Dann müssen sich diese Fenster nicht kennen. Sie arbeiten beide einfach auf dem gleichen Model und haben dann z.B. ein Bidirektionales Binding.
Wenn Du dann den Wert im Textfeld des ersten Fensters änderst, dann:
ändert sich auch der Wert im Model
Und dann ändert sich auch der Wert im zweiten Textfenster.
Anders herum natürlich auch und wenn Du den Wert direkt im Model setzt, dann ändert sich automatisch der Wert in den beiden Textfeldern.
So reduziert sich die Komplexität massiv und Deine Fenster müssen sich nicht untereinander kennen.
(Die Bindings finden zwischen Properties statt. So hat ein Control sehr viele Properties, die man binden kann. Und eine Property ist z.B. das textProperty, welches hier benutzt würde.)
Hallo Konrad,
danke für deine Antwort.
Aber so war es nicht gemeint.
Ich möchte nicht von einem anderen Fenster aus auf Objekt im andernen fenster zugreifen,
sondern ich habe eine eigene class (File) mit der ich auf Objekte (Label, Textfield usw) im Controllerprogramm zugriefen möchte.
Beispiel:
in meinem Program VitalInsertController.java
@FXML
private Label anzeige15;
@FXML
private TextField eingabe21;
Nun möchte ich aus den Routinen im FensterFelder.java (Standard-Routinen)
z. B. den Text inder anzeige15 ändern also
VitalInsertController.anzeige15.setText("ABC");
Das geht nicht, weill ich im VitalInsertController das Label anzeige15 gar nicht angezeigt bekomme.
Auch in f2VarRout ist anzeige 15 nicht drin
f2VarRout kommt aus dem Programm VtalController.jan bei button1Clicked (f2VarRout = fxmlLoader.getController().
Und auch private Label anzeige15; auf public Label anzeige15; setzen geht nicht (mekert an muss auch static sein)
Und wenn ich private Label anzeige15; auf static public Label anzeige15; setze läuft der Label im Programm VitalInsertController nicht mehr richtig.
Das ist DeinMissverständnis. Du hast nur ein einziges Programm. Du hast ein Projekt und das baut genau ein einziges Programm. Und du startest dann dieses eine Programm. In dem Projekt hast Du dann diverse Dateien. Sowohl Java Klassen als auch Ressourcen (z.B. fxml Dateien).
Und in diesem einen Programm öffnest Du dann neue Fenster.... Und im Rahmen dessen lädst Du eine fxml Ressource im Rahmen dessen dann eine Controller Instanz (z.B. von deiner VitalInsertController Klasse) erstellt wird.
Du bist aber in einem Programm. Daher konntest Du auch auf die ganzen public static Variablen zugreifen, die Du so alles hast (oder hattest - ich bin nicht sicher, ob Du die Hinweise bezüglich dieser Variablen umgesetzt hast).
Du kannst das auch gerne prüfen: Starte die Anwendung und schau im Taskmanager nach: Öffnet sich ein weiterer Prozess, wenn Du z.B. das Insert Fenster öffnest? Nein, wie auch? Du startest ja keinen neuen Prozess (und damit wird kein neues Programm gestartet).
Hier ist also wichtig, dass Du die Begriffe richtig verwendest.
Und wie dann mit dem Binding vom Code her aussehen könnte, zeigt dieses Beispiel:
Java:
package de.kneitzel;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class BindingExampleApp extends Application {
StringProperty stringProperty = new SimpleStringProperty();
public static void createScene(Stage stage, String title, StringProperty stringProperty) {
TextField textField = new TextField();
Scene scene = new Scene(new BorderPane(textField), 300, 400);
textField.textProperty().bindBidirectional(stringProperty);
stage.setTitle(title);
stage.setScene(scene);
stage.show();
}
@Override
public void start(Stage primaryStage) {
createScene(primaryStage, "Erstes Fenster", stringProperty);
Stage stage = new Stage();
createScene(stage, "Zweites Fenster", stringProperty);
}
public static void main(String[] args) {
launch(args);
}
}
Hier hast Du die Werte der zwei TextFields immer auf dem Wert der StringProperty.
Das kann man jetzt noch weiter aufteilen:
Die StringProperty gehört in eine eigene Klasse und bildet dann mit das Model (oder ViewModel im MVVM Pattern).
Das Binding gehört dann in eine Methode setModel die dann in etwa sowas macht:
Java:
private Model model;
@FXML
TextField vornameField = new TextField();
public void setModel(Model model) {
this.model = model;
vornameField.textProperty().bindBidirectional(model.getVornameProperty());
// Weitere Bindings ...
// Oder wenn Du kein Control hast, dann kannst Du bei Änderungen auch eigene Dinge machen:
model.getVornameProperty().addListener((observable, oldValue, newValue) -> {
System.out.println("Vorname changed: " + newValue);
});
}
Damit haben deine Controller keine Abhängigkeiten untereinander - das macht es einfacherm was Änderungen angeht.
Statt dessen hast Du ein (View)Model und die Controller haben nur eine Abhängigkeit zu eben diesem.