我正在尝试将MouseListener添加到我的自定义JComponent中。我只想在按下圆的边界时触发MouseListener(JComponent的绘制方法绘制一个圆)。我尝试使用下面的代码,但我无法让它工作(特别是在mousePressed
方法中)。我该如何解决这个问题?
SSCCE:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class AffineTransformTest {
private static TransformingCanvas canvas;
public static void main(String[] args) {
JFrame frame = new JFrame();
canvas = new AffineTransformTest.TransformingCanvas();
TranslateHandler translater = new TranslateHandler();
canvas.addMouseListener(translater);
canvas.addMouseMotionListener(translater);
canvas.addMouseWheelListener(new ScaleHandler());
frame.setLayout(new BorderLayout());
frame.getContentPane().add(canvas, BorderLayout.CENTER);
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
private static class TransformingCanvas extends JComponent {
private double translateX;
private double translateY;
private double scale;
TransformingCanvas() {
translateX = 0;
translateY = 0;
scale = 1;
setOpaque(true);
setDoubleBuffered(true);
}
@Override
public void paint(Graphics g) {
AffineTransform tx = new AffineTransform();
tx.translate(translateX, translateY);
tx.scale(scale, scale);
Graphics2D ourGraphics = (Graphics2D) g;
ourGraphics.setColor(Color.WHITE);
ourGraphics.fillRect(0, 0, getWidth(), getHeight());
ourGraphics.setTransform(tx);
ourGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
ourGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
ourGraphics.setColor(Color.BLACK);
ourGraphics.fillOval(50, 50, 50, 50);
}
}
private static class TranslateHandler implements MouseListener,
MouseMotionListener {
private int lastOffsetX;
private int lastOffsetY;
public void mousePressed(MouseEvent e) {
lastOffsetX = e.getX();
lastOffsetY = e.getY();
double width = canvas.scale * 50;
double height = canvas.scale * 50;
double x = (AffineTransformTest.canvas.getWidth() - width) / 2;
double y = (AffineTransformTest.canvas.getHeight() - height) / 2;
Rectangle2D.Double bounds = new Rectangle2D.Double(x, y, width, height);
System.out.println(bounds + " " + e.getPoint());
if (bounds.contains(e.getPoint())) {
System.out.println("Click!");
}
}
public void mouseDragged(MouseEvent e) {
int newX = e.getX() - lastOffsetX;
int newY = e.getY() - lastOffsetY;
lastOffsetX += newX;
lastOffsetY += newY;
canvas.translateX += newX;
canvas.translateY += newY;
canvas.repaint();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
}
private static class ScaleHandler implements MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
canvas.scale += (.1 * e.getWheelRotation());
canvas.scale = Math.max(0.00001, canvas.scale);
canvas.repaint();
}
}
}
}
答案 0 :(得分:0)
两点:
首先,我将使用Shape或Area对象并使用其.contains()方法。边界始终是围绕整个形状的矩形。此外,当您只需使用JComponent的setBounds()方法时,不确定为什么要创建边界矩形。
其次,可以翻译JComponent的边界,但是我没有找到内置的任何东西来扩展它们。但是,您可以动态更改大小。我正在研究一个相同的问题。现在我正在考虑在我的JComponent扩展时动态更改边界。我试图理解屏幕坐标和JComponent坐标之间的相关性。鼠标坐标似乎总是处于未缩放的框架/屏幕坐标中(可能是我正在使用的全屏模式的工件。我见过的解决方案在JPanel中绘制所有内容,并且不使用离散的JComponents来解决缩放问题。代码有点难以理解,而不是特别模块化,但确实有效。
无论如何,我相信最终可以做到。这只是让数学正确的问题。当我完成它并且它可靠地工作时,我将发布可伸缩JComponent扩展的代码。希望这有点帮助。
答案 1 :(得分:0)
这是代码。一些快速说明,代码中仍然有一些调试,并用System.out.println()替换对LOGGER对象的调用。
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.event.MouseInputListener;
public abstract class LCARSComponent extends JComponent implements MouseInputListener {
/**
* A reference to the global Logger object.
*/
protected final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
protected int x;
protected int y;
protected int w;
protected int h;
protected double scaleFactor = 1.0;
protected Area area;
protected Area scaledArea;
protected int style;
protected Color color;
protected AffineTransform renderingTransform;
protected ActionListener actionListener;
public LCARSComponent(Container parent, int x, int y, int w, int h, int style) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.style = style;
setBounds(x,y,w,h);
addMouseListener(this);
}
@Override
protected void paintComponent(Graphics g) {
/**
* First, paint the background if the component is opaque. Required when
* JComponent is extended, and the paintCompnent() method is overridden.
*/
if(isOpaque()) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
/**
* Create a Graphics2D object so we can use Java 2D features.
*/
Graphics2D g2d = (Graphics2D) g.create();
/**
* Set the anti aliasing rendering hint and the color to draw with.
*/
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
scaleComponent();
/**
* Draw the Area object of the LCARS component, and fill it.
*/
g2d.draw(scaledArea);
g2d.fill(scaledArea);
g2d.drawRect(scaledArea.getBounds().x, scaledArea.getBounds().y, scaledArea.getBounds().width, scaledArea.getBounds().height);
/**
* Clean up when the method has completed by disposing the Graphics2D object that was created.
*/
g2d.dispose();
}
protected void scaleComponent() {
double sw = (double)getParent().getWidth() / (double)getParent().getPreferredSize().width;
double sh = (double)getParent().getHeight() / (double)getParent().getPreferredSize().height;
LOGGER.info("scaledWidth = " + sw);
LOGGER.info("scaledHeight = " + sh);
double scaleFactor;
if(sh < sw) {
scaleFactor = sh;
}
else {
scaleFactor = sw;
}
LOGGER.info("scaleFactor = " + scaleFactor);
if(scaleFactor != this.scaleFactor) {
this.scaleFactor = scaleFactor;
scaledArea = new Area(area);
renderingTransform = new AffineTransform();
renderingTransform.scale(scaleFactor, scaleFactor);
scaledArea.transform(renderingTransform);
}
setBounds((int)(this.x*scaleFactor), (int)(this.y*scaleFactor), this.getWidth(), this.getHeight());
}
public Point screenToComponent(Point pt) {
if(renderingTransform == null) {
Graphics2D g2d = (Graphics2D)(this.getParent().getGraphics());
renderingTransform = g2d.getTransform();
}
Point2D pt2d = renderingTransform.transform(pt,null);
LOGGER.info("mouse click: " + pt.getX() + ", " + pt.getY() + " -- " + pt2d.getX() + ", " + pt2d.getY());
return new Point((int)Math.round(pt2d.getX()), (int)Math.round(pt2d.getY()));
}
public void setActionListener(ActionListener actionListener) {
this.actionListener = actionListener;
}
@Override
public void mouseClicked(MouseEvent e) {
Point pt = e.getPoint();
LOGGER.info("mouseClicked: " + this.getName() + " - " + pt.getX() + ", " + pt.getY());
if(area.contains(e.getPoint())) {
if(actionListener != null) {
actionListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), e.paramString()));
}
if(color.equals(Color.black))
color = Color.blue;
else
color = Color.black;
this.repaint();
}
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
if(area.contains(e.getLocationOnScreen()))
System.out.println("mousePressed()...");
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
if(area.contains(e.getLocationOnScreen()))
System.out.println("mouseReleased()...");
}
@Override
public void mouseEntered(MouseEvent e) {
Point pt = e.getPoint();
// TODO Auto-generated method stub
System.out.println("mouseEntered()...");
LOGGER.info("mouseEntered: " + this.getName() + " - " + pt.getX() + ", " + pt.getY());
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
Point pt = e.getPoint();
System.out.println("mouseExited()...");
LOGGER.info("mouseExited: " + pt.getX() + ", " + pt.getY());
}
@Override
public void mouseDragged(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("mouseDragged()...");
}
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
System.out.println("mouseMoved()...");
}
}