Window
类不会公开用户数据的PFA属性,这意味着它不可直接观察.然而,Window#setUserData(Object)
方法有这个有点神秘的文档:
用于设置可以在以后检索的单个对象属性的方便方法.这在功能上相当于调用getProperties().put(对象键、对象值)方法.稍后可以通过调用getuserData()来检索该内容.
这似乎表明用户数据保存在Window#getProperties()
返回的ObservableMap
中.如果你查看the implementation,你会发现确实如此.不幸的是,用户数据输入的密钥是私有的.但您可以使用反射来获取密钥,或者更好地使用MapChangeListener
来捕获它.
一旦您拥有该密钥,您就可以使用Bindings#valueAt(ObservableMap, K)
来创建一个ObjectBinding
,该ObjectBinding
将始终报告最新的用户数据值.
这是一个使用MapChangeListener
来捕获密钥的示例.
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.collections.MapChangeListener;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.stage.Window;
public class Main extends Application {
// Make sure to keep a strong reference to the binding for as long as you need it.
private ObjectBinding<Object> userData;
@Override
public void start(Stage primaryStage) {
userData = userDataBinding(primaryStage);
// Note: Using _ for unused parameters was standardized in Java 22.
userData.addListener(
(_, oldVal, newVal) -> System.out.printf("User data: %s -> %s%n", oldVal, newVal));
// Type something into the TextField then press ENTER to see the example at work.
var field = new TextField();
field.setMaxWidth(Region.USE_PREF_SIZE);
field.setOnAction(
e -> {
e.consume();
primaryStage.setUserData(field.getText());
field.clear();
});
primaryStage.setScene(new Scene(new StackPane(field), 500, 300));
primaryStage.show();
}
private ObjectBinding<Object> userDataBinding(Window window) {
// Use array because local variables must be (effectively) final when used inside
// a lambda expression or anonymous class.
var keyHolder = new Object[1];
window
.getProperties()
.addListener(
new MapChangeListener<>() {
@Override
public void onChanged(Change<? extends Object, ? extends Object> change) {
keyHolder[0] = change.getKey();
// Only need to capture the key once.
change.getMap().removeListener(this);
}
});
var oldUserData = window.getUserData(); // save current value
window.setUserData(new Object()); // invoke the listener
window.setUserData(oldUserData); // restore to old value
return Bindings.valueAt(window.getProperties(), keyHolder[0]);
}
}
从文档来看,相同的方法可以用于Scene
和Node
.
当然,您可以使用自己的 keys 直接操作Window.getProperties()
map .这可能会更容易.