如果我正确理解问题,那么您的方法会有些落后。 与其让ImageNavigator告诉ZoomedImage绘制哪个子图像,不如让ZoomedImage在绘制时询问ImageNavigator(通过重写ZoomedImage的paintComponent方法)。 当ZonedImage进行绘画时,它将完全摆在屏幕上,并且知道其大小,因此不会有问题。
另外,让ZoomedImage维护整个图像和显示区域的坐标,以便它将具有绘制自身所需的完整信息。 当用户与ImageNavigator交互时,它可以调用ZoomedImage来设置显示区域的坐标。
为了更加具体,这是第二种方法的一个小例子。 为简便起见,我没有创建“ ZoomedImage”类,而是使用了包含图像JLabel的JScrollPane,但它确实可以完成工作。 右侧是ImageNavigator,它调用“ ZoomedImage组件”(实际上是滚动窗格的视口)以获取并设置显示区域的坐标。 它绘制一个红色矩形突出显示该部分。 您可以使用滚动条,导航器或调整窗口大小来调整显示的区域。 没什么太复杂了,但希望它包含一些有用的见解:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
class ImageNavigatorExample {
public static void main(String[] args) throws Throwable {
File imageFile = new File( // change file to one you have!
"Shallow Waters in the South Pacific.jpg");
BufferedImage image = javax.imageio.ImageIO.read(imageFile);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JScrollPane imageScroller = new JScrollPane(new JLabel(new ImageIcon(image)));
imageScroller.setPreferredSize(new Dimension(640, 480));
frame.add(imageScroller);
frame.add(new ImageNavigator(image, imageScroller.getViewport()), BorderLayout.EAST);
frame.pack();
frame.setVisible(true);
}
private static class ImageNavigator extends JPanel {
private final BufferedImage image;
private final JViewport viewport;
public ImageNavigator(BufferedImage image, final JViewport viewport) {
this.image = image;
this.viewport = viewport;
viewport.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
repaint();
}
});
MouseAdapter mouseAdapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int xImage = Math.round(e.getX() / scale());
int yImage = Math.round(e.getY() / scale());
viewport.setViewPosition(new Point(
Math.max(0, xImage - viewport.getExtentSize().width / 2),
Math.max(0, yImage - viewport.getExtentSize().height / 2)));
}
@Override
public void mouseDragged(MouseEvent e) {
mousePressed(e);
}
};
this.addMouseListener(mouseAdapter);
this.addMouseMotionListener(mouseAdapter);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(150, image.getWidth() * 150 / image.getHeight());
}
private float scale() {
return (float)this.getWidth() / image.getWidth();
}
@Override
public void paintComponent(Graphics g1) {
super.paintComponent(g1);
Graphics2D g = (Graphics2D)g1.create();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.scale(scale(), scale());
g.drawImage(image, 0, 0, null);
g.setColor(Color.red);
g.setStroke(new BasicStroke(scale()));
g.draw(viewport.getViewRect());
}
}
}
看起来像什么: