JavaFX Erste Versuche mit Data-Binding

Nemesys88

Bekanntes Mitglied
Guten Abend!

Ich probiere grade ein bisschen mit Data-Bindings herum und versuche folgende Funktionalität zu erreichen:

Java:
button.prefWidthProperty().bind(tf.textProperty());

(musste auch erstmal herausfinden das man nur prefWidthProperty verändern kann und nicht WidthProperty so wie man meinen könnte)

Das geht so natürlich nicht weil man 2 verschiedene Datentypen hat.

Hab jetzt inzwischen herausgefunden, dass es bi-direktional so geht:

Java:
Bindings.bindBidirectional(tf.textProperty(), button.prefWidthProperty(), new NumberStringConverter());

Aber wie lautet der korrekte Befehl wenn ich nur eine Richtung haben will ?
(nach Eingabe im Textfeld soll sich die Button-Width ändern)
 
Nein, das hilft mir leider nicht weiter... oder ich überseh die entsprechende Zeile grade... aber ich probier hier auch schon seit 1,5 Stunden rum und hab das Internet gleich ausgelesen... 😀
 
In diesem Fall wahrscheinlich nicht weil es nur ein ganz einfacher Test ist um die Funktionalität zu verstehen... aber würd ich zb. sagen wollen "wenn ich die Fensterbreite änder soll er die Buttonbreite auch ändern", und dann hängt das TextField da noch dran.. hab ich schon nen Problem..
 
Jetzt dacht ich grad ich hätt's geschafft...

Java:
		tf.setOnKeyReleased(e -> {
			if (!tf.getText().trim().isEmpty())
			{
				simple = new SimpleIntegerProperty(Integer.parseInt(tf.getText()));
				button.prefWidthProperty().bind(simple);
			}
		});

aber ich wunder mich grad, dass er beim Resizen des Buttons auch das TextField auf dieselbe Größe bringt, obwohl ich kein bidirektionales Binding verwendet hab oO
 
Irgendwie muss das doch machbar sein, auch mit nem unidirektionalen Binding:

Java:
button.prefWidthProperty().bind(tf.textProperty());
 
Sicher geht das. Du musst dir nur dein eigenes Binding dafür schreiben.

Java:
import java.util.concurrent.Callable;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class BindingApp extends Application {

  @Override
  public void start(Stage primaryStage) throws Exception {
    TextField widthField = new TextField();
    Button button = new Button("Button");

    DoubleBinding db = Bindings.createDoubleBinding(new Callable<Double>() {

      @Override
      public Double call() throws Exception {
        Double width;
        try {
          width = Double.valueOf(widthField.getText());
        } catch (Exception e) {
          width = -1d;
        }
        return width;
      }
    }, widthField.textProperty());

    button.prefWidthProperty().bind(db);

    VBox root = new VBox(widthField, button);
    primaryStage.setScene(new Scene(root));
    primaryStage.show();
  }

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

}
 
Das liegt wohl daran, das eben auch das Textfeld an das darüberliegende Layout gebunden ist.
Mit den wenigen Code-Schnipseln hier ist es aber auch schwierig, eine gute Aussage zu treffen, was bei dir der Grund für deine Missverständnisse ist...
 
Okay, vielen Dank erstmal!

Das sich das TextField ebenfalls anpasst liegt tatsächlich daran, dass label,tf und Button zusammen in ner VBox liegen.

Lagert man das TF aus so funktioniert sowohl meine Version:

Java:
		simple = new SimpleIntegerProperty();
			
		tf.setOnKeyReleased(e -> {
			if (!tf.getText().trim().isEmpty())
			{
				simple.set(Integer.parseInt(tf.getText()));
			}
		});
		
		button.prefWidthProperty().bind(simple);

als auch die Version von Flown mit dem selbstgeschriebenen Binding in gleicher Art und Weise.

Find ich aber ehrlich gesagt arg unglücklich gelöst (von oracle), dass sich dann durch das Binding alle Komponenten in der VBox automatisch anpassen...

Davon abgesehen das man sich erst so ne Lösung bauen muss, wo nen Binding mit gleichen Datentypen wie zb:

Java:
button.prefWidthProperty().bind(label1.widthProperty());

mit einer Zeile Code erledigt ist... 😀
 
Warum ist das unglücklich gelöst??? Du veränderst du Breite eines Elements in dem Layout, erwartest aber, dass die anderen davon unberührt bleiben? Das wäre erst recht unlogisch! Das ist doch gerade die Aufgabe vom Layout, dass es alle seine Elemente ordentlich layoutet...
 

Zurück
Oben