Estoy intentando implementar el zoom sensible a la posición dentro de un JScrollPane
. El JScrollPane
contiene un componente con un paint
personalizado que se dibujará dentro de cualquier espacio que esté asignado, por lo que el zoom es tan fácil como usar un MouseWheelListener
que redimensiona el componente interno según sea necesario.¿Cómo se implementa el zoom sensible a la posición dentro de un JScrollPane?
Pero también quiero acercarme (o alejarme) de un punto para mantener ese punto lo más central posible dentro de la vista ampliada (o salida) resultante (esto es a lo que me refiero como 'sensible a la posición' zoom), similar a cómo funciona el zoom en google maps. Estoy seguro de que esto ya se ha hecho muchas veces antes: ¿alguien sabe la forma "correcta" de hacerlo en Java Swing ?. ¿Sería mejor jugar con las transformaciones Graphic2D
en lugar de usar JScrollPanes
?
Código de la muestra de la siguiente manera:
package test;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
public class FPanel extends javax.swing.JPanel {
private Dimension preferredSize = new Dimension(400, 400);
private Rectangle2D[] rects = new Rectangle2D[50];
public static void main(String[] args) {
JFrame jf = new JFrame("test");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setSize(400, 400);
jf.add(new JScrollPane(new FPanel()));
jf.setVisible(true);
}
public FPanel() {
// generate rectangles with pseudo-random coords
for (int i=0; i<rects.length; i++) {
rects[i] = new Rectangle2D.Double(
Math.random()*.8, Math.random()*.8,
Math.random()*.2, Math.random()*.2);
}
// mouse listener to detect scrollwheel events
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
updatePreferredSize(e.getWheelRotation(), e.getPoint());
}
});
}
private void updatePreferredSize(int n, Point p) {
double d = (double) n * 1.08;
d = (n > 0) ? 1/d : -d;
int w = (int) (getWidth() * d);
int h = (int) (getHeight() * d);
preferredSize.setSize(w, h);
getParent().doLayout();
// Question: how do I keep 'p' centered in the resulting view?
}
public Dimension getPreferredSize() {
return preferredSize;
}
private Rectangle2D r = new Rectangle2D.Float();
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.red);
int w = getWidth();
int h = getHeight();
for (Rectangle2D rect : rects) {
r.setRect(rect.getX() * w, rect.getY() * h,
rect.getWidth() * w, rect.getHeight() * h);
((Graphics2D)g).draw(r);
}
}
}
Agregado de recompensas para ver si puedo conseguir una respuesta completa (lo ideal es: el fragmento de código que, cuando se añade anterior, responde a la pregunta). – tucuxi