2016-07-28 98 views
0

我試圖實現我自己的工具提示。我使用Timer和鼠標監聽器(movedexited)執行此操作。當鼠標移動時,定時器被重置,所以彈出窗口只在鼠標靜止時顯示。當鼠標退出組件時,彈出窗口被隱藏。但是,當彈出窗口顯示在光標處時,鼠標位於彈出窗口內,因此調用mouseExited。彈出消失,但是,如果鼠標保持靜止,它會再次發生,導致彈出窗口閃爍。這可以通過移動彈出窗口1px來防止,以便鼠標不在彈出窗口中,但這並不能解決整個問題,因爲將鼠標移動到彈出窗口上會使其消失。防止在退出到彈出窗口時調用mouseExited

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

我在想,也許mouseExited方法應檢查是否彈出的mouseEntered叫,但我不知道如何做到這一點,這也將導致問題當彈出窗口延伸到組件的邊緣時。我寧願鼠標監聽器忽略彈出。

如果彈出窗口隨鼠標移動,這也可以,但我不知道該怎麼做。

+0

你爲什麼不改變顏色的任何原因希望使用[工具提示](https://docs.oracle.com/javase/tutorial/uiswing/components/tooltip.html)? – copeg

+0

@copeg我有我想要放入它們的自定義組件 – ricky3350

+0

FWIW JToolTip擴展了JComponent - 你可以重寫'JComponent.createToolTip'來返回你自己定製的JToolTip(應該注意這需要一些佈局和大小的調整 - 你必須設置JToolTip的佈局,並覆蓋它的'getPreferredSize'如[這裏]提到的(http://stackoverflow.com/questions/9522475/custom-java-tool-tip-with-swing-components-as-content-does-not -出現) )。 – copeg

回答

2

但是,當彈出窗口顯示在光標處時,鼠標位於彈出框內,因此調用了mouseExited。

您可以檢查事件的mouseExited座標JPanel的範圍內發生的,只有隱藏Popup如果事件發生的JPanel範圍之外。

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

考慮使用tool tips - 它的事件處理你和高度可定製的......多線過html是可以實現的,你可以通過changing the look and feel

0

刪除在鼠標離開功能關閉彈出窗口代碼(主),將其更改爲:

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

添加新MouseAdaptor的彈出式菜單,用新mouseExited()功能運行相似代碼:

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

這樣,當鼠標離開它時,彈出菜單負責關閉自己。