Прозрачная JFXPanel не передает события компонентам под ней

Я пытаюсь создать прозрачную JFXPanel поверх основанного на колебании пользовательского интерфейса. Проблема в том, что события не передаются через "прозрачные" секции, как для обычных компонентов свинга. Я включил простой пример ниже. Обратите внимание, что есть 3 слоя, свинг, свинг, затем jfxpanel. Если вы закомментируете

addItemToLayeredPanel(panel, createFXOverlay(), 7);

Вы можете нажать обе кнопки, даже если они расположены над нижней панелью. (Просто демонстрация эффекта работает только в свинге, не работает с JFXPanel)

public class Main {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    JLayeredPane panel = new JLayeredPane();
    JButton button = new JButton("Push me");
    JPanel overlay = createOverlay();

    addItemToLayeredPanel(panel, button, 5);
    addItemToLayeredPanel(panel, overlay, 6);
    addItemToLayeredPanel(panel, createFXOverlay(), 7);

    frame.getContentPane().add(panel);
    frame.setSize(500, 500);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private static JPanel createOverlay() {
    JPanel panel = new JPanel();
    panel.add(new JButton("on top"));
    panel.setOpaque(false);
    return panel;
}

private static JFXPanel createFXOverlay() {
    JFXPanel panel = new JFXPanel();
    BorderPane root = new BorderPane();
    root.setStyle("-fx-background-color:transparent;");
    root.setCenter(new Button("root"));
    Scene scene = new Scene(root);

    scene.setFill(javafx.scene.paint.Color.TRANSPARENT);
    panel.setScene(scene);
    panel.setOpaque(false);
    return panel;
}

private static void addItemToLayeredPanel(JLayeredPane panel, JComponent item, int layer) {
    item.setBounds(0,0,500,500);
    panel.add(item);
    panel.setLayer(item, layer);
}

}

Идеи? Я попробовал несколько способов переадресации событий (в общем) на нижележащие компоненты, но я не смог заставить его работать. Я нашел пару похожих вопросов, но здесь и здесь нет решений.

0 ответов

Когда Swings пытается увидеть, проходит ли событие мыши, он использует JComponent метод

public boolean contains(int x, int y) {
    return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
}

Проблема в том, что JFXPanel, в отличие от других компонентов Swing, не определяет ui ComponentUI. Следовательно, проверка возвращается кsuper.contains(x,y), который возвращает истину, если событие мыши происходит в пределах объекта.

Решение состоит в том, чтобы использовать класс, который расширяет JFXPanel и переопределяет contains метод:

public class MyJFXPanel extends JFXPanel{
    @Override
    public boolean contains(int x, int y) { return false; }
}

где false может быть заменен более сложным утверждением, например условием прозрачности пикселя.

Затем события мыши будут автоматически перенаправлены на элемент под MyJFXPanel.

Другие вопросы по тегам