Прозрачная 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.