2010-01-14 72 views
2

我在這裏的代碼是使用MouseAdapter來偵聽用戶在他們想要放大的圖像區域周圍「繪製」一個框,並計算出框中的圖像。然後將圖像調整爲計算出的比例。這部分工作。JScrollPane setViewPosition「縮放」後

我遇到的問題是使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(); 
    } 
} 

}

這是它調整其大小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)); 
} 
} 
+0

請出示在這裏我們可以找到ImageComponent和ResizeViewport。 – lins314159 2010-01-14 23:04:22

+0

你可以發佈一些簡單的代碼來顯示如何使用它?也許我做錯了,但我不斷收到一個ClassCastException,因爲DynamicZoom試圖將我點擊的JLabel轉換爲JScrollPane。 – lins314159 2010-01-21 01:20:31

回答

3

事實證明,用於計算位置的數學或我設計代碼的方式沒有任何問題。問題在於,當計算位置時,ImageComponent仍然在另一個線程中繪製;因此返回getWidth()和getHeight()方法的「false」值。

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

這使得繪畫試圖計算圖像的大小和設置在JScrollPane的位置之前完成:我用下面的代碼解決了這個問題。問題解決了。我仍然想感謝那些花時間至少回顧這個問題的人們。

-1

,我遇到的問題是使 JScrollPane的觀點出現,就好像它 仍然是在圖像後相同的頂部左側位置 已調整。

對不起,我不確定你在問什麼。如果你澄清一點,我可能會給出答案。

+0

等一下,這應該是一個評論,而不是一個答案? – 2010-02-01 20:34:09

+0

對不起模糊或混亂,但我有一個jscrollpane中的圖像正在放大或縮小,我需要根據轉換的比率將jscrollpane的位置設置到新的位置......如果這使得更好的意義。 – Daniel 2010-02-04 18:24:47

1

我有一個類似的問題,但有時面板在調整大小後第一次出現錯誤,經過數小時試圖找到解決方法,我找到了解決方案!

在滾動窗格中調整面板大小後,最好是通過設置爲空來銷燬視口,然後將面板添加回到將重新創建新視口並且一切正常的滾動窗格!

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

/安德斯