【问题标题】:How would I separate the MotionListener to a different class?我如何将 ActionListener 分离到不同的类?
【发布时间】:2014-07-18 23:34:45
【问题描述】:

我正在尝试自学 Java,但我被难住了。我要么今天练习太多,要么我只是有一个愚蠢的时刻。

我正在使用绘画和 MouseMotionListener 来在屏幕上拖动图形,我想将 MouseMotionListener 作为一个单独的类。

关于问题:

如何将我的代码中的监听器分成一个单独的类?当我试图把它放在另一个类中时,我最终做了一个循环引用。

代码:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JFrame;


@SuppressWarnings("serial")
class Class1 extends JFrame implements MouseMotionListener{

Point p,p2;


public Class1(){
    p = new Point(0,0);
    this.setSize(500,500);
    //this.setUndecorated(true);
    //this.setBackground(new Color(0.0f, 0.0f, 0.0f, 0.01f));
    this.addMouseMotionListener(this);
    this.setLocationRelativeTo(null);
    this.setVisible(true);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public static void main(String[]args){
    new Class1();
}

public void paint(Graphics g){
    g.setColor(Color.gray);
    g.fillRect(0, 0, 500, 500);
}

public void paintSquare(Graphics g){
    g.fillRect(p.x, p.y, 50, 50);
}

public void paintCover(Graphics g){
    g.setColor(Color.gray);
    g.fillRect(p2.x, p2.y, 50, 50);
}

@Override
public void mouseDragged(MouseEvent e) {
    p2=p;
    p=e.getPoint();
    p.translate(-25, -25);
    paintCover(this.getGraphics());
    paintSquare(this.getGraphics());
}

@Override
public void mouseMoved(MouseEvent e) {
    //do nothing
}

}

【问题讨论】:

  • (在许多情况下,比如你的)有一个循环引用:框架将“知道”监听器实例,并且监听器实例可能有一个引用返回到框架。但是,在任何情况下:NOT 在组件上调用 getGraphics()!以这种方式绘画显然是错误。例如,请参阅docs.oracle.com/javase/tutorial/uiswing/painting 了解简介。
  • 看看Performing Custom Painting看看应该怎么画……
  • 感谢两位提供的资源。正是我需要阅读的内容。

标签: java class paint circular-reference


【解决方案1】:

开始将您的逻辑划分为职责范围...

你需要:

  • 渲染输出的东西
  • 维持当前输出状态的东西
  • 改变当前输出状态的东西

让我们从模型开始...

模型维护有关输出当前状态的信息,它提供了一种可以更改状态的方法,并且可以生成通知以告知感兴趣的对等方状态已更改。

视图负责渲染模型的状态,并监听模型状态的变化,以便在模型变化时自行更新……

MouseMotionListener(在这种情况下)将用于修改模型的状态...

视图和MouseMotionListener 都会引用模型,这样,模型将充当各种组件之间的桥梁。 MouseMotionListener 将用于更新模型,模型将触发视图通知,从而绘制模型的当前状态。

查看model-view-controller了解更多详情。

此外,Swing 中的自定义绘制通常通过覆盖从JComponent 扩展的类的paintComponent 方法来完成。您应该避免覆盖 paint 的顶级容器,如 JFrame 或使用 getGraphics。更多详情请关注Performing Custom Painting

【讨论】:

  • 你解释得很好。非常感谢
  • 有点抽象,但直击要点。你会发现,如果你使用正确的绘画过程,你只需要突出显示“当前”单元格,之前突出显示的单元格将被自动处理;)
【解决方案2】:

MouseMotionListener 是一个接口,参见here。您可以从Class1 实现中有效地“删除”它的唯一方法是将其移动到abstract 类,请参阅here 或创建一些处理所需逻辑的对象。

您可以让抽象类实现MouseMotionListener 并覆盖MouseMotionListener 中定义的所需方法并处理所述抽象类中的逻辑。然后你会extend你的 Class1 与所说的抽象类。

请注意,您没有将其设为抽象类。你也可以有某种MouseMotionHandler 类可以做同样的事情,你可以创建它并将它添加到JFrame,如下所示:

public class MouseMotionHandler implements MouseMotionListener {
    @Override
    public void mouseDragged(MouseEvent e) {
       // do something here
    }

    @Override
    public void mouseMoved(MouseEvent e) {
       //do something here
    }
}

在你的JFrame

MouseMotionHandler mmh = new MouseMotionHandler();
this.addMouseMotionListener(mmh);

您可以查看的另一件事是MouseAdapterhttp://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseAdapter.html

以下是一些参考资料:

http://docs.oracle.com/javase/tutorial/java/concepts/interface.html http://www.javaworld.com/article/2077421/learn-java/abstract-classes-vs-interfaces.html http://www.tutorialspoint.com/java/java_object_classes.htm http://docs.oracle.com/javase/tutorial/java/javaOO/

【讨论】:

  • 有点,我想,除了 OP 谈到 only MoustMotionListener
  • 是的,你写的内容在技术上是正确的,用信息和链接等进行了适当的表述和格式化 - 但它似乎不是针对问题的核心,哪个( 如果我理解正确)是您提议的MouseMotionHandler 需要引用它所属的Class1 实例(“循环引用”)。正如另一条评论中提到的,这实际上不是问题......
  • 您说得对,在这种情况下循环引用可以忽略不计,并且 OP 是否应该遵循您和@MadProgrammer 发布的教程;那么他们将处于更好的状态。
猜你喜欢
  • 1970-01-01
  • 2015-05-13
  • 2019-03-23
  • 2021-12-23
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
相关资源
最近更新 更多