JScrollPane setViewPosition After "Zoom"

The code I have uses the MouseAdapter to listen to the user, to "draw" a field around the area of ​​the image that they would like to enlarge, and calculate the ratio of the window to the image. Then it resizes the image to the calculated one. This part works.

The problem I am facing is that the JScrollPane view looks as if it is still in the same upper left position after resizing the image. I tried several methods that seemed to come close to the result I want, but not quite.

This is a listener who finds the scaling factor and sets the position:

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(); } } 

}

This is an ImageComponent that resizes and displays the image:

 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 causes the viewport to display the entire ImageComponent when it is scaled, because otherwise it will crop the image to the size that was previously:

 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)); } } 
+2
java image zoom jscrollpane
source share
3 answers

Turns out there is nothing wrong with the math used to calculate the position or the way I developed the code. The problem was that ImageComponent was still drawing in a different topic when the position was calculated; therefore, we return false values ​​for the getWidth () and getHeight () methods. I solved the problem using the following code:

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

This allows you to finish drawing before trying to calculate the size of the image and set the position in JScrollPane. The problem is solved. Anyway, I would like to thank the people who took the time to at least consider this problem.

+3
source share

I had a similar problem, but sometimes the panel was not written correctly for the first time after resizing, after several hours of trying to find a workaround, I found a solution!

After resizing the panel in scrollpane, it is best to destroy the viewport by setting it to null and then adding the panel back to scrollpane, which recreates the new viewport and everything will work!

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

/ Anders

+1
source share

The problem I am facing is that the JScrollPane view looks as if it is still in the same upper left position after resizing the image.

Sorry, I'm not sure what you are asking. Perhaps I can give an answer if you clarify a little.

-one
source share

All Articles