我有一个面板,其中一些2D物体正在移动。我已根据需要覆盖了paintComponent()。现在我希望能够放大并缩小该区域。放大时,将显示滚动条,通过滚动条可以查看整个字段。在放大和缩小时,2D对象应相应地增大或减小。哪个Swing组件或更确切的组件组合将有助于实现这一目标?
答案 0 :(得分:14)
最简单的方法是修改面板并引入一个指示缩放级别的双精度。此双精度表示您的比例,其中1表示正常,较高表示放大。您可以在Graphics2D
中将{2}与paintComponent
一起使用。
如:
Graphics2D g2 = (Graphics2D) g;
int w = // real width of canvas
int h = // real height of canvas
// Translate used to make sure scale is centered
g2.translate(w/2, h/2);
g2.scale(scale, scale);
g2.translate(-w/2, -h/2);
对于滚动,将面板放在JScrollPane中,并将其与同样使用缩放比例的getPreferredSize结合使用。 JScrollPane使用您放入其中的组件的首选大小。如果首选大小超过自己的大小,它将显示滚动条。
如果更改面板的首选大小,使其返回的宽度和高度缩放,则应该没问题。基本上你可以返回类似的东西:
return new Dimension(w * scale, h * scale)
答案 1 :(得分:2)
我知道这个问题已经过时了,但我想我可以发布我的解决方案,以防将来对某人有用。
因此,我创建了一个扩展JPanel的类,该类实现了MouseWheelListener,以便检测用户何时滚动鼠标。我的班级还会监听拖动,以便在用户点击和拖动时移动内容。
首先,在构造函数中,您必须将其设置为MouseWheelListener
addMouseWheelListener(this);
对于放大和缩小,我使用布尔值zoomer
(表示用户何时用鼠标滚动)和两个双倍zoomFactor
(以保持对象尺寸的当前因子乘以)和prevZoomFactor
(对于先前的缩放系数)。
private double zoomFactor = 1;
private double prevZoomFactor = 1;
private boolean zoomer;
我还覆盖了JPanel的paint()
方法,当用户放大(zoomer
= true)时(在绘制任何东西之前)我按zoomFactor
缩放图形。代码:
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
if (zoomer) {
AffineTransform at = new AffineTransform();
at.scale(zoomFactor, zoomFactor);
prevZoomFactor = zoomFactor;
g2.transform(at);
zoomer = false;
}
// All drawings go here
}
最后,我覆盖MouseWheelListener的mouseWheelMoved
方法,其中我增加了zoomFactor
(如果用户卷起)或减少zoomFactor
(如果用户滚动) 。代码:
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
zoomer = true;
//Zoom in
if (e.getWheelRotation() < 0) {
zoomFactor *= 1.1;
repaint();
}
//Zoom out
if (e.getWheelRotation() > 0) {
zoomFactor /= 1.1;
repaint();
}
}
如果你还想使用拖动功能并想根据鼠标的位置进行缩放,你可以使用下面的类,它在构造函数中获取BufferedImage作为参数,以便在屏幕上显示内容。 / p>
我还在GitHub上传了一个名为Zoomable-Java-Panel的项目,其中有一个我上面展示的功能示例,您可以测试它,看看它如何在项目中实现。
package zoomable.panel;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MouseInfo;
import java.awt.Point;
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.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
/**
*
* @author Thanasis1101
* @version 1.0
*/
public class MainPanel extends JPanel implements MouseWheelListener, MouseListener, MouseMotionListener {
private final BufferedImage image;
private double zoomFactor = 1;
private double prevZoomFactor = 1;
private boolean zoomer;
private boolean dragger;
private boolean released;
private double xOffset = 0;
private double yOffset = 0;
private int xDiff;
private int yDiff;
private Point startPoint;
public MainPanel(BufferedImage image) {
this.image = image;
initComponent();
}
private void initComponent() {
addMouseWheelListener(this);
addMouseMotionListener(this);
addMouseListener(this);
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
if (zoomer) {
AffineTransform at = new AffineTransform();
double xRel = MouseInfo.getPointerInfo().getLocation().getX() - getLocationOnScreen().getX();
double yRel = MouseInfo.getPointerInfo().getLocation().getY() - getLocationOnScreen().getY();
double zoomDiv = zoomFactor / prevZoomFactor;
xOffset = (zoomDiv) * (xOffset) + (1 - zoomDiv) * xRel;
yOffset = (zoomDiv) * (yOffset) + (1 - zoomDiv) * yRel;
at.translate(xOffset, yOffset);
at.scale(zoomFactor, zoomFactor);
prevZoomFactor = zoomFactor;
g2.transform(at);
zoomer = false;
}
if (dragger) {
AffineTransform at = new AffineTransform();
at.translate(xOffset + xDiff, yOffset + yDiff);
at.scale(zoomFactor, zoomFactor);
g2.transform(at);
if (released) {
xOffset += xDiff;
yOffset += yDiff;
dragger = false;
}
}
// All drawings go here
g2.drawImage(image, 0, 0, this);
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
zoomer = true;
//Zoom in
if (e.getWheelRotation() < 0) {
zoomFactor *= 1.1;
repaint();
}
//Zoom out
if (e.getWheelRotation() > 0) {
zoomFactor /= 1.1;
repaint();
}
}
@Override
public void mouseDragged(MouseEvent e) {
Point curPoint = e.getLocationOnScreen();
xDiff = curPoint.x - startPoint.x;
yDiff = curPoint.y - startPoint.y;
dragger = true;
repaint();
}
@Override
public void mouseMoved(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
released = false;
startPoint = MouseInfo.getPointerInfo().getLocation();
}
@Override
public void mouseReleased(MouseEvent e) {
released = true;
repaint();
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}