在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中文網其他相關文章!