2

我正在尝试使用 swing 开发一个 GUI 界面,其中组件可以通过侦听器与其他组件进行通信。我遇到的问题是:-

方法


  1. 实现监听器
  2. 使用匿名方法添加具有侦听器方法的侦听器
  3. 从实现监听器的类中添加监听器

问题


  1. 在处理大量对象时,实现侦听器会导致试图对对象进行操作会造成混乱
  2. 与 1 相同,但构造函数需要匿名方法的 final
  3. 不能在不诉诸静态引用的情况下对侦听类之外的对象进行操作。

这真的很令人沮丧,因为我怎样才能让 MouseListenerClass 在作为单独 JFrame 类的一部分的 JPanel 上绘制而不将 JPanel 传递给 mouseListenerClass 以对其进行操作。

我似乎可以使用的唯一方法是创建一个名为 MouseState 的 Enum,当触发鼠标事件 MousePressed 时,它将静态 Enum mouseStatus 设置为按下,然后 JPanel paintComponent 方法检查 Enum mouseStatus 并在按下时进行绘制。

这似乎是错误的方式。

还有其他方法吗?

更新以反映 Cyrille 的评论:-

谢谢@Cyrille,我不得不使用强制转换来修改您的代码,但前提仍然有效。' public void mousePressed(MouseEvent e) {

    PaintPanel p=(PaintPanel) getTargetPanel();
    p.setMousePressed(true);
    p.setMouseCoords(e.getPoint());
}


public void mouseReleased(MouseEvent e) {
    PaintPanel p=(PaintPanel) getTargetPanel();
    p.setMousePressed(false);

}

public JPanel getTargetPanel() {
    return targetPanel;
}'
4

2 回答 2

2

您的鼠标侦听器不应在 JPanel 上绘制。相反,您应该使用 MVC(模型-视图-控制)模式。

例如,您将设置 3 个类:面板、侦听器和一个用于保存数据的类(一个模型类)。当监听器被触发时,它应该编辑模型。然后模型可以通知面板发生了一些变化,面板可以检查模型中的数据并绘制适当的像素。有关详细信息,请参阅http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

顺便说一句:这是大多数标准 Swing 组件的工作方式。只有非常简单的组件(JPanel、JTextField 等)才允许使用,并且基于这些组件制作复杂的组件您应该使用 MVC

于 2013-07-05T14:33:39.180 回答
1

您不必使用任何类型的静态变量。您应该创建 JPanel 的子类来处理绘画,并在此类中提供一个方法供侦听器与之通信:

public class MyPanel extends JPanel {

    // status used for drawing, can be anything you want, but let's say you need to know if the mouse is pressed.
    private boolean isMousePressed;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // do your stuff here, using isMousePressed
    }

    public void setMousePressed(boolean pressed) {
        isMousePressed= pressed;
    }
}

然后,您的鼠标侦听器必须具有对 MyPanel 实例的引用并使用正确的方法与其进行通信。

public class PaintingMouseListener implements MouseListener {

    private final JPanel targetPanel;


    public PaintingMouseListener(JPanel targetPanel) {
        this.targetPanel = targetPanel;
    }


    @Override
    public void mousePressed(MouseEvent e) {
        targetPanel.setMousePressed(true);

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        targetPanel.setMousePressed(false);
    }

    // other methods of the listener
}

然后使用对面板的引用创建鼠标侦听器。

    MyPanel targetPanel = new MyPanel();
    // assign the mouse listener to whatever component needs it.
    component.addMouseListener(new PaintingMouseListener(targetPanel));

这类似于 MVC 解决方案,除了它将模型(变量isMousePressed)和视图(MyPanel)放在一起。对于这么简单的东西,把它们放在一起比较简单,但是随着事情变得越来越复杂,最好把它们分开,把模型放在一个单独的类中。

于 2013-07-05T14:39:33.540 回答