如何在JavaFX ColorPicker中更改或覆盖工具提示 [英] How to change or override the tooltip in JavaFX ColorPicker
问题描述
我在应用程序中使用JavaFX ColorPicker.根据我的要求,我已将颜色选择器上的默认颜色映射到一个数字.我希望此数字作为鼠标悬停在颜色上而不是颜色的十六进制值时的工具提示显示.我该如何实现?
I am using JavaFX ColorPicker in my application. As per my requirements, I have mapped the default colors on the color picker to a number. I want this number to be displayed as tooltip on hover over the color instead of hex value of the color. How can I achieve this?
//部分代码
public void handleNodes(Circle circleNode){
public void handleNodes(Circle circularNode) {
final Delta offset = new Delta();
circularNode.setOnMouseEntered(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
((Circle)(event.getSource())).setCursor(Cursor.HAND);
}
});
circularNode.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if(event.getButton().equals(MouseButton.SECONDARY)) {
System.out.println("Right click");
Circle parent = ((Circle)(event.getSource()));
final ContextMenu contextMenu = new ContextMenu();
MenuItem editLabel = new MenuItem("Edit Label");
editLabel.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Edit Label");
final ColorPicker colorPicker = new ColorPicker();
colorPicker.setStyle("-fx-border-radius: 10 10 10 10;"
+ "-fx-background-radius: 10 10 10 10;");
colorPicker.setValue((Color) parent.getFill());
colorPicker.showingProperty().addListener((obs,b,b1)->{
if(b1){
PopupWindow popupWindow = getPopupWindow();
javafx.scene.Node popup = popupWindow.getScene().getRoot().getChildrenUnmodifiable().get(0);
popup.lookupAll(".color-rect").stream()
.forEach(rect->{
Color c = (Color)((Rectangle)rect).getFill();
Tooltip.install(rect.getParent(), new Tooltip("Custom tip for "+c.toString()));
});
}
});
panelMain.getChildren().add(colorPicker);
}
});
推荐答案
基于OP在我的第一个答案后发布的代码,并且由于所解决问题的实质性变化,我添加了一个新的答案,涵盖了两种情况:
Based on the code posted by the OP after my first answer, and due to the substancial changes in the problem addressed, I'm adding a new answer that covers both situations:
-
ColorPicker
作为常规节点嵌入在主场景中 -
ColorPicker
嵌入在ContextMenu
中
- The
ColorPicker
is embedded in the main scene, as a regular node - The
ColorPicker
is embedded in aContextMenu
在第二种情况下,针对第一种解决方案的建议解决方案不再有效,因为找到的窗口将是具有上下文菜单的解决方案.
In the second situation, the proposed solution for the first one is no longer valid, since the window found will be the one with the context menu.
需要一个任务来继续寻找窗口,直到找到带有ComboBoxPopupControl
的窗口为止.
A task is required to keep looking for windows until the one with the ComboBoxPopupControl
is found.
这是一个完全可运行的示例:
This is a full runnable example:
public class ColorPickerFinder extends Application {
ExecutorService findWindowExecutor = createExecutor("FindWindow");
@Override
public void start(Stage primaryStage) {
AnchorPane panCircles = new AnchorPane();
Scene scene = new Scene(panCircles, 400, 400);
final Random random = new Random();
IntStream.range(0,5).boxed().forEach(i->{
final Circle circle= new Circle(20+random.nextInt(80),
Color.rgb(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
circle.setTranslateX(100+random.nextInt(200));
circle.setTranslateY(100+random.nextInt(200));
panCircles.getChildren().add(circle);
});
panCircles.setPrefSize(400, 400);
ColorPicker colorPicker = new ColorPicker();
panCircles.getChildren().add(colorPicker);
primaryStage.setScene(scene);
primaryStage.show();
// We add listeners AFTER showing the stage, as we are looking for nodes
// by css selectors, these will be available only after the stage is shown
colorPicker.showingProperty().addListener((obs,b,b1)->{
if(b1){
// No need for task in this case
getPopupWindow();
}
});
panCircles.getChildren().stream()
.filter(c->c instanceof Circle)
.map(c->(Circle)c)
.forEach(circle->{
circle.setOnMouseClicked(e->{
if(e.getButton().equals(MouseButton.SECONDARY)){
// We need a task, since the first window found is the ContextMenu one
findWindowExecutor.execute(new WindowTask());
final ColorPicker picker = new ColorPicker();
picker.setStyle("-fx-border-radius: 10 10 10 10;"
+ "-fx-background-radius: 10 10 10 10;");
picker.setValue((Color)(circle.getFill()));
picker.valueProperty().addListener((obs,c0,c1)->circle.setFill(c1));
final ContextMenu contextMenu = new ContextMenu();
MenuItem editLabel = new MenuItem();
contextMenu.getItems().add(editLabel);
editLabel.setGraphic(picker);
contextMenu.show(panCircles,e.getScreenX(),e.getScreenY());
}
});
});
}
private PopupWindow getPopupWindow() {
@SuppressWarnings("deprecation")
final Iterator<Window> windows = Window.impl_getWindows();
while (windows.hasNext()) {
final Window window = windows.next();
if (window instanceof PopupWindow) {
if(window.getScene()!=null && window.getScene().getRoot()!=null){
Parent root = window.getScene().getRoot();
if(root.getChildrenUnmodifiable().size()>0){
Node popup = root.getChildrenUnmodifiable().get(0);
if(popup.lookup(".combo-box-popup")!=null){
// only process ComboBoxPopupControl
Platform.runLater(()->{
popup.lookupAll(".color-rect").stream()
.forEach(rect->{
Color c = (Color)((Rectangle)rect).getFill();
Tooltip.install(rect.getParent(),
new Tooltip("Custom tip for "+c.toString()));
});
});
return (PopupWindow)window;
}
}
}
return null;
}
}
return null;
}
private class WindowTask extends Task<Void> {
@Override
protected Void call() throws Exception {
boolean found=false;
while(!found){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
found=(getPopupWindow()!=null);
}
return null;
}
}
private ExecutorService createExecutor(final String name) {
ThreadFactory factory = r -> {
Thread t = new Thread(r);
t.setName(name);
t.setDaemon(true);
return t;
};
return Executors.newSingleThreadExecutor(factory);
}
public static void main(String[] args) {
launch(args);
}
}
这将是在右键单击一个圆并单击颜色选择器之后的结果:
This will be the result after right clicking on a circle, and clicking on the color picker:
这篇关于如何在JavaFX ColorPicker中更改或覆盖工具提示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!