Ist es in JavaFX möglich, die Fokus-Traversal-Richtlinie zu ändern, wie in AWT?JavaFX: Wie ändere ich die Fokus-Traversal-Politik?
Weil die Traversierungsreihenfolge für zwei meiner HBox
es falsch ist.
Ist es in JavaFX möglich, die Fokus-Traversal-Richtlinie zu ändern, wie in AWT?JavaFX: Wie ändere ich die Fokus-Traversal-Politik?
Weil die Traversierungsreihenfolge für zwei meiner HBox
es falsch ist.
Im allgemeinen Fall erfolgt die Navigation in einer Containerreihenfolge, in der Reihenfolge der Kinder, oder entsprechend den Pfeiltasten. Sie können die Reihenfolge der Knoten ändern - dies ist in dieser Situation die optimale Lösung für Sie.
Es gibt eine Hintertür in JFX über Traversal Motorenstrategie Substitution:
können Sie die interne Klasse com.sun.javafx.scene.traversal.TraversalEngine Unterklasse
engine = new TraversalEngine(this, false) {
@Override public void trav(Node owner, Direction dir) {
// do whatever you want
}
};
Und verwenden
setImpl_traversalEngine(engine);
aufrufen, um diese Engine anzuwenden.
Sie können den Code von OpenJFX beobachten, um zu verstehen, wie es funktioniert und was Sie tun können.
Seien Sie sehr vorsichtig: es ist eine interne API, und es wird wahrscheinlich wahrscheinlich in der nächsten Zukunft ändern. Also verlasse dich nicht darauf (du kannst dich sowieso nicht darauf verlassen).
Beispielimplementierung:
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();
}
Es wird für gemeinsamen Fall stark analitical Fähigkeiten erfordern;)
die interne api scheint sich in fx8 erheblich geändert zu haben, nicht mehr möglich (wahrscheinlich muss man sich anpassen, indem man einen benutzerdefinierten Algorithmus implementiert, eine ParentFocusTraversalEngine damit konfiguriert) – kleopatra
Die einfachste Lösung ist die FXML Datei zu bearbeiten und die Behälter entsprechend neu anordnen. Als Beispiel hat meine aktuelle Anwendung einen Registrierungsdialog, in den eine Seriennummer eingegeben werden kann. Zu diesem Zweck gibt es 5 Textfelder. Für den Fokus von einem Textfeld auf den anderen richtig passieren, musste ich sie auf diese Weise zur Liste:
<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" />
Ja, das ist der einfachste Weg. Ich hatte das gleiche Problem. Das bedeutet, dass der UI-Szenen-Generator während der Entwicklung die relevanten FXML-Tags in add-hock-Reihenfolge neu generiert. Sobald wir sie richtig geordnet haben, funktioniert es gut. – Channa
Ich habe das gleiche hier gemacht, es funktioniert. – ceklock
Es wäre schön, wenn SB das automatisch für uns tun könnte. – User
Bluehair Antwort richtig ist, aber Sie können diese Builder auch in JavaFX Scene tun.
Sie haben Hierarchie-Panel in der linken Spalte. Es gibt alle deine Komponenten aus der Szene. Ihre Reihenfolge repräsentiert die Fokus-Traversierungsreihenfolge und sie antwortet auf ihre Reihenfolge in der FXML-Datei.
fand ich diesen Tipp auf dieser Webseite: www.wobblycogs.co.uk
In Szene Builder zur Ansicht Menü gehen und wählen Sie zeigen Dokument. Auf der linken Seite befinden sich alle Objekte in Ihrem aktuellen fxml-Dokument. Ziehen Sie die Steuerelemente in der Liste nach oben oder unten, um sie für den Registerindex neu anzuordnen. Wählen Sie Dokument ausblenden aus, um die anderen Tools zu verwenden, da der Dokumentbereich den Bereich beeinträchtigt.
Wir JavaFX event filters dafür verwenden, z.B .:
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();
}
}
});
Die event.consume()
unterdrückt den Standardfokus Traversal, die sonst Probleme verursacht, wenn requestFocus()
Aufruf.
Dies ist die akzeptierte Antwort angepasst an die Änderung der internen API (passiert an einem Punkt von fx-8, meine aktuelle Version ist 8u60b5).Offensichtlich gilt immer noch der ursprüngliche Disclaimer: es ist intern api, jederzeit ohne Vorankündigung zu ändern!
Die Änderungen (im Vergleich zu der akzeptierten Antwort)
Die einfache Übersetzung des Beispielcode:
/**
* 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);
vb.setImpl_traversalEngine(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);
}
}
Siehe ContainerTabOrder für ein Beispiel für einen vollständigen Algorithmus (muss in Children recursen). Aber es war zu komplex für mich, ich habe eine Umgehungslösung verwendet, um Schaltflächen in der Registerkarte Politik in FXML ohne Java-Code zu ignorieren: set 'focusTraversable =" false "'. Es wird mit dem nächsten fokussierbaren Element fortgesetzt. – pdem
I Eventfilter als Lösung in Kombination mit Verweis auf die Feld-IDs verwendet, so alles, was Sie tun müssen, ist die Felder wie (Feld1, Feld2, field3 nennen , field4), so können Sie die Felder platzieren, wo u wollen:
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;
}
}
});
Sie Fokus für jeden Knoten in javafx durch den Aufruf node.requestFocus() -Methode anfordern können – invariant
Ja, ich weiß, aber das ist nicht eine sehr saubere Lösung. – Sonja
Bitte stellen Sie Ihr Problem klar dar und geben Sie [sscce] (http://sscce.org/) an. – gontard