Reputation: 125
I want to display a tooltip inside a TextField when user copies data from it to notify him that it happened and so there is my code.
public class TestController {
@FXML private TextField textField;
private final Clipboard clipboard;
private ContextMenu menu;
private MenuItem menuCopy;
@FXML protected void initialize() {
clipboard = Clipboard.getSystemClipboard();
menu = new ContextMenu();
menuCopy = new MenuItem("Copy");
menuCopy.setOnAction(this::copy);
textField.setContextMenu(menu);
}
private void copy(ActionEvent event) {
final ClipboardContent content = new ClipboardContent();
if(((TextField) menu.getUserData()).getSelectedText().length() == 0)
content.putString(((TextField) menu.getUserData()).getText());
else
content.putString(((TextField) menu.getUserData()).getSelectedText());
clipboard.setContent(content);
Point2D p = ((TextField) menu.getUserData()).localToScreen(0,0);
Tooltip test = new Tooltip("Copied");
test.setShowDuration(new Duration(2000));
test.show(((TextField) menu.getUserData()), p.getX(), p.getY());
}
}
But the setShowDuration
doesn't seem to work. It will be displayed forever.
Upvotes: 1
Views: 656
Reputation: 45786
When you install a Tooltip
via Tooltip#install(Node,Tooltip)
1 there are three event handlers added to the given Node
, all related to mouse events. It is these event handlers that implement the showDelay
and showDuration
functionality. This is done internally by using Timeline
s. However, when you manually show a Tooltip
via one of its show
methods you completely bypass this behavior2. In other words, your Tooltip
has the same functionality as any other PopupControl
.
If you want to manually display a Tooltip
and have it disappear after a specified amount of time you'll have to implement that yourself. Here's a proof-of-concept:
import javafx.animation.PauseTransition;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.util.Duration;
public class NotifyingTextField extends TextField {
private final Tooltip tooltip = new Tooltip("Copied contents to clipboard");
private final PauseTransition hideAnimation = new PauseTransition();
{
hideAnimation.durationProperty().bind(tooltip.showDurationProperty());
hideAnimation.setOnFinished(e -> tooltip.hide());
tooltip.setShowDuration(Duration.seconds(2.0));
}
@Override
public void copy() {
var selectedText = getSelectedText();
if (!selectedText.isEmpty()) {
super.copy();
var point = localToScreen(0, 0);
tooltip.show(this, point.getX(), point.getY());
hideAnimation.playFromStart();
}
}
}
Of course, you may be able to find a third-party library that offers a ready-made solution.
1. Even setting properties such as Control#tooltip
or Tab#tooltip
will delegate to #install(Node,Tooltip)
.
2. This is true even if the Tooltip
is installed. Manually calling show
bypasses all the functionality added by the mouse event handlers.
Upvotes: 6
Reputation: 674
I think it's the way you are implementing it, I tried it and it works for me
PasswordField pf = new PasswordField();
Tooltip tooltip = new Tooltip("Your password must be\nat least 8 characters in length");
tooltip.setShowDuration(new Duration(2000));
pf.setTooltip(tooltip);
If this doesn't work with you try to help us to help you by providing snippet of your code that I can test without adding anything to it
Upvotes: 1