On Thu, 10 Oct 2024 21:32:29 GMT, Andy Goryachev <ango...@openjdk.org> wrote:
> > I did my best to actually find some use cases... > > Allow me to refer to some of the linked tickets in RFE > https://bugs.openjdk.org/browse/JDK-8090456: > > [JDK-8091524](https://bugs.openjdk.org/browse/JDK-8091524) Introduce a "focus > container" concept in class Parent > > [JDK-8091670](https://bugs.openjdk.org/browse/JDK-8091670) Add API for better > control over keyboard focus **JDK-8091524** - problem: User wants to create a panel that has its own focus cycle, and focus should not escape to other controls in the same Scene. I saw this issue and feel that it is a "WON'T FIX" as there are standard solutions for this already. It is clearly an X/Y problem. A common thing that trips up beginning FX developers is that they're unwilling to create a 2nd Scene or a Dialog and prefer to just "add a child somewhere to show some extra controls". This is not how you do this, and we shouldn't need to cater to something that is basically building a Dialog type infrastructure from scratch. How would this handle mouse clicks outside the "blessed" panel? Should that be restricted as well then? Possible ways to address this problem: use dialogs, use nested event loops, disable components that should not be part of the focus cycle temporarily, overlay a transparent pane blocking clicks, etc... but best option, just use a dialog... **JDK-8091670** - describes the same problem... Ensemble is not using the right tools to restrict focus. Use dialogs for this purpose. There is no need to restrict focus on container level. Again, what happens when focus is restricted to a container, and the user clicks outside it? What should then happen when I navigate? Should the restricted container by part of the primary focus cycle, but then capture it with no way to exit it once you get there? ## Working example Just to show you can easily do this already, below is an example that will show a new pane, with navigation restricted to it, allowing you to select a new name for a button. Note that you can't click outside it with the mouse (although I'm sure I can add that as well and then "hide" the dialog). Also note that the Dialog doesn't appear as a dialog (they don't have to) and that no new Window is created on the task bar or whatever. package app; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.geometry.Point2D; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Dialog; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.layout.Border; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; public class App extends Application { @Override public void start(Stage primaryStage) { GridPane gp = new GridPane(10, 10); gp.addEventHandler(ActionEvent.ACTION, e -> { // Create a Dialog: Dialog<String> d = new Dialog<>(); // Get Button that triggered it: Button node = (Button)e.getTarget(); // Find location of Button where we want to display a new Pane: Point2D pos = node.localToScreen(new Point2D(0, node.getLayoutBounds().getHeight())); // Set pane position and make it look like it is integrated: d.initStyle(StageStyle.TRANSPARENT); d.initOwner(node.getScene().getWindow()); d.setX(pos.getX()); d.setY(pos.getY()); // Some content for our pane: HBox content = new HBox(5, new Label("Change button name to: "), new Button("Foo"), new Button("Bar"), new Button("Baz")); // Add a border to make it more clearly delineated, and a handler when any button was clicked: content.setBorder(Border.stroke(Color.RED)); content.addEventHandler(ActionEvent.ACTION, ae -> { d.setResult(((Button)ae.getTarget()).getText()); d.close(); }); // Set the content, show the pane, and if there was a result, set that the new text on the button that triggered it: d.getDialogPane().setContent(content); d.showAndWait().ifPresent(node::setText); }); gp.add(new VBox(new Label("Standard Buttons in normal container"), new VBox(5, new Button("Click me"), new Button("B"), new Button("C"))), 0, 0); gp.add(new VBox(new Label("Standard Buttons in ScrollPane"), new ScrollPane(new HBox(5, new Button("A"), new Button("B"), new Button("C")))), 1, 0); Scene scene = new Scene(gp); primaryStage.setScene(scene); primaryStage.show(); } } ------------- PR Comment: https://git.openjdk.org/jfx/pull/1555#issuecomment-2406172036