如何将多个 MouseListener 添加到单个 JFrame?
How can I add multiple MouseListeners to a single JFrame?
我有两件事想做:在鼠标悬停时突出显示 JPanel 并在鼠标拖动时移动蓝色方块。问题是,这需要我将 MouseListeners 添加到不同的组件。当我这样做时,我只能使用一个功能——另一个被阻止。我该怎么做才能使这两个功能都起作用?
注意: 有时 JFrame 不显示任何内容 - 您只需保持 运行 它直到显示(通常需要 2-3 次尝试)。如果它做了任何其他奇怪的事情,请保持 运行 它直到它起作用。如果在超过 5 次尝试后仍然无法正常工作,请发表评论。
它应该是什么样子:
Main(创建 JFrame、容器和子项,并添加 MouseListeners)
public class Main extends JFrame{
private static final long serialVersionUID = 7163215339973706671L;
private static final Dimension containerSize = new Dimension(640, 477);
static JLayeredPane layeredPane;
static JPanel container;
public Main() {
super("Multiple MouseListeners Test");
setSize(640, 477);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(containerSize);
getContentPane().add(layeredPane);
createContainer();
layeredPane.add(container, JLayeredPane.DEFAULT_LAYER);
createChildren(4, 4);
new MovableObject();
MovableObjectMouseListener moml = new MovableObjectMouseListener();
//comment these two out and the highlighter works
layeredPane.addMouseListener(moml);
layeredPane.addMouseMotionListener(moml);
}
private void createChildren(int columns, int rows){
for (int i = 0; i < columns; i++){
for (int j = 0; j < rows; j++){
JPanel child = new JPanel(new BorderLayout());
child.setBackground(Color.LIGHT_GRAY);
//comment this out and you can move the MovableObject
child.addMouseListener(new HighlightJPanelsMouseListener());
container.add(child);
}
}
}
private JPanel createContainer(){
container = new JPanel();
container.setLayout(createLayout(4, 4, 1, 1));
container.setPreferredSize(containerSize);
container.setBounds(0, 0, containerSize.width, containerSize.height);
return container;
}
private GridLayout createLayout(int rows, int columns, int hGap, int vGap){
GridLayout layout = new GridLayout(rows, columns);
layout.setHgap(hGap);
layout.setVgap(vGap);
return layout;
}
public static void main(String[] args) {
new Main();
}
}
HighlightJPanelsMouseListener(创建将添加到子项的 MouseListener)
public class HighlightJPanelsMouseListener implements MouseListener{
private Border grayBorder = BorderFactory.createLineBorder(Color.DARK_GRAY);
public HighlightJPanelsMouseListener() {
}
public void mouseEntered(MouseEvent e) {
Component comp = (Component) e.getSource();
JPanel parent = (JPanel) comp;
parent.setBorder(grayBorder);
parent.revalidate();
}
public void mouseExited(MouseEvent e) {
Component comp = (Component) e.getSource();
JPanel parent = (JPanel) comp;
parent.setBorder(null);
parent.revalidate();
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e) {}
}
MovableObject(创建 MovableObject)
download blueSquare.png,或者使用其他图片。记得把下面图片的名字改成你自己的名字。
public class MovableObject {
public MovableObject() {
JPanel parent = (JPanel) Main.container.findComponentAt(10, 10);
ImageIcon icon = null;
//use any image you might have laying around your workspace - or download the one above
URL imgURL = MovableObject.class.getResource("/blueSquare.png");
if (imgURL != null){
icon = new ImageIcon(imgURL);
}else{
System.err.println("Couldn't find file");
}
JLabel movableObject = new JLabel(icon);
parent.add(movableObject);
parent.revalidate();
}
}
MovableObjectMouseListener(创建用于 MovableObject 的 MouseListener)
public class MovableObjectMouseListener implements MouseListener, MouseMotionListener{
private JLabel replacement;
private int xAdjustment, yAdjustment;
public void mousePressed(MouseEvent e){
replacement = null;
Component c = Main.container.findComponentAt(e.getX(), e.getY());
if (!(c instanceof JLabel)){
return;
}
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
replacement = (JLabel)c;
replacement.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
Main.layeredPane.add(replacement, JLayeredPane.DRAG_LAYER);
Main.layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
public void mouseDragged(MouseEvent me){
if (replacement == null){
return;
}
int x = me.getX() + xAdjustment;
int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
replacement.setLocation(x, y);
}
public void mouseReleased(MouseEvent e){
Main.layeredPane.setCursor(null);
if (replacement == null){
return;
}
int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = Main.container.findComponentAt(x, y);
Container parent = (Container) c;
parent.add(replacement);
parent.validate();
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
没有详细查看您的代码,但我建议您需要将拖动 MouseListener 添加到可移动对象(即 JLabel)而不是面板。然后标签将获得拖动事件,面板将获得 mouseEntered/Exited 事件。
这将导致一个额外的问题,当您移过标签时会生成 mouseExited 事件(您不希望发生这种情况)。查看: 以了解此问题的解决方案。
我有两件事想做:在鼠标悬停时突出显示 JPanel 并在鼠标拖动时移动蓝色方块。问题是,这需要我将 MouseListeners 添加到不同的组件。当我这样做时,我只能使用一个功能——另一个被阻止。我该怎么做才能使这两个功能都起作用?
注意: 有时 JFrame 不显示任何内容 - 您只需保持 运行 它直到显示(通常需要 2-3 次尝试)。如果它做了任何其他奇怪的事情,请保持 运行 它直到它起作用。如果在超过 5 次尝试后仍然无法正常工作,请发表评论。
它应该是什么样子:
Main(创建 JFrame、容器和子项,并添加 MouseListeners)
public class Main extends JFrame{
private static final long serialVersionUID = 7163215339973706671L;
private static final Dimension containerSize = new Dimension(640, 477);
static JLayeredPane layeredPane;
static JPanel container;
public Main() {
super("Multiple MouseListeners Test");
setSize(640, 477);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(containerSize);
getContentPane().add(layeredPane);
createContainer();
layeredPane.add(container, JLayeredPane.DEFAULT_LAYER);
createChildren(4, 4);
new MovableObject();
MovableObjectMouseListener moml = new MovableObjectMouseListener();
//comment these two out and the highlighter works
layeredPane.addMouseListener(moml);
layeredPane.addMouseMotionListener(moml);
}
private void createChildren(int columns, int rows){
for (int i = 0; i < columns; i++){
for (int j = 0; j < rows; j++){
JPanel child = new JPanel(new BorderLayout());
child.setBackground(Color.LIGHT_GRAY);
//comment this out and you can move the MovableObject
child.addMouseListener(new HighlightJPanelsMouseListener());
container.add(child);
}
}
}
private JPanel createContainer(){
container = new JPanel();
container.setLayout(createLayout(4, 4, 1, 1));
container.setPreferredSize(containerSize);
container.setBounds(0, 0, containerSize.width, containerSize.height);
return container;
}
private GridLayout createLayout(int rows, int columns, int hGap, int vGap){
GridLayout layout = new GridLayout(rows, columns);
layout.setHgap(hGap);
layout.setVgap(vGap);
return layout;
}
public static void main(String[] args) {
new Main();
}
}
HighlightJPanelsMouseListener(创建将添加到子项的 MouseListener)
public class HighlightJPanelsMouseListener implements MouseListener{
private Border grayBorder = BorderFactory.createLineBorder(Color.DARK_GRAY);
public HighlightJPanelsMouseListener() {
}
public void mouseEntered(MouseEvent e) {
Component comp = (Component) e.getSource();
JPanel parent = (JPanel) comp;
parent.setBorder(grayBorder);
parent.revalidate();
}
public void mouseExited(MouseEvent e) {
Component comp = (Component) e.getSource();
JPanel parent = (JPanel) comp;
parent.setBorder(null);
parent.revalidate();
}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseClicked(MouseEvent e) {}
}
MovableObject(创建 MovableObject)
download blueSquare.png,或者使用其他图片。记得把下面图片的名字改成你自己的名字。
public class MovableObject {
public MovableObject() {
JPanel parent = (JPanel) Main.container.findComponentAt(10, 10);
ImageIcon icon = null;
//use any image you might have laying around your workspace - or download the one above
URL imgURL = MovableObject.class.getResource("/blueSquare.png");
if (imgURL != null){
icon = new ImageIcon(imgURL);
}else{
System.err.println("Couldn't find file");
}
JLabel movableObject = new JLabel(icon);
parent.add(movableObject);
parent.revalidate();
}
}
MovableObjectMouseListener(创建用于 MovableObject 的 MouseListener)
public class MovableObjectMouseListener implements MouseListener, MouseMotionListener{
private JLabel replacement;
private int xAdjustment, yAdjustment;
public void mousePressed(MouseEvent e){
replacement = null;
Component c = Main.container.findComponentAt(e.getX(), e.getY());
if (!(c instanceof JLabel)){
return;
}
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
replacement = (JLabel)c;
replacement.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
Main.layeredPane.add(replacement, JLayeredPane.DRAG_LAYER);
Main.layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
public void mouseDragged(MouseEvent me){
if (replacement == null){
return;
}
int x = me.getX() + xAdjustment;
int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
replacement.setLocation(x, y);
}
public void mouseReleased(MouseEvent e){
Main.layeredPane.setCursor(null);
if (replacement == null){
return;
}
int xMax = Main.layeredPane.getWidth() - replacement.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = Main.layeredPane.getHeight() - replacement.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = Main.container.findComponentAt(x, y);
Container parent = (Container) c;
parent.add(replacement);
parent.validate();
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
没有详细查看您的代码,但我建议您需要将拖动 MouseListener 添加到可移动对象(即 JLabel)而不是面板。然后标签将获得拖动事件,面板将获得 mouseEntered/Exited 事件。
这将导致一个额外的问题,当您移过标签时会生成 mouseExited 事件(您不希望发生这种情况)。查看: