Всплывающая подсказка JavaFX showDuration не работает - PullRequest
1 голос
/ 23 октября 2019

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

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());
    }
}

Но, похоже, setShowDurationработай. Он будет отображаться всегда.

Ответы [ 2 ]

6 голосов
/ 23 октября 2019

Когда вы устанавливаете Tooltip через Tooltip#install(Node,Tooltip) 1 , к данному Node добавляются три обработчика событий, все они связаны с событиями мыши. Именно эти обработчики событий реализуют функции showDelay и showDuration. Это делается внутренне с помощью Timeline s. Однако, когда вы вручную показываете Tooltip с помощью одного из его show методов, вы полностью игнорируете это поведение 2 . Другими словами, ваш Tooltip имеет те же функции, что и любой другой PopupControl.

Если вы хотите вручную отобразить Tooltip и он исчезнет через определенное время, вам придетсяреализовать это самостоятельно. Вот подтверждение концепции :

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();
    } 
  }
}

Конечно, вы можете найти стороннюю библиотеку, которая предлагает готовое решение.


1. Даже при установке таких свойств, как Control#tooltip или Tab#tooltip, будет делегировано значение #install(Node,Tooltip).
2. Это верно, даже если установлена ​​Tooltip. Вызов show вручную обходит все функции, добавленные обработчиками событий мыши.

1 голос
/ 23 октября 2019

Я думаю, что это способ, которым вы его реализуете, я попробовал это, и это работает для меня

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);

Если это не сработает с вами, попробуйте помочь нам, предоставив фрагмент вашегокод, который я могу проверить, не добавляя к нему ничего

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...