2014-09-30 24 views
0

时,当你创建一个文本区域,你可以聆听到它的“focusedProperty”。文本区松重点使用滚动条

但是,如果用户触摸文本区域内滚动条(如果它太小),TextArea的焦点丢失(因为滚动条具有焦点)。

但就我个人而言,textarea里仍然有焦点,因为滚动条的部分或文本区域甚至还有无法访问它们的方式。

如何破解我的textarea的,这样,当用户使用滚动我会发现?我想破解/创建一个focusedProperty,当用户输入文本或使用scrollBar时,它将返回true。

回答

1

观察ScenefocusOwner财产,并创建一个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); 
    } 
} 
+0

感谢您的答复。可以肯定的是,每次场景焦点所有者都会改变时,CallBack会被调用吗? – Maxoudela 2014-09-30 15:17:41

+0

每次场景的焦点所有者改变时,'BooleanBinding'('focus')的值将被重新计算。 (实际上,这并不是真的,但实际上它是真的......)如果你用这个'BooleanBinding'注册一个监听器,那么只要它的值发生改变,该监听器就会被调用。如果绑定到该'BooleanBinding'(就像我在示例中对标签的文本属性所做的那样),那么绑定到它的属性将在其值更改时重新计算。 – 2014-09-30 15:40:26

+0

另请参阅我对詹姆斯的回答的详细论述,即使场景发生变化也能使此工作成功,例如当在场景中添加“textArea”之前设置绑定时,或者在场景之间移动“textArea”时(不太可能)。 – 2014-09-30 15:43:17

1

这里是@ 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 
}