JavaFX绑定宽高是一种技术,可以让你在JavaFX应用程序中自动调整控件的大小。它可以帮助你创建更具响应性的用户界面,使用户能够在不同分辨率的屏幕上看到相同的内容。
JavaFX绑定宽高可以通过使用bind()方法来实现,该方法允许你将一个控件的大小与另一个控件的大小保持同步。例如,你可以将一个文本字段的宽度与另一个文本字段的宽度保持同步:
textField1.widthProperty().bind(textField2.widthProperty());
这样,当textField2的大小发生变化时,textField1也会随之而变化。此外,你还可以使用bindBidirectional()方法来将两个文本字段的大小保持同步:
Bindings.bindBidirectional(textField1.widthProperty(), textField2.widthProperty());
这样,当textField1或textField2的大小发生变化时,另一个也会随之而变化。此外,你还可以使用bindContent()方法来将文本字段中显示的内容保持同步。例如:
Bindings.bindContent(textField1.textProperty(), textField2.textProperty());
这样,当文本字段中显示的内容发生变化时(例如用户在其中输入了新内容),该内容也会在其他文本字段中显示出来。JavaFX绑定宽高是一项强大而弹性的功能;通过使用诸如bind()、bindBidirectional()和bindContent()之类的方法来创建响应式界面是很重要的。
JavaFX绑定同步两个值:当因变量更改时,其他变量更改。
要将属性绑定到另一个属性,请调用bind()方法,该方法在一个方向绑定值。例如,当属性A绑定到属性B时,属性B的更改将更新属性A,但不是相反。
JavaFX提供了许多绑定选项,以便在域对象和GUI控件中的属性之间进行同步。
我们可以在JavaFX的属性API中使用以下三种绑定策略:
javafx.beans.binding.*
中定义的绑定对象进行低级绑定。
双向绑定绑定相同类型的属性,并同步两侧的a值。
当与bindBidirectional()方法双向绑定时,需要两个属性都必须是可读/可写的。
以下代码显示如何在firstName属性和字符串属性变量之间进行双向绑定
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; public class Main { public static void main(String[] args) { User contact = new User("Jame", "Bind"); StringProperty fname = new SimpleStringProperty(); fname.bindBidirectional(contact.firstNameProperty()); contact.firstNameProperty().set("new value"); fname.set("New First Name"); System.out.println("firstNameProperty = " + contact.firstNameProperty().get()); System.out.println("fname = " + fname.get()); } } class User { private SimpleStringProperty firstName = new SimpleStringProperty(); private SimpleStringProperty lastName = new SimpleStringProperty(); public User(String fn, String ln) { firstName.setValue(fn); lastName.setValue(ln); } public final String getFirstName() { return firstName.getValue(); } public StringProperty firstNameProperty() { return firstName; } public final void setFirstName(String firstName) { this.firstName.setValue(firstName); } public final String getLastName() { return lastName.getValue(); } public StringProperty lastNameProperty() { return lastName; } public final void setLastName(String lastName) { this.lastName.setValue(lastName); } }
上面的代码生成以下结果。
我们还可以使用JavaFX fluent API来绑定属性。流利的API使用类似英语的方法名称对属性执行操作。
例如,multiply(),divide(),subtract(),isEqualTo(),isNotEqualTo(),concat()。请注意,方法名称中没有get或set。当链接流畅的API在一起,我们可以编写代码,如同我们正在写句子,例如 width().multiply(height()).divide(2)
。
以下代码显示如何创建表示计算矩形面积的公式的属性。
它通过使用 javafx.beans.binding.IntegerExpression
接口中的fluent API来执行高级绑定。
该代码使用 multiply()
方法,该方法返回包含计算值的NumberBinding。
这种绑定是延迟评估的,这意味着乘法不会发生,除非我们通过 get()
或 getValue()
方法调用属性的值。
import javafx.beans.binding.NumberBinding; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; public class Main { public static void main(String[] args) { // Area = width * height IntegerProperty width = new SimpleIntegerProperty(10); IntegerProperty height = new SimpleIntegerProperty(10); NumberBinding area = width.multiply(height); System.out.println(area.getValue()); } }
上面的代码生成以下结果。
当对 NumberBinding
类进行子类化时,我们使用低级绑定,例如Double类型的DoubleBinding类。
在DoubleBinding类的子类中,我们重写其 computeValue()
方法,以便我们可以使用运算符(如*
和 -
)来制定复杂的数学方程。
高级绑定使用诸如multiply(),subtract()等方法低级绑定使用诸如*和 - 之类的运算符。
以下代码显示如何为公式创建低级别绑定以计算矩形的面积。
import javafx.beans.binding.DoubleBinding; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; public class Main { public static void main(String[] args) { DoubleProperty width = new SimpleDoubleProperty(2); DoubleProperty height = new SimpleDoubleProperty(2); DoubleBinding area = new DoubleBinding() { { super.bind(width, height); // initial bind } @Override protected double computeValue() { return width.get() * height.get(); } }; System.out.println(area.get()); } }
上面的代码生成以下结果。
在JavaFX中,UI控件和域模型之间的数据绑定很容易。以下代码显示如何创建登录对话框并绑定用户域对象。
首先,我们定义域对象,它是描述用户名和密码的JavaFX JavaBean。
class User { private final ReadOnlyStringWrapper userName; private StringProperty password; public User() { userName = new ReadOnlyStringWrapper(this, "userName", "ABC"); password = new SimpleStringProperty(this, "password", ""); } public final String getUserName() { return userName.get(); } public ReadOnlyStringProperty userNameProperty() { return userName.getReadOnlyProperty(); } public final String getPassword() { return password.get(); } public StringProperty passwordProperty() { return password; } }
我们创建了两个UI控件,一个是用Text控件显示用户名,另一个是PasswordField控件,它将输入值绑定到域对象中的密码字段。
Text userName = new Text(); userName.textProperty().bind(user.userNameProperty()); PasswordField passwordField = new PasswordField(); passwordField.setPromptText("Password"); user.passwordProperty().bind(passwordField.textProperty());
BooleanProperty accessGranted在passwordField的文本值属性的更改侦听器中设置。
passwordField.textProperty().addListener((obs, ov, nv) -> { boolean granted = passwordField.getText().equals(MY_PASS); accessGranted.set(granted); if (granted) { primaryStage.setTitle(""); } });
在enter键hit事件中访问BooleanProperty accessGranted。
// user hits the enter key passwordField.setOnAction(actionEvent -> { if (accessGranted.get()) { System.out.println("granted access:"+ user.getUserName()); System.out.println("password:"+ user.getPassword()); Platform.exit(); } else { primaryStage.setTitle("no access"); } });
完整的源代码。
import javafx.application.Application; import javafx.application.Platform; import javafx.beans.property.BooleanProperty; import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.PasswordField; import javafx.scene.layout.VBox; import javafx.scene.text.Text; import javafx.stage.Stage; public class Main extends Application { private final static String MY_PASS = "asdf"; private final static BooleanProperty accessGranted = new SimpleBooleanProperty(false); @Override public void start(Stage primaryStage) { User user = new User(); Group root = new Group(); Scene scene = new Scene(root, 320, 100); primaryStage.setScene(scene); Text userName = new Text(); userName.textProperty().bind(user.userNameProperty()); PasswordField passwordField = new PasswordField(); passwordField.setPromptText("Password"); user.passwordProperty().bind(passwordField.textProperty()); // user hits the enter key passwordField.setOnAction(actionEvent -> { if (accessGranted.get()) { System.out.println("granted access:"+ user.getUserName()); System.out.println("password:"+ user.getPassword()); Platform.exit(); } else { primaryStage.setTitle("no access"); } }); passwordField.textProperty().addListener((obs, ov, nv) -> { boolean granted = passwordField.getText().equals(MY_PASS); accessGranted.set(granted); if (granted) { primaryStage.setTitle(""); } }); VBox formLayout = new VBox(4); formLayout.getChildren().addAll(userName, passwordField); formLayout.setLayoutX(12); formLayout.setLayoutY(12); root.getChildren().addAll(formLayout); primaryStage.show(); } public static void main(String[] args) { launch(args); } } class User { private final ReadOnlyStringWrapper userName; private StringProperty password; public User() { userName = new ReadOnlyStringWrapper(this, "userName", "ABC"); password = new SimpleStringProperty(this, "password", ""); } public final String getUserName() { return userName.get(); } public ReadOnlyStringProperty userNameProperty() { return userName.getReadOnlyProperty(); } public final String getPassword() { return password.get(); } public StringProperty passwordProperty() { return password; } }
上面的代码生成以下结果。
JavaFX教程 -JavaFX按钮当用户单击按钮时,JavaFX Button类可以触发事件。Button类扩展标记的类,它可以显示文本,图像,或两者...
JavaFX教程 -JavaFX 文本字段TextField用于单行文本输入。import javafx.application.Application;import javafx.geometry.Inset...
JavaFX教程 -JavaFX渐变颜色我们可以使用径向渐变使形状看起来三维。梯度绘制可以在两种或更多种颜色之间内插,这给出形状的深度...
JavaFX教程 -JavaFX 滚动条ScrollBar类经常带有一个可滚动的窗格。import javafx.application.Application;import javafx.geomet...