【问题标题】:Where can I put mouse event handling code so that it is out of the way but can still manipulate objects?我在哪里可以放置鼠标事件处理代码以便它不碍事但仍然可以操作对象?
【发布时间】:2012-03-07 10:56:31
【问题描述】:

我在这里学习 Java,并尝试掌握类以及如何最好地为我的小游戏捕捉鼠标事件等,所以请耐心等待并给我一些提示。

我项目的主类扩展了JFrame,并在构造时为其自身添加了一个扩展JPanel 的类的对象。这个JPanel 覆盖了整个窗口,这就是我用来在屏幕上绘制东西的地方。然后我有一个名为Scene 的类,它只扩展了对屏幕上当前对象的所有引用,并负责将它们全部编译并将它们传递回JPanel。我不想将完整的鼠标事件代码放在 JPanel 中,因为它会很乱,所以我想为它创建另一个名为 MEs 的类,并让每个场景都有一个。我的想法是,这样每个mes 对象都可以轻松访问每个场景中的对象。所以我的代码是这样的:

class DPanel extends JPanel {
    Scene scCurrent;

    public DPanel() {
        scCurrent = new Scene();
        addMouseMotionListener(new MouseAdapter() { 
            public void mouseMoved(MouseEvent me) { scCurrent.mes.moved(me); } 
        });
...
    }

...

当然,inside scCurrent.mes.moved() 我什至不知道如何更改光标。它无法识别其中的setCursor()。如何更改光标并访问树上较高的对象,就像我需要切换场景一样?或者有没有其他地方我可以把我的鼠标事件处理代码塞进我的 JPanel 中?

【问题讨论】:

    标签: java swing class event-handling


    【解决方案1】:

    您正试图将控制代码与视图 (GUI) 代码分开,这是一件好事。一种解决方案是为视图代码提供允许外部代码更改其状态的公共方法,并为控件类提供对视图的引用,以便控件(即,MouseListeners、MouseMotionListeners、ActionListeneres)可以在适当的引用上调用这些方法并更改视图的状态。

    编辑 1
    给你看一个例子可能更容易:

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    
    public class ViewControl {
    
       private static void createAndShowGui() {
          View view = new View();
          Control control = new Control(view);
          view.addMouseAdapter(control);
    
          JFrame frame = new JFrame("ViewControl");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(view);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class View extends JPanel {
       private static final int PREF_W = 400;
       private static final int PREF_H = PREF_W;
       private List<Point> points = new ArrayList<Point>();
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          if (points.size() > 1) {
             for (int i = 0; i < points.size() - 1; i++) {
                int x1 = points.get(i).x;
                int y1 = points.get(i).y;
                int x2 = points.get(i + 1).x;
                int y2 = points.get(i + 1).y;
    
                g.drawLine(x1, y1, x2, y2);
             }
          }
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    
       public void addMouseAdapter(MouseAdapter adapter) {
          // addMouseListener(adapter);
          addMouseMotionListener(adapter);
       }
    
       public void addPoint(Point p) {
          points.add(p);
          repaint();
       }
    }
    
    class Control extends MouseAdapter {
       private View view;
    
       public Control(View view) {
          this.view = view;
       }
    
       @Override
       public void mouseDragged(MouseEvent e) {
          view.addPoint(e.getPoint());
       }
    }
    

    【讨论】:

    • 感谢您的回复@Hovercraft Full Of Eels,这听起来像是我需要的建议。听起来如此优雅和简单!但是如何将引用传递给控件类?如果我尝试调整控件类以接受引用作为另一个变量,如 scCurrent.mes.moved(this,me); 它认为 this 意味着鼠标适配器
    • 啊,通过创建一个扩展 MouseAdapter 的新类,并在创建 JPanel 的同一级别的新实例时为其提供引用...巧妙!谢谢@Hovercraft Full Of Eels,现在更清楚了:)
    • @Jimmy:不客气!还有更详细的MVC例子,请看我的例子herehere
    猜你喜欢
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2021-09-09
    相关资源
    最近更新 更多