如果已经 运行 如何触发 MouseListener 事件方法
how to fire MouseListener event methods if it's already running
在我的代码中我有:
带有普通 JPanel 的 JFrame,其中包含一些 JComponent 对象。
这些 JComponents 有:
- JTextFields 列表。
- 一个侦听器,它在 mouseEntered 触发时突出显示其边框,并在 mouseExited 触发时隐藏它。
由于当光标越过嵌套到 JComponent 中的 jtextField 时也会触发 mouseExited 方法,因此 mouseExited 方法的实现会在隐藏边框之前检查事件的光标位置是否在 JComponentArea 之外:
问题是:
如果您缓慢移动鼠标,代码似乎工作正常,但如果您在组件之间快速移动鼠标,有时 JComponent 的边框不会隐藏。
我认为这可能是因为 mouseExited 在光标经过嵌套的 textField 时触发,然后在光标位于 JComponent 之外时再次触发,但我不确定真正的问题是什么。
在此先感谢您的任何提示或帮助!
代码:
针对上述问题写了代码。这是 Jcomponent class (MyContainer) 和 class 包括 Main (MyClass):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MyClass {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run(){
int i=0;
//mainWindow
JFrame mainWindow = new JFrame("MyFrame");
mainWindow.setLayout(new BorderLayout());
mainWindow.setMinimumSize(new Dimension(300,300));
JPanel viewPort = new JPanel();
viewPort.setLayout(new FlowLayout(FlowLayout.LEFT));
MyContainer one = new MyContainer();
MyContainer two = new MyContainer();
MyContainer three = new MyContainer();
viewPort.add(one);
viewPort.add(two);
viewPort.add(three);
mainWindow.add(viewPort,BorderLayout.CENTER);
mainWindow.setVisible(true);
}
});
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class MyContainer extends JComponent {
JTextField text1 ;
JTextField text2 ;
JTextField text3 ;
public MyContainer(){
super.setLayout(new FlowLayout(FlowLayout.LEFT));
super.setPreferredSize(new Dimension(200,50));
super.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
super.setBackground(Color.green);
text1 = new JTextField("LABEL_1");
text1.setPreferredSize(new Dimension(60,30));
text1.setEditable(false);
this.add(text1);
text2 = new JTextField("LABEL_2");
text2.setPreferredSize(new Dimension(60,30));
text2.setEditable(false);
this.add(text2);
text3 = new JTextField("LABEL_3");
text3.setPreferredSize(new Dimension(60,30));
text3.setEditable(false);
this.add(text3);
addListener();
}
private void addListener() {
this.addMouseListener(new MouseListener() {
@Override
public void mouseEntered(MouseEvent e) {
MyContainer.this.setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
@Override
public void mouseExited(MouseEvent e) {
Rectangle r = e.getComponent().getBounds();
Point p = e.getPoint();
if( p.x < 0 || p.y < 0 || p.x >= r.width || p.y >= r.height)
MyContainer.this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
@Override public void mouseClicked(MouseEvent e) { /*NOTHING*/ }
@Override public void mouseReleased(MouseEvent e) { /*NOTHING*/ }
@Override public void mousePressed(MouseEvent e) { /*NOTHING*/ }
});
}
}
我建议不要使用静态方法,但我不确定按您的方式进行操作是否会产生任何实际影响。我会推荐
public void mouseEntered(MouseEvent e) {
((MyContainer) e.getSource()).setBorder(...)
}
// and so forth
此外,问题可能与您的 mouseExited
方法有关。而不是使用 .getBounds()
我建议使用 instanceof
if(e.getSource() instanceof MyContainer) {
// do the stuff
} else {
// do nothing
}
或者:
if(!(e.getSource() instanceof JTextField)) {
// do the stuff
} else {
// do nothing
}
else
声明甚至不是必需的;为了完整起见,我将其包括在内。
这是使用 MyContainer.this.dispatchEvent(SwingUtilities.convertMouseEvent(JTextField, e, MyContainer.this));
的一种可能实现:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class MyClass2 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int i = 0;
//mainWindow
JFrame mainWindow = new JFrame("MyFrame");
mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainWindow.setMinimumSize(new Dimension(300, 300));
JPanel viewPort = new JPanel();
viewPort.setLayout(new FlowLayout(FlowLayout.LEFT));
MyContainer one = new MyContainer();
MyContainer two = new MyContainer(true);
viewPort.add(makeTitledPanel(one, "move it fast: NG?"));
viewPort.add(makeTitledPanel(two, "move it fast: OK?"));
mainWindow.add(viewPort, BorderLayout.CENTER);
mainWindow.setVisible(true);
}
});
}
private static JComponent makeTitledPanel(JComponent c, String title) {
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createTitledBorder(title));
p.add(c);
return p;
}
}
class MyContainer extends JComponent {
JTextField text1 ;
JTextField text2 ;
JTextField text3 ;
private final boolean flag;
public MyContainer() {
this(false);
}
public MyContainer(boolean flag) {
super();
this.flag = flag;
super.setLayout(new FlowLayout(FlowLayout.LEFT));
super.setPreferredSize(new Dimension(200, 50));
super.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
super.setBackground(Color.green);
text1 = new JTextField("LABEL_1");
text2 = new JTextField("LABEL_2");
text3 = new JTextField("LABEL_3");
MouseListener l = new MouseEventConverter();
for (JTextField f : Arrays.asList(text1, text2, text3)) {
f.setPreferredSize(new Dimension(60, 30));
f.setEditable(false);
if (flag) {
f.addMouseListener(l);
}
this.add(f);
}
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
MyContainer.this.setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
@Override
public void mouseExited(MouseEvent e) {
Rectangle r = e.getComponent().getBounds();
Point p = e.getPoint();
if (p.x < 0 || p.y < 0 || p.x >= r.width || p.y >= r.height) {
MyContainer.this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
}
});
}
}
class MouseEventConverter extends MouseAdapter {
@Override public void mouseEntered(MouseEvent e) {
dispatchMouseEvent(e);
}
@Override public void mouseExited(MouseEvent e) {
dispatchMouseEvent(e);
}
private void dispatchMouseEvent(MouseEvent e) {
Component c = e.getComponent();
Component p = SwingUtilities.getUnwrappedParent(c);
p.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, p));
}
}
在我的代码中我有:
带有普通 JPanel 的 JFrame,其中包含一些 JComponent 对象。 这些 JComponents 有: - JTextFields 列表。 - 一个侦听器,它在 mouseEntered 触发时突出显示其边框,并在 mouseExited 触发时隐藏它。 由于当光标越过嵌套到 JComponent 中的 jtextField 时也会触发 mouseExited 方法,因此 mouseExited 方法的实现会在隐藏边框之前检查事件的光标位置是否在 JComponentArea 之外:
问题是:
如果您缓慢移动鼠标,代码似乎工作正常,但如果您在组件之间快速移动鼠标,有时 JComponent 的边框不会隐藏。 我认为这可能是因为 mouseExited 在光标经过嵌套的 textField 时触发,然后在光标位于 JComponent 之外时再次触发,但我不确定真正的问题是什么。 在此先感谢您的任何提示或帮助!
代码:
针对上述问题写了代码。这是 Jcomponent class (MyContainer) 和 class 包括 Main (MyClass):
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class MyClass {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run(){
int i=0;
//mainWindow
JFrame mainWindow = new JFrame("MyFrame");
mainWindow.setLayout(new BorderLayout());
mainWindow.setMinimumSize(new Dimension(300,300));
JPanel viewPort = new JPanel();
viewPort.setLayout(new FlowLayout(FlowLayout.LEFT));
MyContainer one = new MyContainer();
MyContainer two = new MyContainer();
MyContainer three = new MyContainer();
viewPort.add(one);
viewPort.add(two);
viewPort.add(three);
mainWindow.add(viewPort,BorderLayout.CENTER);
mainWindow.setVisible(true);
}
});
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTextField;
@SuppressWarnings("serial")
public class MyContainer extends JComponent {
JTextField text1 ;
JTextField text2 ;
JTextField text3 ;
public MyContainer(){
super.setLayout(new FlowLayout(FlowLayout.LEFT));
super.setPreferredSize(new Dimension(200,50));
super.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
super.setBackground(Color.green);
text1 = new JTextField("LABEL_1");
text1.setPreferredSize(new Dimension(60,30));
text1.setEditable(false);
this.add(text1);
text2 = new JTextField("LABEL_2");
text2.setPreferredSize(new Dimension(60,30));
text2.setEditable(false);
this.add(text2);
text3 = new JTextField("LABEL_3");
text3.setPreferredSize(new Dimension(60,30));
text3.setEditable(false);
this.add(text3);
addListener();
}
private void addListener() {
this.addMouseListener(new MouseListener() {
@Override
public void mouseEntered(MouseEvent e) {
MyContainer.this.setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
@Override
public void mouseExited(MouseEvent e) {
Rectangle r = e.getComponent().getBounds();
Point p = e.getPoint();
if( p.x < 0 || p.y < 0 || p.x >= r.width || p.y >= r.height)
MyContainer.this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
@Override public void mouseClicked(MouseEvent e) { /*NOTHING*/ }
@Override public void mouseReleased(MouseEvent e) { /*NOTHING*/ }
@Override public void mousePressed(MouseEvent e) { /*NOTHING*/ }
});
}
}
我建议不要使用静态方法,但我不确定按您的方式进行操作是否会产生任何实际影响。我会推荐
public void mouseEntered(MouseEvent e) {
((MyContainer) e.getSource()).setBorder(...)
}
// and so forth
此外,问题可能与您的 mouseExited
方法有关。而不是使用 .getBounds()
我建议使用 instanceof
if(e.getSource() instanceof MyContainer) {
// do the stuff
} else {
// do nothing
}
或者:
if(!(e.getSource() instanceof JTextField)) {
// do the stuff
} else {
// do nothing
}
else
声明甚至不是必需的;为了完整起见,我将其包括在内。
这是使用 MyContainer.this.dispatchEvent(SwingUtilities.convertMouseEvent(JTextField, e, MyContainer.this));
的一种可能实现:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class MyClass2 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
int i = 0;
//mainWindow
JFrame mainWindow = new JFrame("MyFrame");
mainWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainWindow.setMinimumSize(new Dimension(300, 300));
JPanel viewPort = new JPanel();
viewPort.setLayout(new FlowLayout(FlowLayout.LEFT));
MyContainer one = new MyContainer();
MyContainer two = new MyContainer(true);
viewPort.add(makeTitledPanel(one, "move it fast: NG?"));
viewPort.add(makeTitledPanel(two, "move it fast: OK?"));
mainWindow.add(viewPort, BorderLayout.CENTER);
mainWindow.setVisible(true);
}
});
}
private static JComponent makeTitledPanel(JComponent c, String title) {
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createTitledBorder(title));
p.add(c);
return p;
}
}
class MyContainer extends JComponent {
JTextField text1 ;
JTextField text2 ;
JTextField text3 ;
private final boolean flag;
public MyContainer() {
this(false);
}
public MyContainer(boolean flag) {
super();
this.flag = flag;
super.setLayout(new FlowLayout(FlowLayout.LEFT));
super.setPreferredSize(new Dimension(200, 50));
super.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
super.setBackground(Color.green);
text1 = new JTextField("LABEL_1");
text2 = new JTextField("LABEL_2");
text3 = new JTextField("LABEL_3");
MouseListener l = new MouseEventConverter();
for (JTextField f : Arrays.asList(text1, text2, text3)) {
f.setPreferredSize(new Dimension(60, 30));
f.setEditable(false);
if (flag) {
f.addMouseListener(l);
}
this.add(f);
}
this.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
MyContainer.this.setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
@Override
public void mouseExited(MouseEvent e) {
Rectangle r = e.getComponent().getBounds();
Point p = e.getPoint();
if (p.x < 0 || p.y < 0 || p.x >= r.width || p.y >= r.height) {
MyContainer.this.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
}
}
});
}
}
class MouseEventConverter extends MouseAdapter {
@Override public void mouseEntered(MouseEvent e) {
dispatchMouseEvent(e);
}
@Override public void mouseExited(MouseEvent e) {
dispatchMouseEvent(e);
}
private void dispatchMouseEvent(MouseEvent e) {
Component c = e.getComponent();
Component p = SwingUtilities.getUnwrappedParent(c);
p.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, p));
}
}