2011-08-26 60 views
2

我正在使用Swing中的Touch用户界面。虽然我知道这不是最佳的,但我只是在一个很短的截止日期,没有时间触摸特定的GUI软件包(如果有的话)。Java Swing中的MouseMotionListener,使用它与组件内部的组件等

我希望我的用户能够在屏幕上“滑动”他们的手指,并且我制作的特殊JScrollPane的视图也随之移动。 的代码非常简单 -

public class PanScrollPane extends JScrollPane implements MouseMotionListener{ 
public PanScrollPane() { 
    super();   
    this.addMouseMotionListener(this);  
} 
@Override 
public void mouseDragged(MouseEvent arg0) { 
    System.out.println("Mouse Dragged!");  
} 
@Override 
public void mouseMoved(MouseEvent arg0) { 
    System.out.println("Mouse Moved!");  
} 

我遇到的问题是,JScrollPane的是各种JComponents的容器。当我第一次开始研究这个时,我认为MouseMovedEvent和MouseDraggedEvent会向上传播'GUI树',直到他们遇到一个具有特定于该事件的侦听器的Component。现在看来,我添加到panScrollPane的任何组件都会阻止任何这些MouseMotion事件,使我无法平移。

panScrollPane.add(new JButton("This thing blocks any mouse motion events")); 

我想通手传播的MouseEvent(添加听众每一个部件,然后让他们的事件发送到他们的父母)会工作。但是,这是一项非常耗时的工作,因为我宁愿花时间处理其他事情,所以我想知道您是否有任何人知道解决此问题的方法。

感谢您的阅读,并希望谢谢您的回答! :)

编辑:使我的意图更清晰。我只希望mousemotion事件被panPanel捕获,任何其他事件(如MouseClick,MouseRelease)都应该正常处理

回答

2

如何使用GlassPane?我认为它意在处理这些类型的情况。

+0

看起来很有希望,但玻璃窗会“捕捉”我感兴趣的“捕捉”事件(MouseMotion的事件)还是每一个可能的事件? –

+0

对,教程代码展示了如何让它传播任何剩余的事件,我会用这个玻璃窗格来测试:)谢谢! –

+0

@Erwin您可以将MouseInputAdapter作为mouseListner添加到父级以侦听拖动事件。其他事件,我认为只会通过它发送给子组件。 –

2

获取组件及其所有子组件的mouseEvent是很棘手的。你可能会考虑依赖于稳定(和广泛测试:-)的代码。这样做的jdk7方式是使用JLayer(内部注册AWTEventListener,因为它具有所有权限)。对于早期版本,您可以使用其前身JXLayer

+0

或只是为了确定鼠标按键是否仍然按下+1 – mKorbel

7

特设方法利用了通常在key bindings使用现有JScrollPane行动。您必须调整N才能执行Scrollable

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; 

/** @see http://stackoverflow.com/questions/7201509 */ 
public class ScrollAction extends JPanel { 

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

    public ScrollAction() { 
     this.setOpaque(false); 
     this.setFocusable(true); 
     this.setPreferredSize(new Dimension(50 * TILE, 50 * TILE)); 
    } 

    @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); 
       } 
      } 
     } 
    } 

    private void display() { 
     JFrame f = new JFrame("ScrollAction"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     final JScrollPane scrollPane = new JScrollPane(this); 
     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"); 
     final JViewport viewPort = scrollPane.getViewport(); 
     viewPort.setPreferredSize(new Dimension(5 * TILE, 5 * TILE)); 
     viewPort.addMouseMotionListener(new MouseAdapter() { 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       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(); 
       } 
      } 
     }); 
     f.add(scrollPane); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    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; 
     } 
    } 

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

      @Override 
      public void run() { 
       new ScrollAction().display(); 
      } 
     }); 
    } 
} 
+0

然后只需添加mouseDragged()用于垂直动作+1 – mKorbel

+0

添加了包含垂直动作的示例。 – trashgod

+0

不错,很好嗯... – mKorbel