是的,这个问题已经发布在JavaRanch上,但我对它们并不了解。
我有JDialog,其中添加了MouseListener,如下所示:
super.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
ConnectionTreeTooltip
是这个jdialog。
问题是只要鼠标进入或退出JDialog,就会调用这两个方法。他们只是一起跑。
我的JDialog的代码:
public class ConnectionTreeTooltip extends JDialog {
...........
public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
super(connectionsTree.getMainFrame(), "", false);
super.setUndecorated(true);
super.setFocusableWindowState(false);
.............
super.getContentPane().add(scrollPane);
super.pack();
}
connectionsTree.getMainFrame()
返回JFrame的实例。
编辑以下是完整代码:
public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
super(connectionsTree.getMainFrame(), "", false);
super.setUndecorated(true);
super.setFocusableWindowState(false);
this.connectionsTree = connectionsTree;
JPanel contentPane = (JPanel) super.getContentPane();
contentPane.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.blue, Color.red));
tipLabel = new JLabel();
// by default, JLabel is not focusable.
tipLabel.setFocusable(true);
tipLabel.setBackground(Color.WHITE);
scrollPane = new JScrollPane(tipLabel) {
@Override
public Dimension getPreferredSize() {
return preferredSizeOfScrollPane;
}
};
scrollPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 1, 1));
super.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
tipLabel.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
// tipLabel can key events only if it is visible and focused
if (e.getKeyCode() == 32) {
unFocusTipLabel();
}
}
});
super.getContentPane().add(scrollPane);
super.pack();
}
为什么我的JDialog或我的MouseListener出现了什么问题?
谢谢!
答案 0 :(得分:2)
你的JDialog很可能在其中拥有一个从对话框本身窃取鼠标监听器的组件,所以当你的鼠标进入对话框时,对话框会检测到鼠标进入,但鼠标会立即进入对话框的组件(也许就是JScrollPane),mouselistener会感觉你已经离开了对话框并进入了它的子组件。
例如,我的SSCCE:
import java.awt.event.*;
import javax.swing.*;
public class MouseListenerTest {
public static void main(String[] args) {
final JFrame mainFrame = new JFrame("My Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new JPanel() {
{
add(new JButton(new AbstractAction("Show Dialog") {
@Override
public void actionPerformed(ActionEvent arg0) {
ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
mainFrame);
cttt.setVisible(true);
}
}));
}
});
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
class ConnectionTreeTooltip extends JDialog {
public ConnectionTreeTooltip(JFrame mainFrame) {
super(mainFrame, "", false);
setUndecorated(true);
setFocusableWindowState(false);
add(new JScrollPane(new JTextArea(20, 40)));
((JPanel)getContentPane()).setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
pack();
addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof ConnectionTreeTooltip) {
System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
// hideTooltip();
}
}
});
}
}
现在最困难的部分是弄清楚如何使用GlassPane来获取鼠标输入/离开信息,但仍允许将鼠标事件传递到玻璃窗格下方的对话框中。
修改
是的解决方案是使用玻璃窗格:
import java.awt.event.*;
import javax.swing.*;
public class MouseListenerTest {
public static void main(String[] args) {
final JFrame mainFrame = new JFrame("My Frame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new JPanel() {
{
add(new JButton(new AbstractAction("Show Dialog") {
@Override
public void actionPerformed(ActionEvent arg0) {
ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
mainFrame);
cttt.setVisible(true);
}
}));
}
});
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
class ConnectionTreeTooltip extends JDialog {
public ConnectionTreeTooltip(JFrame mainFrame) {
super(mainFrame, "", false);
setUndecorated(true);
setFocusableWindowState(false);
add(new JScrollPane(new JTextArea(20, 40)));
((JPanel) getContentPane()).setBorder(
BorderFactory.createEmptyBorder(4, 4, 4, 4));
pack();
JComponent glassPane = (JComponent) getGlassPane();
glassPane.setVisible(true);
glassPane.addMouseListener(new MyMouseAdapter());
}
private class MyMouseAdapter extends MouseAdapter {
@Override
public void mouseExited(MouseEvent e) {
System.out.println("mouse exited");
}
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouse entered");
}
}
}
答案 1 :(得分:1)
我以比使用GlassPane更好的方式解决了我的问题。 GlassPane只给我增加了麻烦,因为我无法滚动GlassPane下的JScrollPane,并且在glasspane swing教程中建议的redispatching mouse事件根本没有帮助,因为glasspane上的mouseListener没有收到mouseDragged。
解决方案是使用AWTEventListener。使用AWTEventListener,我可以检查组件事件是否打开以及事件的ID。所以我的AWTEventListener检查是否在JDialog上发生了mouseEntered事件,如果是,则以编程方式聚焦。如果在JScrollPane上发生了mouseDragged事件,我会以编程方式滚动它。最后,如果在JDialog上发生mouseExited事件,它将被隐藏。
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
MouseEvent me = (MouseEvent) event;
Component mouseComponent = me.getComponent();
if (mouseComponent == scrollPane) {
if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
scrollPane.getViewport().setViewPosition(me.getPoint()); // scroll JScrollPane programmatically
}
} else if (mouseComponent == ConnectionTreeTooltip.this) {
if (me.getID() == MouseEvent.MOUSE_ENTERED)
focusTipLabel(); //focus JDialog(ConnectionTreeTooltip)
else if (me.getID() == MouseEvent.MOUSE_EXITED) {
hideTooltip(); //hide JDialog(ConnectionTreeTooltip)
}
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
但是这个AWTEventListener适用于从主框架中的任何组件生成的mouseevents。它并不总是处理JDialog上的mouseExited事件。
答案 2 :(得分:0)
或者更简单的替代方案。检查mouseExited上鼠标的坐标,如果鼠标真的在控件之外,则只计为退出:
super.addMouseListener(new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
Point cursor = e.getPoint();
if ( (cursor.x < super.getX()) || (cursor.y < super.getY()) || (cursor.x > popup.getX()+super.getWidth()) || (cursor.y > super.getY()+super.getHeight()))
popup.setVisible(false);
}
});