小编典典

单独类中的MouseListener不起作用

java

我有单独的类来处理鼠标侦听器。但是当我在另一个类中使用它时,它不起作用,并且我还不知道如何解决这个问题。这是我的Handler类:

some import stuff

public class Handler implements MouseListener, MouseMotionListener {
private final Canvas canvas;

public Handler(Canvas targetCanvas) {
    this.canvas = targetCanvas;
}

// recasting exception
public Canvas getTargetCanvas() {
    return canvas;
}
...
...
@Override
public void mouseDragged(MouseEvent e) {
    // recasting exception
    DrawingCanvas dC = (DrawingCanvas) getTargetCanvas();
    dC.setMouseDragged(true);
}

@Override
public void mouseMoved(MouseEvent e) {
    // recasting exception
    DrawingCanvas dCanvas = (DrawingCanvas) getTargetCanvas();
    dCanvas.setMouseClicked(true);
    dCanvas.setMouseCoordinates(e.getPoint());
}
}

DrawingCanvas类:

some import stuff

public class DrawingCanvas extends Canvas {
private boolean isMouseDragged, isMouseMoved;
private Point mouseCoordinates;

public DrawingCanvas() {
    this.setPreferredSize(new Dimension(790, 500));
    this.setBackground(Color.WHITE);
}

public Point getMouseCoordinates() {
    return mouseCoordinates;
}

public boolean isIsMouseDragged() {
    return isMouseDragged;
}

public boolean isIsMouseMoved() {
    return isMouseMoved;
}
...
...
public void setMouseDragged(boolean dragged) {
    isMouseDragged = dragged;
}

public void setMouseMoved(boolean moved) {
    isMouseMoved = moved;
}

public void setMouseCoordinates(Point coordinates) {
    mouseCoordinates = coordinates;
}
}

StatusBar类:

some import stuff

public class StatusBar extends JPanel {
private JLabel statusBar;

public StatusBar() {
    statusBar = new JLabel();

    this.setPreferredSize(new Dimension(500, 30));
    this.setBackground(new Color(242,241,240));
    this.add(statusBar, new BorderLayout(5,0));

}

public JLabel getStatusBar() {
    return statusBar;
}

public void setStatusBar(JLabel statusBar) {
    this.statusBar = statusBar;
}
}

和MouseEventGUI类:

some import stuff

public class MouseEventGUI extends JFrame {
private DrawingCanvas drawingCanvas;
private StatusBar statusBar;
private MenuBar menuBar;

public MouseEventGUI() {
    super("Learn Mouse Event");

    drawingCanvas = new DrawingCanvas();
    statusBar = new StatusBar();
    menuBar = new MenuBar();

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(750, 560));

    this.add(menuBar, BorderLayout.NORTH);
    this.add(drawingCanvas, BorderLayout.CENTER);       
    this.add(statusBar, BorderLayout.SOUTH);
    this.addMouseListener(new Handler(drawingCanvas));
    this.addMouseMotionListener(new Handler(drawingCanvas));

    if(drawingCanvas.isIsMouseMoved()){
        statusBar.getStatusBar().setText(String.format("%d, %d", 
                drawingCanvas.getMouseCoordinates().x, 
                drawingCanvas.getMouseCoordinates().y));
    } else {
        statusBar.getStatusBar().setText("Mouse is not listened.");
    }    
}
}

当我运行该程序时,在状态栏中显示“未监听鼠标”(请参见MouseEventGUI类),希望它在画布中移动时显示鼠标光标的坐标。

[更新]

如果在同一个类中,则 可以 进行一些修改 很好地工作 。这是DrawingCanvas类的代码:

public class DrawingCanvas extends JPanel {
private boolean isMouseClicked,
        isMouseMoved;
private Point mouseCoordinates;
protected StatusBar statusBar;
protected MenuBar menuBar;


public DrawingCanvas(StatusBar st) {
    setPreferredSize(new Dimension(790, 500));
    setBackground(Color.WHITE);
    statusBar = st;
    Handlers handlers = new Handlers();
    addMouseListener(handlers);
    addMouseMotionListener(handlers);
}

**// inner class**
protected class Handlers extends MouseAdapter implements MouseListener, MouseMotionListener {

    @Override
    public void mouseClicked(MouseEvent e) {
        statusBar.getStatusBar().setText("Mouse clicked.");
    }

    @Override
    public void mouseMoved(MouseEvent e) {            
        statusBar.getStatusBar().setText(String.format("%d, %d", e.getX(),e.getY()));

    }

}
}

这里是MouseEventGUI类:

public class MouseEventGUI extends JFrame {
private DrawingCanvas drawingCanvas;
private StatusBar statusBar;
private MenuBar menuBar;

public MouseEventGUI() {
    super("Learn Mouse Event");

    statusBar = new StatusBar();
    menuBar = new MenuBar();
    drawingCanvas = new DrawingCanvas(statusBar);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setPreferredSize(new Dimension(750, 560));
    this.add(menuBar, BorderLayout.NORTH);
    this.add(drawingCanvas, BorderLayout.CENTER);       
    this.add(statusBar, BorderLayout.SOUTH);
}
}

但是,出于 可重用的 原因,我计划将其放在单独的类中。


阅读 332

收藏
2020-11-30

共1个答案

小编典典

建议:

  • 是的,使Handler成为完全独立的独立类。
  • 是的,通过MouseEvent的getSource()方法获取您的监听组件。您可以使用instanceof运算符在投射之前检查它是否是正确的对象类型,但是如果总是将它仅添加到一种类型的对象上,那么这不是问题。
  • 是的,正如Camickr和其他人所建议的,不要使用AWT的Canvas,而要使用Swing的JPanel。如果将AWT和Swing组件混合在一起,可能会发生陷阱,如果使用AWT而不是Swing,则会损失很多功能,并且不需要使用Canvas。
  • 我将让MouseListener(在我的代码中,我使用MouseAdapter,因为它可以允许使用稍微更紧凑的代码和更少的不必要代码(例如空方法))通过调用setter方法来更改侦听组件的状态。
  • 我已经通过使该setter方法更改“绑定”属性的状态来很好地完成了这一工作,该属性会通知对它的更改感兴趣的所有PropertyChangeListener。
  • 我只是这样做-使用MouseListener将PropertyChangeListener添加到JPanel,如果发生鼠标事件,它会更改状态JPanel的状态。

例如:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

@SuppressWarnings("serial")
public class HandlerTester extends JPanel {
   public HandlerTester() {
      Handler handler = new Handler();
      final MyPanel myPanel = new MyPanel();
      myPanel.addMouseListener(handler);
      myPanel.addMouseMotionListener(handler);

      final StatusPanel statusPanel = new StatusPanel();

      myPanel.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if (MyPanel.MOUSE_PRESSED.equals(pcEvt.getPropertyName())) {
               statusPanel.setMousePressed(((Boolean)pcEvt.getNewValue()).booleanValue());
            }
         }
      });

      setLayout(new BorderLayout());
      add(myPanel, BorderLayout.CENTER);
      add(statusPanel, BorderLayout.PAGE_END);
   }

   private static void createAndShowGUI() {
      HandlerTester handlerTester = new HandlerTester();

      JFrame frame = new JFrame("HandlerTester");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(handlerTester);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}

class Handler extends MouseAdapter {
   @Override
   public void mousePressed(MouseEvent mEvt) {
      Object src = mEvt.getSource();
      if (src instanceof MyPanel) {
         MyPanel myPanel = (MyPanel) src;
         myPanel.setMousePressed(true);         
      }
   }

   @Override
   public void mouseReleased(MouseEvent mEvt) {
      Object src = mEvt.getSource();
      if (src instanceof MyPanel) {
         MyPanel myPanel = (MyPanel) src;
         myPanel.setMousePressed(false);         
      }
   }
}

@SuppressWarnings("serial")
class MyPanel extends JPanel {
   public static final String MOUSE_PRESSED = "mouse pressed";
   private static final int PREF_W = 600;
   private static final int PREF_H = 400;
   private boolean mousePressed = false;

   public boolean isMousePressed() {
      return mousePressed;
   }

   public void setMousePressed(boolean mousePressed) {
      boolean oldValue = this.mousePressed;
      boolean newValue = mousePressed;
      this.mousePressed = mousePressed;
      firePropertyChange(MOUSE_PRESSED, oldValue, newValue);
   }

   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }
}

@SuppressWarnings("serial")
class StatusPanel extends JPanel {
   private static final String MOUSE_PRESSED = "Mouse Pressed";
   private static final String MOUSE_NOT_PRESSED = "Mouse Not Pressed";
   private JLabel label = new JLabel(MOUSE_NOT_PRESSED);

   public StatusPanel() {
      setLayout(new FlowLayout(FlowLayout.LEADING));
      add(label);
      setBorder(BorderFactory.createEtchedBorder());
   }

   public void setMousePressed(boolean mousePressed) {
      String text = mousePressed ? MOUSE_PRESSED : MOUSE_NOT_PRESSED;
      label.setText(text);
   }
}
2020-11-30