2016-07-28 16 views
0

Ich versuche, meinen eigenen Tooltip zu implementieren. Ich mache das mit einem Timer und Maushörer (für moved und exited). Wenn die Maus bewegt wird, wird der Timer zurückgesetzt, so dass das Popup nur angezeigt wird, wenn die Maus stillstand. Wenn die Maus die Komponente verlässt, ist das Popup ausgeblendet. Wenn das Popup jedoch am Cursor angezeigt wird, befindet sich die Maus innerhalb des Popups, so dass mouseExited aufgerufen wird. Das Popup verschwindet, aber wenn die Maus still bleibt, passiert es erneut und das Popup flimmert. Dies kann verhindert werden, indem das Popup-Fenster 1px verschoben wird, so dass sich die Maus nicht im Popup befindet, aber dies löst nicht das ganze Problem, da das Bewegen der Maus über das Popup-Fenster es verschwinden lässt.Verhindern, dass mouseExited beim Beenden in ein Popup aufgerufen wird

Mein MCVE:

private static Timer timer = new Timer(100, new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     JPanel pop = new JPanel(new GridLayout(0, 3)); 
     pop.setBackground(Color.BLUE); 
     // Do calculations similar to what would actually be happening, 
     // because otherwise the flicker is too fast to demonstrate on my screen 
     for (double i = Math.random() * 12; i < 40; i++) { 
      BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB_PRE); 
      Graphics2D g = img.createGraphics(); 
      g.drawString(Math.log(Math.sqrt(Math.random())) + "", 0, 32); 
      g.dispose(); 

      pop.add(new JLabel(new ImageIcon(img))); 
     } 

     popup = PopupFactory.getSharedInstance().getPopup(panel, pop, x, y); 
     popup.show(); 
    } 
}); 
private static JPanel panel; 
private static Popup popup; 
private static int x, y; 

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(640, 480); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

    MouseAdapter ma = new MouseAdapter() { 

     @Override 
     public void mouseMoved(MouseEvent e) { 
      timer.setRepeats(false); 
      if (popup == null) timer.restart(); 
      x = e.getXOnScreen(); // Adding one here eliminates the flicker problem, 
      y = e.getYOnScreen(); // but still calls mouseExited entering the popup 
     } 

     @Override 
     public void mouseExited(MouseEvent e) { 
      if (popup != null) { 
       popup.hide(); 
       popup = null; 
      } 
      timer.stop(); 
     } 

    }; 

    panel = new JPanel(); 
    panel.setBackground(Color.GREEN); 
    panel.addMouseListener(ma); 
    panel.addMouseMotionListener(ma); 
    frame.add(panel); 

    frame.setVisible(true); 
} 

Ich dachte, dass vielleicht die mouseExited Methode zu überprüfen, um sollte, wenn die mouseEntered des Popup genannt wurde, aber ich bin nicht sicher, wie dies zu tun, und es wäre auch zu Problemen führen wenn sich das Popup über die Kanten der Komponente erstreckt. Ich würde es vorziehen, dass der Maushörer das Popup ignoriert.

Es wäre auch in Ordnung, wenn das Popup mit der Maus bewegt wird, aber ich bin mir nicht sicher, wie das geht.

+0

Gibt es Gründe, die Farbe ändern, warum Sie nicht tun möchten [Tooltipps] (https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html) verwenden? – copeg

+0

@copeg Ich habe benutzerdefinierte Komponenten, die ich in sie setzen möchte – ricky3350

+0

FWIW JToolTip erweitert JComponent - Sie können 'JComponent.createToolTip' außer Kraft setzen, um Ihre eigene angepasste JToolTip zurückzugeben (sollte beachtet werden, dass ein bisschen Layout und Größe zwickt - müssen Sie setze das Layout von JToolTip und überschreibe seine 'getPreferredSize' wie erwähnt [hier] (http://stackoverflow.com/questions/9522475/custom-java-tool-tip-with-swing-components-as-content-does- nicht -erscheinen)). – copeg

Antwort

2

Wenn das Popup jedoch am Cursor angezeigt wird, befindet sich die Maus innerhalb des Popups, also wird mouseExited aufgerufen.

Sie können prüfen, ob die MouseExited Ereigniskoordinaten innerhalb der Grenzen des JPanel aufgetreten ist, und verstecken nur die Popup, wenn das Ereignis außerhalb der Grenzen JPanel aufgetreten.

if (panel.contains(e.getX(), e.getY())){ 
    return; 
} 

Betrachten tool tips mit - es macht die Veranstaltung für Sie Umgang mit und ist hochgradig anpassbar ... mehrzeiligen über html erreichbar ist und Sie können durch changing the look and feel

0

Entfernen Sie die Pop-up schließen Code in der Maus verlassen Funktion (in main), ändert es an:

@Override 
public void mouseExited(MouseEvent e) { 
    timer.stop(); 
} 

Hinzufügen eines neuen MouseAdaptor zu dem Popup-Menü, mit einer neuen mouseExited() Funktion läuft ähnlichen Code:

popup.addMouseMotionListener(new MouseAdaptor() { 
    @Override 
    public void mouseExited(MouseEvent e) { 
     popup.hide(); 
    } 
} 

Auf diese Weise ist das Popup-Menü dafür verantwortlich, sich selbst zu schließen, wenn die Maus es verlässt.