Zoom point invariant JScrollPan sauf pour le premier Zoom
Bonjour à tous,
Je suis en train de développer une carte zoomable avec le point de la souris qui reste invariant. J'obtient des résultats corrects excepté pour le premier zoom. Mon calcul a été vérifié plusieurs fois et au moment de mettre les valeurs de setViewPosition, elles sont bonnes, mais cette fameuse viewPosition est fixé a 15, 15 dans la suite du programme et je n'arrive pas à trouver ou cela a lieu, car ensuite le zoom marche parfaitement.
Graphiquement cela se traduit par le fait que vue est mauvaise pour le premier zoom et ensuite pour les prochains zooms le point de la souris est bien invariant.
Mon code à été simplifié pour cet exemple
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
public class MainClass {
public static void main(String[] args) {
Controler controler = new Controler();
View view = new View(controler);
controler.setViewWeak(view);
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
public class View extends JFrame {
private final static int WIDTH = 1200; //1200
private final static int HEIGHT = 700; //770
private Controler controler;
private ResizableImage imageMap; // inherite from JPanel
private JScrollPane scrollPane; // without attribute like private, protected, public : means frendly
//private JPanel pane; // this panel contains the JscrollPane
public ResizableImage getImageMap() {
return imageMap;
}
public void setImageMap(ResizableImage imageMap) {
this.imageMap = imageMap;
}
public JScrollPane getScrollPane() {
return scrollPane;
}
public void setScrollPane(JScrollPane scrollPane) {
this.scrollPane = scrollPane;
}
public View(Controler controler) {
super("Projet"); // Appel a la fonction mere (JFrame) et donc son constructeur qui prend le nom de la fenetre
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // pour pouvoir rendre le bouton de fermeture reactif
this.controler = controler;
// Permet de centrer la fenetre au milieu de l'ecran
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
this.setBounds( (int) ( dim.getWidth() - WIDTH ) / 2, (int) ( dim.getHeight() - HEIGHT ) / 2, WIDTH, HEIGHT);
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.setResizable(false);
this.getContentPane().setLayout(new FlowLayout());
this.imageMap = new ResizableImage(new File("./carte.gif"));
this.imageMap.addMouseWheelListener(this.controler);
this.imageMap.addMouseMotionListener(this.controler);
this.imageMap.addMouseListener(this.controler);
this.imageMap.setPreferredSize(new Dimension(934,600));//934,654
scrollPane = new JScrollPane(imageMap);
this.getContentPane().add(scrollPane);
this.pack();
this.setVisible(true);
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
public class Controler implements ActionListener, MouseWheelListener, MouseInputListener {
private WeakReference<View> viewWeak;
public void setViewWeak(View view) {
this.viewWeak = new WeakReference<View>(view);
}
public WeakReference<View> getViewWeak() {
return viewWeak;
}
public void actionPerformed(ActionEvent e) {
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL ) {
int i = e.getWheelRotation();
if( i > 0 ){
int lX = e.getX();
int lY = e.getY();
System.out.println("on recupere la vue actuelle");
Point VxVy = this.viewWeak.get().getScrollPane().getViewport().getViewPosition();
int x = (int) (lX - VxVy.getX());
int y = (int) (lY - VxVy.getY());
if( this.viewWeak.get().getImageMap().isPossibleToZoomIn(1.1)){
this.viewWeak.get().getImageMap().setZoom(1.1);
int lXp = (int) (lX * 1.1);
int lYp = (int) (lY * 1.1);
int VxP = (int) (x*(1.1 - 1) + 1.1 * VxVy.getX());
int VyP = (int) (y*(1.1 - 1) + 1.1 * VxVy.getY());
//System.out.println("ViewPosition : "+this.viewWeak.get().getScrollPane().getViewport().getViewPosition());
System.out.println("on applique la nouvelle vue");
this.viewWeak.get().getScrollPane().getViewport().setViewPosition(new Point(VxP, VyP));
}
}
}
System.out.println("ViewPosition fin methode : "+this.viewWeak.get().getScrollPane().getViewport().getViewPosition());
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
public class ResizableImage extends JPanel {
private BufferedImage image;
private final int minWidth = 934;
private final int minHeight = 654;
private final int maxWidth = 9807;
private final int maxHeight = 6867;
private double zoomX = maxWidth / minWidth; // zoom of the view considering the size of the picture
private double zoomY = maxHeight / minHeight;
public double getZoomX() {
return zoomX;
}
public void setZoomX(double zoom){
this.zoomX = zoom;
}
public double getZoomY() {
return zoomY;
}
public void setZoomY(double zoom){
this.zoomY = zoom;
}
public ResizableImage(File file){
try {
this.image = ImageIO.read(file);
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("capture exception");
e.printStackTrace();
}
}
public void paintComponent(Graphics g){
Graphics2D g2D = (Graphics2D) g;
Dimension dim = getPreferredSize();
g2D.drawImage(image, 0, 0, dim.width, dim.height, this);
}
public boolean isPossibleToZoomOut(double zoom){
int w = (int) (zoom * this.getSize().getWidth());
int h = (int) (zoom * this.getSize().getHeight());
if( zoom >= 1 || w > this.minWidth || h > this.minHeight)
return true;
else
return false;
}
public boolean isPossibleToZoomIn(double zoom){
int w = (int) (zoom * this.getSize().getWidth());
int h = (int) (zoom * this.getSize().getHeight());
if( w >= this.maxWidth || h >= this.maxHeight){
return false;
}
else
return true;
}
public void setZoom(double zoom) {
if( zoom < 1){
if( this.isPossibleToZoomOut(zoom) ){
int w = (int) (zoom * this.getSize().getWidth());
int h = (int) (zoom * this.getSize().getHeight());
setPreferredSize(new Dimension(w, h));
revalidate();
repaint();
}
else{
if( this.getPreferredSize() != new Dimension(this.minWidth, this.minHeight)){
setPreferredSize(new Dimension(this.minWidth, this.minHeight));
revalidate();
repaint();
}
}
}
else{
if( this.isPossibleToZoomIn(zoom) ){
int w = (int) (zoom * this.getSize().getWidth());
int h = (int) (zoom * this.getSize().getHeight());
setPreferredSize(new Dimension(w, h));
revalidate();
repaint();
}
}
}
public int getMinWidth() {
return minWidth;
}
public int getMaxWidth() {
return maxWidth;
}
} |