Как динамически управлять отображением подсказок в приложении JavaFX - PullRequest
0 голосов
/ 27 августа 2018

Я ищу способ динамического управления отображением всплывающей подсказки в приложении JavaFX на основе некоторого глобального свойства.Допустим, в моем приложении есть 1000 узлов, на которых установлена ​​всплывающая подсказка.У меня есть логическое свойство для включения / выключения подсказок.Как я могу достичь этого более осуществимым способом?Просто чтобы вы знали, я знаю о функциях установки / удаления всплывающей подсказки.Я не хочу делать это для всех 1000 узлов каждый раз, когда пользователь переключает свойство настройки.

Моя первоначальная мысль - расширить элемент управления Tooltip и установить некоторый фильтр событий для «onShowing», который потребляет событие, еслиСвойство настройки имеет значение false.Но это не останавливает всплывающую подсказку для отображения.Всплывающая подсказка отображается, даже если я использую событие.

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

Любая помощь по этому вопросу высоко ценится.

import javafx.event.Event;
import javafx.event.EventDispatcher;
import javafx.scene.control.Tooltip;
import javafx.stage.WindowEvent;

public class CustomTooltip extends Tooltip {

    public static boolean SHOW_TOOLTIP = false;

    public CustomTooltip(String txt){
        super(txt);

        // Approach #1
        addEventFilter(WindowEvent.WINDOW_SHOWING, e->{
            if (!SHOW_TOOLTIP) {
                e.consume();
            }
        });

        // Approach #2
        //setEventDispatcher();
    }

    private void setEventDispatcher() {
        final EventDispatcher oed = getEventDispatcher();
        final EventDispatcher ned = (event, tail) -> {
            Event r = null;
            if (!SHOW_TOOLTIP) {
                event.consume();
            } else{
                r = oed.dispatchEvent(event, tail);
            }
            return r;
        };
        setEventDispatcher(ned);
    }
}

Ниже приведен полный пример / демонстрация, демонстрирующая мое требование.

import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventDispatcher;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class TooltipDisableDemo extends Application {
    public static boolean SHOW_TOOLTIP = false;


    @Override
    public void start(Stage stage) throws Exception {
        StackPane root = new StackPane();
        Scene sc = new Scene(root, 700, 700);
        stage.setScene(sc);
        stage.setTitle("Tooltips Disable Demo");
        stage.show();

        CheckBox showToolTip = new CheckBox("Enable tooltip displaying");
        showToolTip.selectedProperty().addListener((obs, old, show) -> SHOW_TOOLTIP = show);
        showToolTip.setSelected(true);

        TabPane tabPane = new TabPane();
        for (int i = 1; i < 11; i++) {
            Tab tab = new Tab("Tab " + i);
            tab.setClosable(false);
            FlowPane fp = new FlowPane();
            fp.setPadding(new Insets(10));
            fp.setHgap(15);
            fp.setVgap(15);
            for (int j = 1; j < 51; j++) {
                StackPane sp = new StackPane();
                sp.setStyle("-fx-background-color: gray");
                sp.setPadding(new Insets(0,5,0,5));
                sp.getChildren().add(new Label("SP T"+i+" - "+j));
                Tooltip.install(sp, new CustomTooltip("This is stack pane " + j + " in Tab " + i));

                Button btn = new Button("Button T"+i+" - "+j);
                btn.setTooltip(new CustomTooltip("This is button " + j + " in Tab " + i));
                fp.getChildren().addAll(sp, btn);
            }
            tab.setContent(fp);
            tabPane.getTabs().add(tab);
        }
        VBox.setVgrow(tabPane, Priority.ALWAYS);

        VBox vb = new VBox();
        vb.setSpacing(10);
        vb.setPadding(new Insets(10));
        vb.getChildren().addAll(showToolTip,tabPane);
        root.getChildren().add(vb);
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    /**
     * Custom tooltip implementation.
     */
    class CustomTooltip extends Tooltip {

        public CustomTooltip(String txt){
            super(txt);

            // Approach #1
            addEventFilter(WindowEvent.WINDOW_SHOWING, e->{
                if (!SHOW_TOOLTIP) {
                    e.consume();
                }
            });

            // Approach #2
            //setEventDispatcher();
        }

        private void setEventDispatcher() {
            final EventDispatcher oed = getEventDispatcher();
            final EventDispatcher ned = (event, tail) -> {
                Event r = null;
                if (!SHOW_TOOLTIP) {
                    event.consume();
                } else{
                    r = oed.dispatchEvent(event, tail);
                }
                return r;
            };
            setEventDispatcher(ned);
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Ниже приведена последняя рабочая демонстрация в соответствии с предложением Клеопатры.Я переопределяю защищенный метод show () и условно вызываю супер-метод для отображения всплывающей подсказки.

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TooltipDisableDemo extends Application {
    public static boolean SHOW_TOOLTIP = false;


    @Override
    public void start(Stage stage) throws Exception {
        StackPane root = new StackPane();
        Scene sc = new Scene(root, 700, 700);
        stage.setScene(sc);
        stage.setTitle("Tooltips Disable Demo");
        stage.show();

        CheckBox showToolTip = new CheckBox("Enable tooltip displaying");
        showToolTip.selectedProperty().addListener((obs, old, show) -> SHOW_TOOLTIP = show);
        showToolTip.setSelected(true);

        TabPane tabPane = new TabPane();
        for (int i = 1; i < 11; i++) {
            Tab tab = new Tab("Tab " + i);
            tab.setClosable(false);
            FlowPane fp = new FlowPane();
            fp.setPadding(new Insets(10));
            fp.setHgap(15);
            fp.setVgap(15);
            for (int j = 1; j < 51; j++) {
                StackPane sp = new StackPane();
                sp.setStyle("-fx-background-color: gray");
                sp.setPadding(new Insets(0, 5, 0, 5));
                sp.getChildren().add(new Label("SP T" + i + " - " + j));
                Tooltip.install(sp, new CustomTooltip("This is stack pane " + j + " in Tab " + i));

                Button btn = new Button("Button T" + i + " - " + j);
                btn.setTooltip(new CustomTooltip("This is button " + j + " in Tab " + i));
                fp.getChildren().addAll(sp, btn);
            }
            tab.setContent(fp);
            tabPane.getTabs().add(tab);
        }
        VBox.setVgrow(tabPane, Priority.ALWAYS);

        VBox vb = new VBox();
        vb.setSpacing(10);
        vb.setPadding(new Insets(10));
        vb.getChildren().addAll(showToolTip, tabPane);
        root.getChildren().add(vb);
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    /**
     * Custom tooltip implementation.
     */
    class CustomTooltip extends Tooltip {
        public CustomTooltip() {
            super();
        }

        public CustomTooltip(String txt) {
            super(txt);
        }

        @Override
        protected void show() {
            if (SHOW_TOOLTIP) {
                super.show();
            }
        }
    }
}
0 голосов
/ 27 августа 2018

Вы всегда можете сделать привязку, если Tooltip должен быть установлен на элементе управления (т.е. вы не можете использовать это, например, для Pane).

public final class ToolTipManager {
    public ToolTipManager INSTANCE; // Some singleton implementation
    public final ReadOnlyBooleanProperty enabledProperty() { return enabled.getReadOnlyProperty(); }

   // ...
}

public class MyController {
    @FXML private Button button;
    private Tooltip myTooltip;

    @FXML private void initialize() {
        button.tooltipProperty().bind(
            Bindings.when(ToolTipManager.INSTANCE.enabledProperty())
                    .then(myTooltip)
                    .otherwise((Tooltip)null));
    }
}
...