3

の上にJFrameと がたくさんあります。を利用する必要があり、この実装を使用してセットアップしました。JComponentsJFrameJGlassPane

   JPanel glass = new JPanel();
   frame.setGlassPane(glass);
   glass.setVisible(true);
   glass.setOpaque(false);

JButtonsその後、 のJComponents下で何も選択できませんJGlassPane

GlassPaneの下のコンポーネントを選択する機能を持ちながら、選択可能なコンポーネントのみを表示する方法はありGlassPaneますか?

編集私はガラス板にaMouseListenerと a の両方を取り付けたことを言及するのを忘れていました (これが関連することを知りませんでした) 。MouseMotionListenerマウス イベントを他のコンポーネントに渡し、必要な場合にのみ使用する方法はありますか?

4

3 に答える 3

6

mouseListener が処理したくないイベントをディスパッチするようにします。

以下のコード例は、 @whiskeyspider による素敵な SSCCE とチュートリアルを使用して混合されています (ところで: チュートリアルを調べることは、問題を解決するための良い出発点です :-)

ml = new MouseListener() {
    @Override
    public void mousePressed(MouseEvent e) {
        dispatchEvent(e);
    }
    // same for all methods
    // ....

    private void dispatchEvent(MouseEvent e) {
        if (isBlocked)
            return;
        Point glassPanePoint = e.getPoint();
        Container container = frame.getContentPane();
        Point containerPoint = SwingUtilities.convertPoint(glass,
                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(
                        glass, glassPanePoint, component);
                component.dispatchEvent(new MouseEvent(component, e
                        .getID(), e.getWhen(), e.getModifiers(),
                        componentPoint.x, componentPoint.y, e
                                .getClickCount(), e.isPopupTrigger()));
            }
        }
    }
};

glass.addMouseListener(ml);
glassButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent ae) {
        if (isBlocked) {
            // glass.removeMouseListener(ml);
            glassButton.setText("Block");
        } else {
            // ml = new MouseAdapter() { };
            // glass.addMouseListener(ml);
            glassButton.setText("Unblock");
        }

        isBlocked = !isBlocked;
    }
});
于 2012-11-07T10:20:21.480 に答える
2

これは、ガラスペインのJButtonの例です。これをクリックすると、マウスイベントのキャプチャが切り替わります([テスト]ボタンをクリックできません)。

public class Test
{
    private static boolean isBlocked = false;
    private static MouseListener ml;

    public static void main(String[] args)
    {
        JButton button = new JButton("Test");
        button.setPreferredSize(new Dimension(100, 100));

        final JButton glassButton = new JButton("Block");

        JPanel panel = new JPanel();
        panel.add(button);

        final JPanel glass = new JPanel();
        glass.setOpaque(false);
        glass.add(glassButton);

        final JFrame frame = new JFrame();
        frame.setGlassPane(glass);
        glass.setVisible(true);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);

        glassButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (isBlocked) {
                    glass.removeMouseListener(ml);
                    glassButton.setText("Block");
                } else {
                    ml = new MouseAdapter() { };
                    glass.addMouseListener(ml);
                    glassButton.setText("Unblock");
                }

                isBlocked = !isBlocked;
            }
        });
    }
}
于 2012-11-06T22:42:56.803 に答える
2

Swing イベント チェーンを中断しない別の解決策は、AWTEventListener代わりに a を使用することです。次のように、通常のガラス板BetterGlassPaneの代わりに使用する を実装しました。JPanel

JFrame frame = ...; // any JRootPane will do...
BetterGlassPane glass = new BetterGlassPane(frame);

これは、質問に示されているように、「従来の」方法でも機能します。

JPanel glass = new BetterGlassPane();
frame.setGlassPane(glass);    
glass.setRootPane(frame);

お役に立てれば。GitHub でプロジェクトを自由に複製するか、Maven 依存関係を使用してください。

<dependency>
  <groupId>lc.kra.swing</groupId>
  <artifactId>better-glass-pane</artifactId>
  <version>0.1.3</version>
</dependency>
<repositories>
  <repository>
    <id>better-glass-pane-mvn-repo</id>
    <url>https://raw.github.com/kristian/better-glass-pane/mvn-repo/</url>
    <snapshots>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
    </snapshots>
  </repository>
</repositories>

短い、自己完結型、正しい、例 (SSCCE、必須の Maven 依存関係なし):

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

import lc.kra.swing.BetterGlassPane;

public class TestBetterGlassPane {
    public static void main(String[] args) {
        final JFrame frame = new JFrame("BetterGlassPane Test");
        frame.setLayout(null);
        frame.setSize(400,300);
        frame.setResizable(false);
        frame.setLocationByPlatform(true);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        BetterGlassPane glassPane = new BetterGlassPane(frame.getRootPane()) {
            private static final long serialVersionUID = 1L;
            @Override protected void paintComponent(Graphics graphics) {
                super.paintComponent(graphics);
                graphics.setColor(Color.BLACK);
                graphics.drawRect(20,160,360,50);
                graphics.setFont(graphics.getFont().deriveFont(Font.BOLD));
                graphics.drawString("I'm the glass pane, click me!",120,190);
            }
        };
        glassPane.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent event) {
                if(new Rectangle(20,180,360,50).contains(event.getPoint()))
                    JOptionPane.showMessageDialog(frame,"I'm the glass pane!");
            }
        });
        glassPane.setLayout(null);

        ActionListener defaultActionListener = new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                JOptionPane.showMessageDialog(frame,
                    ((JButton)event.getSource()).getText());
            }
        };

        JButton frameButton = new JButton("I'm on the frame!");
        frameButton.addActionListener(defaultActionListener);
        frameButton.setBounds(20,20,360,50);
        frame.add(frameButton);

        JButton glassPaneButton = new JButton("I'm on the glass pane!");
        glassPaneButton.addActionListener(defaultActionListener);
        glassPaneButton.setBounds(20,90,360,50);
        glassPane.add(glassPaneButton);

        frame.setVisible(true);
    }
}
于 2016-01-04T20:51:18.550 に答える