フレーム内の要素を移動するために GlassPane を使用しています。ドラッグされた要素がない場合、すべてのマウスイベントは通常の方法で送出されます
public class MainFrame implements MouseListener {
private JFrame frame;
public MainFrame()
{
frame = new JFrame();
JPanel testPanel = new JPanel();
testPanel.addMouseListener(this);
JLabel testLabel = new JLabel("Test",JLabel.CENTER);
testPanel.add(testLabel);
frame.add(testPanel);
frame.pack();
frame.setVisible(true);
GlassPanel glassPanel = new GlassPanel(frame);
frame.setGlassPane(glassPanel);
// Without this line the click in the panel is mentioned.
// otherwise it is ignored.
frame.getGlassPane().setVisible(true);
}
@Override
public void mouseClicked(MouseEvent e)
{
System.out.print("CLicked");
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public class GlassPanel extends JPanel implements MouseMotionListener, MouseListener
{
private JFrame frame;
public GlassPanel(JFrame mainframe)
{
frame = mainframe;
setLayout(null);
setOpaque(false);
addMouseMotionListener(this);
addMouseListener(this);
}
@Override
public void mouseClicked(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mousePressed(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mouseReleased(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mouseEntered(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mouseExited(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mouseDragged(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
@Override
public void mouseMoved(MouseEvent e)
{
redispatchMouseEvent(e, true);
}
private void redispatchMouseEvent(MouseEvent e, boolean repaint)
{
System.out.println("Dispatch");
Point glassPanePoint = e.getPoint();
Container container = frame.getContentPane();
Point containerPoint = SwingUtilities.convertPoint(frame.getGlassPane(),
glassPanePoint, container);
if (containerPoint.y < 0) { // we're not in the content pane
// Could have special code to handle mouse events over
// the menu bar or non-system window decorations, such as
// the ones provided by the Java look and feel.
} else {
// The mouse event is probably over the content pane.
// Find out exactly which component it's over.
Component component = SwingUtilities.getDeepestComponentAt(
container, containerPoint.x, containerPoint.y);
if (component != null) {
// Forward events to component below
Point componentPoint = SwingUtilities.convertPoint(
frame.getGlassPane(), glassPanePoint, component);
component.dispatchEvent(new MouseEvent(component, e
.getID(), e.getWhen(), e.getModifiers(),
componentPoint.x, componentPoint.y, e
.getClickCount(), e.isPopupTrigger()));
}
}
}
}
}
しかし、これにより、マウス イベント処理で異常な動作が発生します。例: マウス リスナーを持つ JPanel があります。このパネルをダブルクリックすると、別のフレームが開きます。このパネルにはいくつかのラベルがあります。Glasspane がない場合、このラベルをクリックできます。ラベルはマウス イベントに作用しないため、イベントはパネルに渡され、クリック アクションが実行されます。ディスパッチ ルーチンを使用するとき、マウス イベントをラベルに直接ディスパッチしますが、これはもちろんアクションにつながりません。
では、どうすればこれを修正できますか?もちろん、Panel への参照を使用して独自のラベル クラスを作成し、マウス イベントを再びパネルにディスパッチすることもできますが、これは適切な設計とは言えません。2 つ目は、Glasspane ディスパッチャーで、最も深いパネルがマウス イベントに関心があるかどうかを判断できることです。
何か案は?