我有一个带有CardLayout和两张卡的JPanel。我希望布局每次鼠标进入或退出面板时翻转卡片。除非其中一张卡是侦听鼠标事件的组件,否则此方法工作正常。考虑以下示例:
JPanel cardLayoutPanel = new JPanel(layout);
JButton button = new JButton("listening!");
JLabel label = new JLabel("not listening.");
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
});
问题是,如果MouseEvent被子组件捕获,则父组件不会将它作为与该主题相关的许多SO问题中的读取对象进行处理。我尝试了不同的操作,例如重新分发事件,或者如果事件坐标仍在面板中,则忽略退出事件。
第一个解决方案根本不起作用,第二个解决方案都没有,因为从那以后不再发生鼠标输入事件。
我该如何解决?
我现在看到的唯一解决方案是将侦听器从子组件中完全删除,并在父级鼠标侦听器中自行执行碰撞和事件处理,但这将是一团糟,而不是预期的方式。我想这样做。
任何帮助或想法得到赞赏。
编辑:这是一个完整的简短可编译示例:
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class CardLayoutTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(new EmptyBorder(new Insets(50, 50, 50, 50)));
CardLayout layout = new CardLayout();
JPanel cardLayoutPanel = new JPanel(layout);
JButton button = new JButton("listening!");
JLabel label = new JLabel("not listening.");
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
});
content.add(cardLayoutPanel);
frame.add(content);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
我稍微修改了您的示例,并使其生效。按键(至少在此示例中)是使按钮与mouseListener
共享相同的cardLayoutPanel
。我不知道这是否是通用解决方案,但它确实在这里起作用。我还进行了以下更改:
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class CardLayoutTest {
JButton button = new JButton("listening!");
JPanel cardLayoutPanel = new JPanel();
CardLayout layout = new CardLayout();
public static void main(String[] args) {
new CardLayoutTest().start();
}
public void start() {
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setBorder(new EmptyBorder(
new Insets(50, 50, 50, 50)));
cardLayoutPanel.setLayout(layout);
cardLayoutPanel
.setPreferredSize(new Dimension(200, 200));
button.addActionListener(
ae -> System.out.println("IT WORKS!"));
button.removeMouseMotionListener(
button.getMouseMotionListeners()[0]);
button.removeMouseListener(
button.getMouseListeners()[0]);
MyMouseListener ml = new MyMouseListener();
button.addMouseListener(ml);
button.setBorder(new LineBorder(Color.red, 2));
JLabel label = new JLabel("not listening.");
label.setBorder(new LineBorder(Color.blue, 2));
cardLayoutPanel.add(button);
cardLayoutPanel.add(label);
layout.last(cardLayoutPanel);
cardLayoutPanel.addMouseListener(ml);
content.add(cardLayoutPanel);
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private class MyMouseListener extends MouseAdapter {
@Override
public void mouseEntered(MouseEvent e) {
System.out.println("entered!");
layout.next(cardLayoutPanel);
}
public void mouseClicked(MouseEvent e) {
if (e.getSource() instanceof JButton) {
JButton b = (JButton)(e.getSource());
b.doClick();
}
}
@Override
public void mouseExited(MouseEvent e) {
System.out.println("exited!");
layout.next(cardLayoutPanel);
}
}
}
这不是一个好的解决方案,但是我通过entering parent component。时调用flip事件设法达到了我想要的目的。这是可行的,因为我的面板之间有足够的空间来使用此属性。
但是,我没有按照评论所建议的那样用玻璃板实现这种效果。也许我做错了,但是事件没有正确到达组件,甚至某些检查实例都失败了。
[如果有人知道如何正确执行此操作,我将很高兴见到。