我正在寻找一种基于某些全局属性动态控制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);
}
}
}
答案 0 :(得分:4)
如果要将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));
}
}
答案 1 :(得分:1)
根据kleopatra的建议,以下是最终的工作演示。我将覆盖受保护的方法show(),并有条件地调用super方法以显示工具提示。
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();
}
}
}
}