Request focus to shape 正在获取错误的控件

Request focus to shape is getting to the wrong control

我正在尝试请求焦点到场景中的矩形形状。当我使用鼠标执行此操作时,焦点 属性 侦听器没有触发,即使形状可遍历到焦点。我试图向形状添加一个 EventListener 以调用其上的 requestFocus() 方法,但在矩形获得焦点后,另一个没有任何侦听器或其他代码的按钮立即夺走了焦点。在我删除该按钮后,另一个控件完成了同样的事情(所有窃取焦点的控件都按照添加到根节点的顺序位于矩形之前)。我尝试使用 Tab 按钮遍历焦点并且它有效。那么,如何使用鼠标请求对焦到矩形?

<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="232.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <ToolBar prefHeight="40.0" prefWidth="200.0">
        <items>
          <Button mnemonicParsing="false" text="Button" />
        </items>
      </ToolBar>
      <HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
         <children>
            <VBox prefHeight="200.0" prefWidth="100.0">
               <children>
                  <ListView id="slotsList" prefHeight="200.0" prefWidth="200.0" />
               </children>
            </VBox>
            <FilmTimeLine HBox.hgrow="ALWAYS" fx:id="timeLine"/>
         </children>
      </HBox>
   </children>
</VBox>

矩形 class,我将其添加到 FilmTimeLine 内的场景(FilmTimeLine 是一个 ScrollPane,它有一个 Pane 子项。矩形在该 Pane 内):

public class EventSlot extends Rectangle {

    public EventSlot() {
        setFocusTraversable(true);
        setWidth(100);
        setHeight(25);
        setFill(Color.web("#9DD3DF"));
        focusedProperty().addListener((observable, oldValue, newValue) -> {
            if (isFocused()) {
                setEffect(FOCUSED_EFFECT);
            } else {
                setEffect(INNER_SHADOW);
            }
        });
        addEventHandler(MouseEvent.MOUSE_PRESSED, (mouseEvent) -> {
            requestFocus();
        });
    }
}

gif of what is happening

当动作发生时,系统构造事件route

看起来你的鼠标事件是由 Rectangle(我假设它是从 Node 继承的)、Pane 和 FilmTimeLine 处理的。 所以我们需要构建到 ignore/filter 除选定矩形之外的所有节点的事件路由。

修改路线的选项:

  • 消耗一个事件。调用 mouseEvent.consume() 以停止事件传播。
addEventHandler(MouseEvent.MOUSE_CLECKED, (mouseEvent) -> {
    requestFocus();
    mouseEvent.consume();
});
  • 使父节点鼠标透明Node.setMouseTransparent(true)。如果为 true,则此节点(及其所有子节点)是完全透明的,因此请确保所有矩形 mouseTransparent 属性 为 false。
pane.setMouseTransparent(true);//the FilmTimeLine is a ScrollPane that has a Pane child
pane.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) { event.consume(); };
});