2017-01-04 2 views
0

создать Tooltip для TableColumn заголовка через fxml, как это:Держите подсказку открытой до тех пор, как мышь над ним

<TableColumn> 
    <cellValueFactory> 
     <PropertyValueFactory property="someProperty" /> 
    </cellValueFactory> 
    <graphic> 
     <Label text="Column 1"> 
      <tooltip> 
       <Tooltip text="Tooltip text" /> 
      </tooltip> 
     </Label> 
    </graphic> 
</TableColumn> 

Я хотел бы сохранить всплывающую подсказку открытой, если я двигаю курсор подсказки. В конце концов, я хотел бы иметь интерактивные ссылки в тексте всплывающей подсказки (точно так же, как всплывающие подсказки для JavaDoc Eclipse). Возможно ли это?

Edit: Учитывая ответ, я пытаюсь сейчас следующее:

Label label = new Label(); 
label.setText("test text"); 
DelayedTooltip beakerTip = new DelayedTooltip(); 
beakerTip.setDuration(3000); 
beakerTip.setText("Science from Base: 12"); 
beakerTip.isHoveringTarget(label); 
Tooltip tooltip = new Tooltip(); 
tooltip.setText("test tooltip text"); 
label.setTooltip(beakerTip); 
myTableColumn.setGraphic(label); 

Здесь проблема заключается в том, что label не то же самое, как подсказке. Поэтому, если мышь находится над подсказкой, но не над label, всплывающая подсказка скрыта. Я не могу передать сам подсказку как цель наведения, поскольку это не Node.

ответ

0

Я использую этот класс в настоящее время, и она работает, как ожидалось:

public class HoveringTooltip extends Tooltip { 

    private Timer timer = new Timer(); 
    private Map<Object, Boolean> mapHoveringTarget2Hovering = new ConcurrentHashMap<>(); 
    private final int duration; 

    public HoveringTooltip(int duration) { 
     super.setAutoHide(false); 
     this.duration = duration; 
    } 

    public void addHoveringTarget(Node object) { 

     mapHoveringTarget2Hovering.put(object, false); 
     object.setOnMouseEntered(e -> { 
      onMouseEntered(object); 
     }); 
     object.setOnMouseExited(e -> { 
      onMouseExited(object); 
     }); 
    } 

    public void addHoveringTarget(Scene object) { 

     mapHoveringTarget2Hovering.put(object, false); 
     object.setOnMouseEntered(e -> { 
      onMouseEntered(object); 
     }); 
     object.setOnMouseExited(e -> { 
      onMouseExited(object); 
     }); 
    } 

    @Override 
    public void hide() { 

     // super.hide(); 
    } 

    public boolean isHovering() { 

     return isHoveringProperty().get(); 
    } 

    public BooleanProperty isHoveringProperty() { 

     synchronized(mapHoveringTarget2Hovering) { 
      for(Entry<Object, Boolean> e : mapHoveringTarget2Hovering.entrySet()) { 
       if(e.getValue()) { 
        // if one hovering target is hovering, return true 
        return new ReadOnlyBooleanWrapper(true); 
       } 
      } 
      // no hovering on any target, return false 
      return new ReadOnlyBooleanWrapper(false); 
     } 
    } 

    private synchronized void onMouseEntered(Object object) { 

     // System.err.println("Mouse entered for " + object + ", canelling timer"); 
     // stop a potentially running hide timer 
     timer.cancel(); 
     mapHoveringTarget2Hovering.put(object, true); 
    } 

    private synchronized void onMouseExited(Object object) { 

     // System.err.println("Mouse exit for " + object + ", starting timer"); 
     mapHoveringTarget2Hovering.put(object, false); 
     startTimer(); 
    } 

    private void startTimer() { 

     timer.cancel(); 
     timer = new Timer(); 
     timer.schedule(new TimerTask() { 

      @Override 
      public void run() { 

       Platform.runLater(new Runnable() { 

        @Override 
        public void run() { 

         if(!isHovering()) 
          HoveringTooltip.super.hide(); 
        } 
       }); 
      } 
     }, duration); 
    } 
} 
1

В самом деле, это возможно, но в нем в основном используются основные функции всплывающей подсказки. Это, как я осуществил то же самое:

Сначала я сделал пользовательскую подсказку, которая была основана от основной подсказке (этот код является модификацией аналогичного вопроса)

public class DelayedTooltip extends Tooltip { 

    private int duration = 0; 
    private BooleanProperty isHoveringPrimary = new SimpleBooleanProperty(false); 
    private BooleanProperty isHoveringSecondary = new SimpleBooleanProperty(false); 

    public void setDuration(int d) { 
     duration = d; 
    } 

    public BooleanProperty isHoveringPrimaryProperty() 
    { 
     return isHoveringPrimary; 
    } 

    public BooleanProperty isHoveringSecondaryProperty() 
    { 
     return isHoveringSecondary; 
    } 

    public void isHoveringTargetPrimary(Node node){ 
     node.setOnMouseEntered(e -> isHoveringPrimary.set(true)); 
     node.setOnMouseExited(e -> isHoveringPrimary.set(false)); 
    } 

     //Usually you will use the tooltip here so enter tooltip.getGraphic() for the node. 
    public void isHoveringTargetSecondary(Node node){ 
     node.setOnMouseEntered(e -> isHoveringTooltip.set(true)): 
     node.setOnMouseExited(e -> isHoveringTooltip.set(false)); 
    } 

    @Override 
    public void hide() { 
     if(isHoveringPrimary.get()==true || isHoveringTooltip.get()==true) 
     { 
      Timeline timeline = new Timeline(); 
      KeyFrame key = new KeyFrame(Duration.millis(duration)); 
      timeline.getKeyFrames().add(key); 
      timeline.setOnFinished(new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent t) { 
        DelayedTooltip.super.hide(); 
       } 
      }); 
      timeline.play(); 
     } 
     else 
     { 
      DelayedTooltip.super.hide(); 
     } 
    } 
} 

И тогда это, как я установлена ​​подсказка

DelayedTooltip beakerTip = new DelayedTooltip(); 
    beakerTip.setDuration(999999); 
    beakerTip.setText("Science from Base: 12"); 
    beakerTip.isHoveringTargetPrimary(beakerView); 
     beakerTip.isHoveringTargetSecondary(beakerTip.geoGraphic()); 

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

+0

Спасибо за ответы! К сожалению, я не могу открыть всплывающую подсказку. Я попробовал установить TableView в качестве объекта hoovering и самой Tooltip/Label. Установка самого всплывающего подсказки в качестве цели не работает, поскольку всплывающая подсказка не является узлом. beakerTip.getGraphic() возвращает null .. – kerner1000

+0

@ kerner1000 Он отлично работает для меня. Если вам не нужна функция задержки, вы можете немного упростить ее (если хотите), но я не вижу проблемы. –

+0

@James_D, что вы проходите как парящая цель? – kerner1000

0

Вот способ взломать поведение подсказки:

import javafx.animation.KeyFrame; 
import javafx.animation.Timeline; 
import javafx.scene.control.Tooltip; 
import javafx.util.Duration; 

import java.lang.reflect.Field; 

/** 
* @author rdeardorff 
*/ 
public class TooltipDelay { 

    public static void hackTooltipActivationTimer(Tooltip tooltip, int delay) { 
     hackTooltipTiming(tooltip, delay, "activationTimer"); 
    } 

    public static void hackTooltipHideTimer(Tooltip tooltip, int delay) { 
     hackTooltipTiming(tooltip, delay, "hideTimer"); 
    } 

    private static void hackTooltipTiming(Tooltip tooltip, int delay, String property) { 
     try { 
      Field fieldBehavior = tooltip.getClass().getDeclaredField("BEHAVIOR"); 
      fieldBehavior.setAccessible(true); 
      Object objBehavior = fieldBehavior.get(tooltip); 

      Field fieldTimer = objBehavior.getClass().getDeclaredField(property); 
      fieldTimer.setAccessible(true); 
      Timeline objTimer = (Timeline) fieldTimer.get(objBehavior); 

      objTimer.getKeyFrames().clear(); 
      objTimer.getKeyFrames().add(new KeyFrame(new Duration(delay))); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
Смежные вопросы