Как определить, когда событие JavaFx мыши происходит в "метке", имеют TitledPane?

У меня есть Аккордеон с несколькими TitledPanes. При расширении TitledPane на панели появляются "мертвые области", в которых нет подкомпонентов (например, кнопок, текста и т. Д.).

Прямо сейчас, когда я проверяю MouseEvent.getSource(), он возвращает экземпляр TitledPane для всех областей. Есть ли способ специально ограничить / проверить щелчок мышью в разделе "title" на TitledPane?

2 ответа

Решение

Я не думаю, что есть публичный API для определения щелчка мышью в области заголовка, однако это можно сделать следующим образом:

titledPane.setOnMouseClicked(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent event) {
        EventTarget target = event.getTarget();
        String clazz = "class com.sun.javafx.scene.control.skin.TitledPaneSkin$TitleRegion";
        if(target.getClass().toString().equals(clazz) || // anywhere on title region except title Text
            (target instanceof Node && ((Node) target).getParent().getClass().toString().equals(clazz))) // title Text
            System.out.println("title was clicked");
    }
});

Но этот метод крайне не рекомендуется, поскольку он опирается на некоторые внутренние детали реализации, которые могут быть изменены.

Может быть, лучше подумать о том, что вам действительно нужно. Может быть, ваше действительное требование может быть выполнено uisng TitledPaneобщедоступные методы и свойства API.

Для бездействия expandedProperty()Значение меняется каждый раз, когда щелчок мыши происходит в области заголовка (если isCollapsible() установлен в true).

titledPane.expandedProperty().addListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        System.out.println("mouse click changed expanded from " + oldValue + " to " + newValue);
    }
});

В справочнике CSS вы можете узнать, что есть ребенок TitledPane который имеет класс стиля title, Нетрудно догадаться, что эта часть является названием. Вы можете переходить от результата выбора к графу сцены, пока не найдете узел с классом стиля. title или пока вы не достигнете Accordion,

Следующий код окрашивает прямоугольник под Accordion зеленый, если мышь находится в заголовке и красный в противном случае:

@Override
public void start(Stage primaryStage) {
    TitledPane tp1 = new TitledPane("foo", new Rectangle(100, 100));
    TitledPane tp2 = new TitledPane("bar", new Circle(100));
    Accordion accordion = new Accordion(tp1, tp2);

    Rectangle rect = new Rectangle(100, 20, Color.RED);

    accordion.addEventFilter(MouseEvent.MOUSE_MOVED, evt -> {
        Node n = evt.getPickResult().getIntersectedNode();
        boolean title = false;
        while (n != accordion) {
            if (n.getStyleClass().contains("title")) {
                // we're in the title
                title = true;
                break;
            }
            n = n.getParent();
        }
        rect.setFill(title ? Color.LIME : Color.RED);
    });

    Scene scene = new Scene(new VBox(accordion, rect), 100, 400);

    primaryStage.setScene(scene);
    primaryStage.show();
}

Обратите внимание, что с фильтром событий для MouseEvent.MOUSE_CLICKED Вы можете просто использовать событие, если результат выбора отсутствует в заголовке...

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