时,当你创建一个文本区域,你可以聆听到它的“focusedProperty”。文本区松重点使用滚动条
但是,如果用户触摸文本区域内滚动条(如果它太小),TextArea的焦点丢失(因为滚动条具有焦点)。
但就我个人而言,textarea里仍然有焦点,因为滚动条的部分或文本区域甚至还有无法访问它们的方式。
如何破解我的textarea的,这样,当用户使用滚动我会发现?我想破解/创建一个focusedProperty,当用户输入文本或使用scrollBar时,它将返回true。
时,当你创建一个文本区域,你可以聆听到它的“focusedProperty”。文本区松重点使用滚动条
但是,如果用户触摸文本区域内滚动条(如果它太小),TextArea的焦点丢失(因为滚动条具有焦点)。
但就我个人而言,textarea里仍然有焦点,因为滚动条的部分或文本区域甚至还有无法访问它们的方式。
如何破解我的textarea的,这样,当用户使用滚动我会发现?我想破解/创建一个focusedProperty,当用户输入文本或使用scrollBar时,它将返回true。
观察Scene
的focusOwner
财产,并创建一个BooleanBinding
这是真的,如果它是文本的区域,否则假的后代:
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TextAreaFocusTest extends Application {
@Override
public void start(Stage primaryStage) {
TextArea textArea = new TextArea();
IntStream.rangeClosed(1, 200).forEach(i -> textArea.appendText(" "));
IntStream.rangeClosed(1, 80).forEach(i -> textArea.appendText("\nLine "+i));
Label label = new Label();
TextField textField = new TextField();
VBox root = new VBox(10, textArea, textField, label);
Scene scene = new Scene(root, 400, 400);
BooleanBinding focus = Bindings.createBooleanBinding(() -> {
for (Node n = scene.getFocusOwner(); n!= null ; n=n.getParent()) {
if (n == textArea) return true ;
}
return false ;
}, scene.focusOwnerProperty());
label.textProperty().bind(Bindings.when(focus).then("Focused").otherwise("Not Focused"));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这里是@ James_D的答案的变化,以防您需要能够从他的答案中获得focus
绑定,而无需参考场景,例如如果您需要在将文本区域添加到场景之前设置绑定,则正在实现一个库,或者只是想让您的代码纠结得更少。
此解决方案使用EasyBind库方便地选择嵌套属性(从sceneProperty
中选择focusOwnerProperty
)。
public static Binding<Boolean> containsFocus(Node node) {
return EasyBind.monadic(node.sceneProperty())
.flatMap(Scene::focusOwnerProperty)
.map(owner -> {
for (Node n = owner; n != null; n = n.getParent()) {
if (n == node) return true ;
}
return false ;
})
.orElse(false); // when node.getScene() is null
}
感谢您的答复。可以肯定的是,每次场景焦点所有者都会改变时,CallBack会被调用吗? – Maxoudela 2014-09-30 15:17:41
每次场景的焦点所有者改变时,'BooleanBinding'('focus')的值将被重新计算。 (实际上,这并不是真的,但实际上它是真的......)如果你用这个'BooleanBinding'注册一个监听器,那么只要它的值发生改变,该监听器就会被调用。如果绑定到该'BooleanBinding'(就像我在示例中对标签的文本属性所做的那样),那么绑定到它的属性将在其值更改时重新计算。 – 2014-09-30 15:40:26
另请参阅我对詹姆斯的回答的详细论述,即使场景发生变化也能使此工作成功,例如当在场景中添加“textArea”之前设置绑定时,或者在场景之间移动“textArea”时(不太可能)。 – 2014-09-30 15:43:17