“缩放”后的JScrollPane setViewPosition

我这里的代码是使用MouseAdapter来监听用户在他们想要放大的图像区域周围“绘制”一个框,并计算框与图像的比例。 然后它将图像调整为计算的比例。 这部分有效。

我遇到的问题是,在调整图像大小后,JScrollPane视图看起来好像仍处于同一个左上角位置。 我已经尝试了几种方法似乎已经接近我想要的结果但不完全正确。

这是侦听器,它找到比例并设置位置:

import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.Graphics; import java.awt.Point; import javax.swing.JScrollPane; import javax.swing.JViewport; import javax.swing.JComponent; public class DynamicZoom extends MouseAdapter { private Point start; private Point end; private double zoom = 1.0; private JScrollPane pane; private JViewport port; public void mousePressed(MouseEvent e) { if(e.getButton() == MouseEvent.BUTTON1) { this.pane = (JScrollPane)e.getSource(); this.port = pane.getViewport(); start = e.getPoint(); } } public void mouseReleased(MouseEvent e) { if(this.pane != null) { Point curr = this.port.getViewPosition(); end = e.getPoint(); ImageComponent canvas = (ImageComponent)this.port.getView(); zoom = canvas.getScale(); double factor = 0.0; double selectedWidth = Math.abs(end.getX() - start.getX()); double selectedHeight = Math.abs(end.getY() - start.getY()); if(selectedWidth > selectedHeight) factor = this.port.getWidth() / selectedWidth; else factor = this.port.getHeight() / selectedHeight; zoom *= factor; int x = (int)((start.x+curr.x)*zoom); int y = (int)((start.y+curr.y)*zoom); Point point = new Point(x, y); ((ImageComponent)(this.port.getView())).setScale(zoom); ResizeViewport.resize(pane); this.port.setViewPosition(point); } } public void mouseDragged(MouseEvent e) { if(this.pane != null) { Graphics g = this.port.getGraphics(); int width = this.start.x - e.getX(); int height = this.start.y - e.getY(); int w = Math.abs( width ); int h = Math.abs( height ); int x = width < 0 ? this.start.x : e.getX(); int y = height < 0 ? this.start.y : e.getY(); g.drawRect(x, y, w, h); this.port.repaint(); } } 

}

这是它resize并显示图像的ImageComponent:

 import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import javax.swing.JComponent; public class ImageComponent extends JComponent { private static final long serialVersionUID = 1975488835382044371L; private BufferedImage img = null; private double scale = 0.0; public ImageComponent() {} public ImageComponent(BufferedImage img) { this.displayPage(img); } @Override public void paint(Graphics g) { Graphics2D g2 = ((Graphics2D)g); if(this.img != null) { int width = (int)(this.img.getWidth() * this.scale); int height = (int)(this.img.getHeight() * this.scale); this.setPreferredSize(new Dimension(width, height)); g2.drawImage(this.img, 0, 0, width, height, null, null); g2.dispose(); } } public void displayPage(BufferedImage pic) { if(img != null) { this.img = pic; } } public BufferedImage getPage() { return this.img; } public void setScale(double ratio) { if(ratio > .04) { this.scale = ratio; this.repaint(); } } public double getScale() { return this.scale; } } 

ResizeViewport强制视口在放大时显示整个ImageComponent,否则它将以之前的大小剪切图像:

 import java.awt.Dimension; import javax.swing.JScrollPane; public class ResizeViewport { public static void resize(JScrollPane scroll) { int vw = scroll.getWidth()-scroll.getVerticalScrollBar().getWidth(); int vh = scroll.getHeight()-scroll.getHorizontalScrollBar().getHeight(); scroll.getViewport().setViewSize(new Dimension(vw, vh)); } } 

事实certificate,用于计算位置的数学或我设计代码的方式没有任何问题。 问题是ImageComponent在计算位置时仍在另一个Thread中绘制; 因此返回getWidth()和getHeight()方法的“false”值。 我使用以下代码解决了这个问题:

 EventQueue.invokeLater(new Runnable() { public void run() { port.setViewPosition(new Point(x,y)); } }); 

这允许在尝试计算图像的大小和在JScrollPane中设置位置之前完成绘画。 问题解决了。 我还是要感谢花时间至少审查这个问题的人们。

我有一个类似的问题,但有时面板在resize后第一次被涂错了,经过几个小时试图找到解决方法后我找到了解决方案!

在滚动窗格中调整面板大小后,最好通过设置为null来破坏视口,然后将面板添加回滚动窗格,这将重新创建一个新视口,一切正常!

 // Old viewport has to be replaced scrollPane.setViewport(null); scrollPane.setViewportView(zoomablePanel); 

/安德斯

我遇到的问题是,在调整图像大小后,JScrollPane视图看起来好像仍处于同一个左上角位置。

对不起,我不确定你在问什么。 如果你澄清一下,我或许可以给出答案。