如何在具有null Layout和SubPanels的JPanel中实现缩放

时间:2014-09-19 09:43:06

标签: java jpanel zoom jscrollpane null-layout-manager

我用JScrollPane构建了一个程序,这个滚动窗格包含另一个带有null Layout的JPanel,这个面板包含了一些其他JPanel [我将它们命名为子面板](带有一些绘制的东西和JLabel) 那些子面板使用setBounds(int,int,int,int)方法定位在面板中(我不想改变它)

在寻找缩放的好解决方案后,我找到了两个选项 - 缩放paint / paintComponent方法(很糟糕,因为绘制的东西被更改但不是x,y轴的比例,而不是那些子面板的高度和高度 - >我的mouselisteners不起作用(在错误的地方) ) - 使用JScrollPane的视口缩放(根本不起作用(我在谷歌上找到的等等)。)

所以我正在寻找放大和缩小JPanel的好方法

这里有一些代码可以想象我的意思

 import java.awt.Color;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Point;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
 import java.awt.geom.AffineTransform;

 import javax.swing.JFrame;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;


 public class MyAppFrame extends JFrame {

private JScrollPane scroll;
private JPanel nullLayoutPanel;
private JPanel subPanel;
private double zoomFactor;
private double lastScale;
private static Point pressed;

public MyAppFrame(){
    setSize(200, 200);
    setLocation(50, 50);
    zoomFactor = 1.0;
    lastScale = 1.0;

    nullLayoutPanel = new JPanel(){


        //when you try it with the paint method you'll see my problem
        //move the rect by dragging it around then
        //scroll out or in and try to move the rect
        //you'll see that the position of the logical rect doesn't fit with the painted one
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            //g2d.translate(nullLayoutPanel.getWidth()/2, nullLayoutPanel.getHeight()/2);
            g2d.scale(zoomFactor, zoomFactor);
            //g2d.translate(-nullLayoutPanel.getWidth()/2, -nullLayoutPanel.getHeight()/2);
            //super.paint(g2d);
            g2d.dispose();
        }

        @Override
        public Dimension getPreferredSize(){
            return new Dimension((int)(nullLayoutPanel.getWidth()*zoomFactor), (int)(nullLayoutPanel.getHeight()*zoomFactor));
        }

    };
    nullLayoutPanel.setPreferredSize(new Dimension(400,400));
    nullLayoutPanel.setLayout(null);
    nullLayoutPanel.addMouseWheelListener(new MouseWheelListener() {

        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL){
                if((.1 * e.getWheelRotation()) > 0 && zoomFactor < 2.0){
                    zoomFactor += (.1 * e.getWheelRotation());
                } else if((.1 * e.getWheelRotation()) < 0 && zoomFactor > 0.1){
                    zoomFactor += (.1 * e.getWheelRotation());
                }
                zoomFactor = Math.round(zoomFactor*10.0)/10.0;
                zoom(e.getPoint());
            }
        }
    });


    scroll = new JScrollPane(nullLayoutPanel);
    scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    getContentPane().add(scroll);

    subPanel = new JPanel(){
        @Override
        public void paint(Graphics g){
            g.setColor(Color.BLUE);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());
        }
    };

    subPanel.addMouseListener(new MouseListener() {

        @Override
        public void mouseReleased(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mousePressed(MouseEvent e) {
            pressed = e.getPoint();
        }

        @Override
        public void mouseExited(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseEntered(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseClicked(MouseEvent e) {
            // TODO Auto-generated method stub

        }
    });
    subPanel.addMouseMotionListener(new MouseMotionListener() {

        @Override
        public void mouseMoved(MouseEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public void mouseDragged(MouseEvent e) {
            Point pPoint;
            pPoint = subPanel.getLocation();
            int x = (int)(pPoint.x - pressed.getX()+e.getX());
            int y = (int)(pPoint.y - pressed.getY()+e.getY());
            if(x>0&&y>0)
                subPanel.setLocation(x,y);
            repaint();
        }
    });

    subPanel.setBounds(10, 10, 10, 10);
    nullLayoutPanel.add(subPanel);


    setVisible(true);

}

public void alignViewPort(Point mousePosition) {
    // if the scale didn't change there is nothing we should do
    if (zoomFactor != lastScale) {
        // compute the factor by that the image zoom has changed
        double scaleChange = zoomFactor / lastScale;

        // compute the scaled mouse position
        Point scaledMousePosition = new Point(
                (int)Math.round(mousePosition.x * scaleChange),
                (int)Math.round(mousePosition.y * scaleChange)
        );

        // retrieve the current viewport position
        Point viewportPosition = scroll.getViewport().getViewPosition();

        // compute the new viewport position
        Point newViewportPosition = new Point(
                viewportPosition.x + scaledMousePosition.x - mousePosition.x,
                viewportPosition.y + scaledMousePosition.y - mousePosition.y
        );

        // update the viewport position
        // IMPORTANT: This call doesn't always update the viewport position. If the call is made twice
        // it works correctly. However the screen still "flickers".
        scroll.getViewport().setViewPosition(newViewportPosition);

        // debug
        if (!newViewportPosition.equals(scroll.getViewport().getViewPosition())) {
            System.out.println("Error: " + newViewportPosition + " != " + scroll.getViewport().getViewPosition());
        }

        // remember the last scale
        lastScale = zoomFactor;
    }
}

public void zoom(Point p){
    alignViewPort(p);
    nullLayoutPanel.revalidate();
    scroll.repaint();
}

/**
 * @param args
 */
public static void main(String[] args) {
    new MyAppFrame();
}

 }

我希望你理解我的问题......

编辑:更改了一些代码(视口事物)

0 个答案:

没有答案