如果子组件添加了鼠标侦听器,则会在其中处理鼠标事件,并且父组件中的鼠标侦听器不会听到它们。
以下代码中说明了这种情况。
我想用更精细的颗粒分离处理是什么?例如,在一个组件中处理双击,在另一个组件中单击一次。怎么做到这一点?
更新
在下面的示例中,如果复选框为ON,则子(黄色方块)正在处理鼠标事件。在这种情况下,父(灰色)停止处理单击。我希望父母仍然可以在双子进程双击的情况下同时处理单击。
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Try_ChildEvents {
public static void main(String[] args) {
final MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 ) {
System.out.println("Double clicked inside inner");
}
}
};
final JPanel inner = new JPanel();
{
inner.setBackground(Color.yellow);
}
inner.addMouseListener(mouseAdapter);
JPanel outer = new JPanel();
{
outer.setLayout(null);
outer.add(inner);
inner.setBounds(50, 50, 100, 100);
}
outer.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1 ) {
System.out.println("Single clicked in outer");
}
}
});
JCheckBox check = new JCheckBox("Enable events", true);
check.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if( e.getStateChange() == ItemEvent.SELECTED ) {
inner.addMouseListener(mouseAdapter);
}
else {
inner.removeMouseListener(mouseAdapter);
}
}
});
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(check, BorderLayout.NORTH);
frame.add(outer, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
更新2
我做了@camickr sadi并且它有效,但我不明白,为什么?为什么不派遣事件再次回到孩子身上?
package tests;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Try_ChildEvents {
public static void main(String[] args) {
class JPanelWithTurnableListener extends JPanel {
final MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 ) {
System.out.println("Double clicked inside inner");
}
else {
MouseEvent mouseEvent = new MouseEvent(
(Component) e.getSource(),
e.getID(),
e.getWhen(),
e.getModifiers(),
e.getX(),
e.getY(),
e.getXOnScreen(),
e.getYOnScreen(),
e.getClickCount(),
e.isPopupTrigger(),
e.getButton()
);
getParent().dispatchEvent(mouseEvent);
}
}
};
boolean on;
public JPanelWithTurnableListener() {
setBackground(Color.yellow);
addMouseListener(mouseAdapter);
}
boolean isOn() {
return on;
}
void setOn(boolean newValue) {
boolean oldValue = this.on;
if( newValue != oldValue ) {
this.on = newValue;
if( newValue ) {
addMouseListener(mouseAdapter);
}
else {
removeMouseListener(mouseAdapter);
}
}
}
}
final JPanelWithTurnableListener inner = new JPanelWithTurnableListener();
JPanel outer = new JPanel();
{
outer.setLayout(null);
outer.add(inner);
inner.setBounds(50, 50, 100, 100);
}
outer.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1 ) {
System.out.println("Single clicked in outer");
}
}
});
JCheckBox check = new JCheckBox("Enable events", true);
check.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if( e.getStateChange() == ItemEvent.SELECTED ) {
inner.setOn(true);
}
else {
inner.setOn(false);
}
}
});
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(check, BorderLayout.NORTH);
frame.add(outer, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
答案 0 :(得分:2)
使用Component.dispatchEvent(...)
方法将事件重新分发到父组件。您需要创建一个新的MouseEvent。
请参阅How to Use Root Panes中的GlassPane示例。它将事件从玻璃窗格重新分派到玻璃窗格下的组件。