我正在尝试实现自己的工具提示。我使用Timer
和鼠标监听器(moved和exited)执行此操作。移动鼠标时,计时器会重置,因此弹出窗口仅在鼠标静止时显示。当鼠标退出组件时,弹出窗口将被隐藏。但是,当光标处显示弹出窗口时,鼠标位于弹出窗口内,因此调用mouseExited
。弹出窗口消失,但是,如果鼠标仍然静止,它会再次发生,导致弹出窗口闪烁。这可以通过移动弹出式1px来防止,这样鼠标不在弹出窗口中,但这并不能解决整个问题,因为将鼠标移到弹出窗口会使其消失。
我的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 :(得分:2)
但是,当光标处显示弹出窗口时,鼠标位于弹出窗口内,因此调用mouseExited。
您可以检查MouseExited事件坐标是否发生在JPanel
的范围内,并且只有在事件发生在Popup
范围之外时才隐藏JPanel
。
if ( panel.contains(e.getX(), e.getY() ) ){
return;
}
考虑使用tool tips - 它为您执行事件处理并且可以高度自定义...可以通过html
实现多行,您可以按changing the look and feel 更改颜色
答案 1 :(得分:0)
删除鼠标退出函数中的关闭弹出代码(在main中),将其更改为:
@Override
public void mouseExited(MouseEvent e) {
timer.stop();
}
在弹出菜单中添加一个新的MouseAdaptor,新的mouseExited()
函数运行类似的代码:
popup.addMouseMotionListener( new MouseAdaptor() {
@Override
public void mouseExited(MouseEvent e) {
popup.hide();
}
}
这样弹出菜单就会在鼠标离开时自行关闭。