Java 如何使此面板向面板中间缩放?
我有一个JPanel,代码在这里。当我用鼠标滚轮滚动时,我希望面板朝面板中心放大。当前,每当我使用鼠标滚轮放大/缩小时,图像左上角的位置都保持不变。我很难找到正确的算法 为了放大图片,代码使用仿射变换对象,该对象根据双值缩放图像,该双值根据鼠标滚轮的移动而增减 更为复杂的是,还可以在面板上单击和拖动图像。如果单击并拖动,缩放仍必须放大面板中心的内容,而不必放大实际图像的中心 同样,缩放应该相对于当前可见区域的中心点进行。也就是说,随着缩放的发生,视图中心的点应该保持固定 这是代码(它是可执行的):Java 如何使此面板向面板中间缩放?,java,swing,Java,Swing,我有一个JPanel,代码在这里。当我用鼠标滚轮滚动时,我希望面板朝面板中心放大。当前,每当我使用鼠标滚轮放大/缩小时,图像左上角的位置都保持不变。我很难找到正确的算法 为了放大图片,代码使用仿射变换对象,该对象根据双值缩放图像,该双值根据鼠标滚轮的移动而增减 更为复杂的是,还可以在面板上单击和拖动图像。如果单击并拖动,缩放仍必须放大面板中心的内容,而不必放大实际图像的中心 同样,缩放应该相对于当前可见区域的中心点进行。也就是说,随着缩放的发生,视图中心的点应该保持固定 这是代码(它是可执行的)
packageclientgui;
导入java.awt.*;
导入javax.imageio.imageio;
导入javax.swing.*;
导入java.awt.event.*;
导入java.awt.geom.*;
导入java.awt.image.buffereImage;
导入java.net.URL;
导入javax.swing.border.TitledBorder;
公共类MoveImageExample扩展了JFrame{
展示帆布;
public MoveImageExample()引发异常{
超级();
Container=getContentPane();
画布=新的ShowCanvas(
"http://cdn.smosh.com/sites/default/files/bloguploads/funny-iphone-5-bruce-lee.jpg");
container.setPreferredSize(新维度(canvas.getWidth(),canvas
.getHeight());
System.out.println(“width=“+canvas.getWidth()+”height=”
+canvas.getHeight());
容器。添加(画布);
包装();
setVisible(真);
}
公共静态void main(字符串arg[])引发异常{
新的MoveImageExample();
}
}
@抑制警告(“串行”)
类ShowCanvas扩展了JPanel{
int imageX=0,imageY=0;
int lastMouseX=0,lastMouseY=0;
int centerX=225;
int centerY=225;
int canvasWidth=450;
int画布高度=450;
双尺度因子=1.0;
布尔值firstMouseDrag=true;
缓冲图像;
公共ShowCanvas(字符串imagePath)引发异常{
挫折地面(颜色:白色);
MouseMotionHandler mouseHandler=新的MouseMotionHandler();
addMouseMotionListener(mouseHandler);
addMouseListener(mouseHandler);
添加MouseWheelListener(mouseHandler);
URL URL=新URL(图像路径);
Image rawImage=ImageIO.read(url);
image=新的buffereImage(rawImage.getWidth(this),
rawmimage.getHeight(this),BufferedImage.TYPE_INT_ARGB);
设置大小(image.getWidth(),image.getHeight());
Graphics2D g2=image.createGraphics();
g2.drawImage(rawImage、imageX、imageY、this);
}
公共组件(图形g){
超级组件(g);
Graphics2D g2D=(Graphics2D)g;
g2D.setColor(Color.gray);
g、 fillRect(0,0,image.getWidth(),image.getHeight());
仿射变换器=新仿射变换器();
//向后平移图像(使用新的比例因子)
scale(scaleFactor,scaleFactor);//在x和y上按2x缩放
//斧头。
translate(imageX/scaleFactor,imageY/scaleFactor);
g2D.drawImage(图像、变压器、此);
}
类MouseMotionHandler扩展了MouseMotionAdapter实现
鼠标听器,鼠标轮听器{
公共无效鼠标按下(MouseEvent e){
lastMouseX=e.getX();
lastMouseY=e.getY();
}
公共无效鼠标标记(鼠标事件e){
int xDiff=e.getX()-lastMouseX;
int yDiff=e.getY()-lastMouseY;
imageX=imageX+xDiff;
imageY=imageY+yDiff;
lastMouseX=e.getX();
lastMouseY=e.getY();
重新油漆();
}
已移动公共无效鼠标滚轮(鼠标滚轮事件e){
int槽口=e.getWheelRotation();
scaleFactor=scaleFactor+槽口/10.0;
如果(比例因子<0.5){
scaleFactor=0.5;
}否则如果(缩放因子>3.0){
scaleFactor=3.0;
}
重新油漆();
}
公共无效MouseEvent(MouseEvent e){
}
公共无效鼠标事件(鼠标事件e){
}
公共无效mouseExited(MouseEvent e){
}
公共无效mouseClicked(MouseEvent e){
}
}
}
因此,基本思想是,当您更改比例时,而不是允许从宽度/高度中添加/减去整个更改,您需要在位置和大小之间进行划分
public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation();
// Get the current/old size...
double oldWidth = image.getWidth() * scaleFactor;
double oldHeight = image.getHeight() * scaleFactor;
scaleFactor = scaleFactor + notches / 10.0;
if (scaleFactor < 0.5) {
scaleFactor = 0.5;
} else if (scaleFactor > 3.0) {
scaleFactor = 3.0;
}
// Get the new size
double newWidth = image.getWidth() * scaleFactor;
double newHeight = image.getHeight() * scaleFactor;
// Calculate the difference (and divide it by 2)
double difWidth = (oldWidth - newWidth) / 2;
double difHeight = (oldHeight - newHeight) / 2;
// Add it to the image position...
imageX += difWidth;
imageY += difHeight;
revalidate();
repaint();
}
基本思想是,当您可以缩放尺寸时,您也需要更改面板的位置。您确切地更改面板的位置是什么意思?比如,当图像缩放时,图像本身并没有真正移动,但面板在移动?对不起,这应该是“更改图像位置”-我原本以为您也在更改面板的大小…:这是一个非常好的解决方案。。。这不是我真正需要的。我需要它放大面板的中心,而不一定是图像。我真的不知道怎么解释,但是如果,比如说,面板的左上角在面板的中心点,面板需要放大那一部分。是的,我刚才被那一部分绊倒了。我不太确定我是否理解它的工作原理请允许我澄清一下。。。应相对于当前可见区域的中心点进行缩放。也就是说,当缩放发生时,vi中心的点
public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation();
// Get the current/old size...
double oldWidth = image.getWidth() * scaleFactor;
double oldHeight = image.getHeight() * scaleFactor;
scaleFactor = scaleFactor + notches / 10.0;
if (scaleFactor < 0.5) {
scaleFactor = 0.5;
} else if (scaleFactor > 3.0) {
scaleFactor = 3.0;
}
// Get the new size
double newWidth = image.getWidth() * scaleFactor;
double newHeight = image.getHeight() * scaleFactor;
// Calculate the difference (and divide it by 2)
double difWidth = (oldWidth - newWidth) / 2;
double difHeight = (oldHeight - newHeight) / 2;
// Add it to the image position...
imageX += difWidth;
imageY += difHeight;
revalidate();
repaint();
}
import java.awt.*;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.net.URL;
public class MoveImageExample extends JFrame {
ShowCanvas canvas;
public MoveImageExample() throws Exception {
super();
Container container = getContentPane();
canvas = new ShowCanvas(
"http://cdn.smosh.com/sites/default/files/bloguploads/funny-iphone-5-bruce-lee.jpg");
container.add(canvas);
pack();
setVisible(true);
}
public static void main(String arg[]) throws Exception {
new MoveImageExample();
}
}
@SuppressWarnings("serial")
final class ShowCanvas extends JPanel {
int imageX = 0, imageY = 0;
int lastMouseX = 0, lastMouseY = 0;
int centerX = 225;
int centerY = 225;
int canvasWidth = 450;
int canvasHeight = 450;
double scaleFactor = 1.0;
boolean firstMouseDrag = true;
BufferedImage image;
private BufferedImage scaled;
public ShowCanvas(String imagePath) throws Exception {
setBackground(Color.white);
MouseMotionHandler mouseHandler = new MouseMotionHandler();
addMouseMotionListener(mouseHandler);
addMouseListener(mouseHandler);
addMouseWheelListener(mouseHandler);
URL url = new URL(imagePath);
Image rawImage = ImageIO.read(url);
image = new BufferedImage(rawImage.getWidth(this),
rawImage.getHeight(this), BufferedImage.TYPE_INT_ARGB);
setSize(image.getWidth(), image.getHeight());
Graphics2D g2 = image.createGraphics();
g2.drawImage(rawImage, imageX, imageY, this);
}
@Override
public Dimension getPreferredSize() {
return new Dimension((int) (image.getWidth()), (int) (image.getHeight()));
}
protected BufferedImage getScaledInstance() {
if (scaled == null) {
int width = (int) (image.getWidth() * scaleFactor);
int height = (int) (image.getHeight() * scaleFactor);
scaled = new BufferedImage(width, height, image.getType());
Graphics2D g2d = scaled.createGraphics();
AffineTransform transformer = new AffineTransform();
transformer.scale(scaleFactor, scaleFactor); // scale by 2x on x and y
g2d.setTransform(transformer);
g2d.drawImage(image, 0, 0, this);
g2d.dispose();
}
return scaled;
}
public Dimension getVirtualSize() {
return new Dimension(
(int)(getWidth() * scaleFactor),
(int)(getHeight() * scaleFactor));
}
public Point getVirtualPoint(int x, int y) {
return new Point(
(int)(x * scaleFactor),
(int)(y * scaleFactor));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension vitualSize = getVirtualSize();
int xOffset = (getWidth() - vitualSize.width) / 2;
int yOffset = (getHeight() - vitualSize.height) / 2;
Graphics2D g2D = (Graphics2D) g.create();
g2D.setColor(Color.gray);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g2D.setColor(Color.GREEN);
g2D.drawRect(xOffset, yOffset, vitualSize.width, vitualSize.height);
g2D.setColor(Color.RED);
g2D.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
g2D.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
Point virtualPoint = getVirtualPoint(imageX, imageY);
System.out.println(virtualPoint);
g2D.drawImage(getScaledInstance(), virtualPoint.x + xOffset, virtualPoint.y + yOffset, this);
g2D.dispose();
}
class MouseMotionHandler extends MouseMotionAdapter implements
MouseListener, MouseWheelListener {
public void mousePressed(MouseEvent e) {
lastMouseX = e.getX();
lastMouseY = e.getY();
}
public void mouseDragged(MouseEvent e) {
int xDiff = e.getX() - lastMouseX;
int yDiff = e.getY() - lastMouseY;
imageX = imageX + xDiff;
imageY = imageY + yDiff;
lastMouseX = e.getX();
lastMouseY = e.getY();
repaint();
}
public void mouseWheelMoved(MouseWheelEvent e) {
scaled = null;
int notches = e.getWheelRotation();
scaleFactor = scaleFactor + notches / 10.0;
if (scaleFactor < 0.5) {
scaleFactor = 0.5;
} else if (scaleFactor > 3.0) {
scaleFactor = 3.0;
}
repaint();
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
}
}
}