我在互联网上找到了一些代码,可以用Java控制可滚动面板的缩放和平移,但我希望能够操作该区域内的形状,并且难以将x和y坐标转换回原始(未缩放(尺寸。。
我想对这些形状做一些事情,但首先,当鼠标在两个实体矩形中移动时,我如何将它们涂成红色?
这是我迄今为止的代码:
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class CanvasPane extends JPanel {
private static Canvas canvas;
public CanvasPane(boolean isDoubleBuffered) {
super(isDoubleBuffered);
setLayout(new BorderLayout());
canvas = new Canvas(1.0);
JScrollPane pane = new JScrollPane(canvas);
pane.getViewport().setBackground(Color.DARK_GRAY);
add(pane, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Test Graphics");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new CanvasPane(true), BorderLayout.CENTER);
frame.pack();
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//Initial scrolling of the canvas to its center
Rectangle canvasRectangle = canvas.getBounds();
Rectangle visibleRectangle = canvas.getVisibleRect();
double tx = (canvasRectangle.getWidth() - visibleRectangle.getWidth())/2;
double ty = (canvasRectangle.getHeight() - visibleRectangle.getHeight())/2;
visibleRectangle.setBounds((int)tx, (int)ty, visibleRectangle.width, visibleRectangle.height);
canvas.scrollRectToVisible(visibleRectangle);
}
}
class Canvas extends JComponent implements MouseWheelListener, MouseMotionListener, MouseListener {
private static final long serialVersionUID = 1L;
private double zoom = 1.0;
public static final double SCALE_STEP = 0.1d;
private Dimension initialSize;
private Point origin;
private double previousZoom = zoom;
private double scrollX = 0d;
private double scrollY = 0d;
private Rectangle2D workspace = new Rectangle2D.Double(0,0, 1024, 768);
private Rectangle entity1 = new Rectangle(10, 10, 100, 100);
private Rectangle entity2 = new Rectangle(300, 300, 100, 100);
public Canvas(double zoom) {
this.zoom = zoom;
addMouseWheelListener(this);
addMouseMotionListener(this);
addMouseListener(this);
setAutoscrolls(true);
setPreferredSize(new Dimension((int)workspace.getWidth(), (int)workspace.getHeight()));
}
@Override public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
//Zoom graphics
g2d.scale(zoom, zoom);
//translate graphics to be always in center of the canvas
Rectangle size = getBounds();
double tx = ((size.getWidth() - workspace.getWidth() * zoom) / 2) / zoom;
double ty = ((size.getHeight() - workspace.getHeight() * zoom) / 2) / zoom;
g2d.translate(tx, ty);
//Draw
g2d.setColor(Color.LIGHT_GRAY);
g2d.fill(workspace);
g2d.setColor(Color.DARK_GRAY);
g2d.setStroke(new BasicStroke(5.0f));
g2d.draw(workspace);
g2d.draw(entity1);
g2d.draw(entity2);
}
@Override public void setSize(Dimension size) {
super.setSize(size);
if (initialSize == null) {
this.initialSize = size;
}
}
@Override public void setPreferredSize(Dimension preferredSize) {
super.setPreferredSize(preferredSize);
if (initialSize == null) {
this.initialSize = preferredSize;
}
}
public void mouseWheelMoved(MouseWheelEvent e) {
double zoomFactor = -SCALE_STEP * e.getPreciseWheelRotation() * zoom;
zoom = Math.abs(zoom + zoomFactor);
//Here we calculate new size of canvas relative to zoom.
Dimension d = new Dimension(
(int)(initialSize.width * zoom),
(int)(initialSize.height * zoom));
setPreferredSize(d);
setSize(d);
validate();
followMouseOrCenter(e.getPoint());
previousZoom = zoom;
}
public void followMouseOrCenter(Point2D point) {
Rectangle size = getBounds();
Rectangle visibleRect = getVisibleRect();
scrollX = size.getCenterX();
scrollY = size.getCenterY();
if (point != null) {
scrollX = point.getX() / previousZoom * zoom - (point.getX() - visibleRect.getX());
scrollY = point.getY() / previousZoom * zoom - (point.getY() - visibleRect.getY());
}
visibleRect.setRect(scrollX, scrollY, visibleRect.getWidth(), visibleRect.getHeight());
scrollRectToVisible(visibleRect);
}
public void mouseDragged(MouseEvent e) {
if (origin != null) {
int deltaX = origin.x - e.getX();
int deltaY = origin.y - e.getY();
Rectangle view = getVisibleRect();
view.x += deltaX;
view.y += deltaY;
scrollRectToVisible(view);
}
}
public void mousePressed(MouseEvent e) {
origin = new Point(e.getPoint());
}
public void mouseMoved(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
我已经尝试使用以下代码进行计算,但这不是很正确的
public void mouseMoved(MouseEvent e) {
double x = e.getX() / zoom;
double y = e.getY() / zoom;
double x2 = getWidth() - workspace.getWidth() * zoom;
double y2 = getHeight() - workspace.getHeight() * zoom;
if(x2 > 0) x -= x2;
if(y2 > 0) y -= y2;
Point p = new Point((int)x, (int)y);
if(entity1.contains(p)) {
intersects = true;
}
else {
intersects = false;
}
repaint();
}
这似乎效果更好,但我不确定它是否是最干净的解决方案。。。
public void mouseMoved(MouseEvent e) {
double x = e.getX() / zoom;
double y = e.getY() / zoom;
// double x2 = getWidth() - workspace.getWidth() * zoom;
// double y2 = getHeight() - workspace.getHeight() * zoom;
double x2 = ((getWidth() - workspace.getWidth() * zoom) / 2) / zoom;
double y2 = ((getHeight() - workspace.getHeight() * zoom) / 2) / zoom;
if(x2 > 0) x -= x2;
if(y2 > 0) y -= y2;
Point p = new Point((int)x, (int)y);
if(entity1.contains(p)) {
intersects = true;
}
else {
intersects = false;
}
repaint();
}