是否有可能在JavaFX的在AWT改变焦点遍历策略 ,怎么样?
因为两个我的遍历顺序HBox
ES是错误的。
是否有可能在JavaFX的在AWT改变焦点遍历策略 ,怎么样?
因为两个我的遍历顺序HBox
ES是错误的。
在普通情况下,导航在容器中以便根据箭头键按下进行,在儿童的顺序,或。 您可以更改节点的顺序 - 它会为你在这种情况下的最佳解决方案。
有一个在JFX后门约穿越引擎战略替代:
你也可以继承内部类com.sun.javafx.scene.traversal.TraversalEngine
engine = new TraversalEngine(this, false) {
@Override public void trav(Node owner, Direction dir) {
// do whatever you want
}
};
和使用
setImpl_traversalEngine(engine);
调用应用该引擎。
你可以观察的OpenJFX的代码,理解,它是如何工作的,以及你可以做什么。
要非常小心:这是一个内部API,它很可能会改变,可能的话,在不久的将来。 所以不要依赖这个(你不能靠这个officialy,反正)。
示例实现:
public void start(Stage stage) throws Exception {
final VBox vb = new VBox();
final Button button1 = new Button("Button 1");
final Button button2 = new Button("Button 2");
final Button button3 = new Button("Button 3");
TraversalEngine engine = new TraversalEngine(vb, false) {
@Override
public void trav(Node node, Direction drctn) {
int index = vb.getChildren().indexOf(node);
switch (drctn) {
case DOWN:
case RIGHT:
case NEXT:
index++;
break;
case LEFT:
case PREVIOUS:
case UP:
index--;
}
if (index < 0) {
index = vb.getChildren().size() - 1;
}
index %= vb.getChildren().size();
System.out.println("Select <" + index + ">");
vb.getChildren().get(index).requestFocus();
}
};
vb.setImpl_traversalEngine(engine);
vb.getChildren().addAll(button1, button2, button3);
Scene scene = new Scene(vb);
stage.setScene(scene);
stage.show();
}
这将需要对常见的情况强analitical技能;)
最简单的办法是编辑文件FXML并适当地重新排列容器。 作为一个例子,我的当前应用具有其中可以输入序列号登记对话框。 有此目的的5个文本字段。 对于焦点从一个文本字段正确地传递给对方,我必须列出他们以这种方式:
<TextField fx:id="tfSerial1" layoutX="180.0" layoutY="166.0" prefWidth="55.0" />
<TextField fx:id="tfSerial2" layoutX="257.0" layoutY="166.0" prefWidth="55.0" />
<TextField fx:id="tfSerial3" layoutX="335.0" layoutY="166.0" prefWidth="55.0" />
<TextField fx:id="tfSerial4" layoutX="412.0" layoutY="166.0" prefWidth="55.0" />
<TextField fx:id="tfSerial5" layoutX="488.0" layoutY="166.0" prefWidth="55.0" />
Bluehair的答案是正确的,但你甚至可以在JavaFX的场景生成器做到这一点。
您在左列层次面板。 有来自现场所有组件。 他们为了表示焦点遍历顺序并响应其在FXML文件顺序。
我发现该网页上的这个提示: www.wobblycogs.co.uk
这是公认的答案适用于改变内部的API(在FX-8的某一点发生了,我现在的版本是8u60b5)。 显然,原来的免责声明仍然适用:它的内部 API,开放在任何时候,恕不另行通知更改!
的变化(相对于公认的答案)
示例代码平原翻译:
/**
* Requirement: configure focus traversal
* old question with old hack (using internal api):
* http://stackoverflow.com/q/15238928/203657
*
* New question (closed as duplicate by ... me ..)
* http://stackoverflow.com/q/30094080/203657
* Old hack doesn't work, change of internal api
* rewritten to new internal (sic!) api
*
*/
public class FocusTraversal extends Application {
private Parent getContent() {
final VBox vb = new VBox();
final Button button1 = new Button("Button 1");
final Button button2 = new Button("Button 2");
final Button button3 = new Button("Button 3");
Algorithm algo = new Algorithm() {
@Override
public Node select(Node node, Direction dir,
TraversalContext context) {
Node next = trav(node, dir);
return next;
}
/**
* Just for fun: implemented to invers reaction
*/
private Node trav(Node node, Direction drctn) {
int index = vb.getChildren().indexOf(node);
switch (drctn) {
case DOWN:
case RIGHT:
case NEXT:
case NEXT_IN_LINE:
index--;
break;
case LEFT:
case PREVIOUS:
case UP:
index++;
}
if (index < 0) {
index = vb.getChildren().size() - 1;
}
index %= vb.getChildren().size();
System.out.println("Select <" + index + ">");
return vb.getChildren().get(index);
}
@Override
public Node selectFirst(TraversalContext context) {
return vb.getChildren().get(0);
}
@Override
public Node selectLast(TraversalContext context) {
return vb.getChildren().get(vb.getChildren().size() - 1);
}
};
ParentTraversalEngine engine = new ParentTraversalEngine(vb, algo);
// internal api in fx8
// vb.setImpl_traversalEngine(engine);
// internal api since fx9
ParentHelper.setTraversalEngine(vb, engine);
vb.getChildren().addAll(button1, button2, button3);
return vb;
}
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent()));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
我们使用JavaFX的事件过滤器对于这一点,例如:
cancelButton.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.TAB && event.isShiftDown()) {
event.consume();
getDetailsPane().requestFocus();
}
}
});
该event.consume()
抑制默认焦点遍历,当调用否则会造成麻烦requestFocus()
。
在现场建设者进入查看菜单,然后选择显示文件。 在左侧会以您目前FXML文档中的所有对象。 拖动控制向上或向下在列表中重新排序的选项卡索引。 选择隐藏文件使用其他工具,因为文档窗格猪的空间。
我用Eventfilter作为解决方案结合引用字段的ID的,因此,所有你需要做的就是类似名称的字段(字段1,字段2,字段3,字段4),所以你可以把其中u想要的字段:
mainScene.addEventFilter(KeyEvent.KEY_PRESSED, (event) -> {
if(event.getCode().equals(KeyCode.TAB)){
event.consume();
final Node node = mainScene.lookup("#field"+focusNumber);
if(node!=null){
node.requestFocus();
}
focusNumber ++;
if(focusNumber>11){
focusNumber=1;
}
}
});
您可以使用NodeName.requestFocus()
就像上面说; 此外,一定要索取这个重点实例,并添加所有的根布局的节点,因为当你这样做时,焦点将转换后。
你可以很容易地SceneBuilder做到这一点。 与scenebuilder打开FXML文件,然后转到层次 文档选项卡下。 将输入控件到你想要通过拖动输入控制器的订单。 记住要检查焦点遍历的性质。 然后集中,当你按下标签栏遍历政策将很好地工作。