首页  >  文章  >  Java  >  如何在带有嵌套组件的 Java Swing 中有效使用 MouseMotionListener?

如何在带有嵌套组件的 Java Swing 中有效使用 MouseMotionListener?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-10-30 21:56:02244浏览

How to Effectively Use MouseMotionListener in Java Swing with Nested Components?

Java Swing 中的 MouseMotionListener:克服组件拦截

在 Swing 中开发触摸用户界面时,当嵌套组件阻塞时,可能会遇到如何有效使用 MouseMotionListener 接口的挑战事件传播。

MouseMovedEvent 和 MouseDraggedEvent 旨在向上传播 GUI 层次结构,但它们可能会被容器内的组件阻止。例如,当向 JScrollPane 添加 JButton 时,事件可能不再触发 JScrollPane 的 MouseMotionListener。

为了解决此问题,我们提出了一种临时方法,该方法利用 JScrollPane 的内置方法操作,通常用于键绑定。通过调整 N 变量以与您的实现保持一致,此解决方案可以实现事件传播,而无需大量手动事件转发。

这是一个工作示例:

<code class="java">import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Timer;

public class ScrollAction extends JFrame {

    private static final int TILE = 64;
    private static final int DELTA = 16;

    public ScrollAction() {
        setupAndDisplay();
    }

    private void setupAndDisplay() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.lightGray);
                int w = this.getWidth() / TILE + 1;
                int h = this.getHeight() / TILE + 1;
                for (int row = 0; row < h; row++) {
                    for (int col = 0; col < w; col++) {
                        if ((row + col) % 2 == 0) {
                            g.fillRect(col * TILE, row * TILE, TILE, TILE);
                        }
                    }
                }
            }
        };
        panel.setOpaque(false);
        panel.setFocusable(true);
        panel.setPreferredSize(new Dimension(50 * TILE, 50 * TILE));

        final JScrollPane scrollPane = new JScrollPane(panel);
        final JViewport viewport = scrollPane.getViewport();
        viewport.addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                handleMouseMovement(scrollPane, e);
            }
        });
        
        add(scrollPane);            
    }
    
    private static final class ScrollTimer implements ActionListener {

        private static int N = 10;
        private static int DELAY = 100;
        private String cmd;
        private Timer timer;
        private Action action;
        private JScrollPane scrollPane;
        private int count;

        public ScrollTimer(JScrollPane scrollPane, String action) {
            this.cmd = action;
            this.timer = new Timer(DELAY, this);
            this.action = scrollPane.getActionMap().get(action);
            this.scrollPane = scrollPane;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (count++ < N) {
                action.actionPerformed(new ActionEvent(scrollPane, 0, cmd));
            } else {
                timer.stop();
            }
        }

        public void start() {
            count = 0;
            timer.start();
        }

        public void stop() {
            timer.stop();
            count = 0;
        }
    }

    private void handleMouseMovement(JScrollPane scrollPane, MouseEvent e) {
        final ScrollTimer left = new ScrollTimer(scrollPane, "scrollLeft");
        final ScrollTimer right = new ScrollTimer(scrollPane, "scrollRight");
        final ScrollTimer up = new ScrollTimer(scrollPane, "scrollUp");
        final ScrollTimer down = new ScrollTimer(scrollPane, "scrollDown");

        left.stop();
        if (e.getX() < DELTA) {
            left.start();
        }
        right.stop();
        if (e.getX() > viewport.getWidth() - DELTA) {
            right.start();
        }
        up.stop();
        if (e.getY() < DELTA) {
            up.start();
        }
        down.stop();
        if (e.getY() > viewport.getHeight() - DELTA) {
            down.start();
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ScrollAction().setVisible(true);
                pack();
            }
        });
    }
}</code>

以上是如何在带有嵌套组件的 Java Swing 中有效使用 MouseMotionListener?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn