简体   繁体   中英

Zooming panel in and out but scrollbar don't work

I have created a panel with zoom in and out function but the scrollbar don't work, I mean when I zoom in I can't scroll to see the entire panel.
This is my code:

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JScrollPane;
import java.awt.Dimension;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

@SuppressWarnings("serial")
public class PanelWithZoom extends JPanel{

    private JButton btnZoomIn;
    private JButton btnZoomOut;
    private double scale = 1;
    private JPanel innerPanel;
    private JPanel outerPanel;
    public PanelWithZoom() {
        setLayout(new BorderLayout(0, 0));

        JPanel panel = new JPanel();
        add(panel, BorderLayout.NORTH);

        btnZoomIn = new JButton("zoom in");
        btnZoomIn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                scale = scale + 0.1;
                outerPanel.repaint();
                outerPanel.revalidate();
            }
        });
        panel.add(btnZoomIn);

        btnZoomOut = new JButton("zoom out");
        btnZoomOut.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                scale = scale - 0.1;
                outerPanel.repaint();
                outerPanel.revalidate();
            }
        });
        panel.add(btnZoomOut);

        JPanel panel_1 = new JPanel();
        add(panel_1, BorderLayout.WEST);

        JPanel panel_2 = new JPanel();
        add(panel_2, BorderLayout.SOUTH);

        JPanel panel_3 = new JPanel();
        add(panel_3, BorderLayout.EAST);

        outerPanel = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);

                Graphics2D g2 = (Graphics2D) g;             
                int w = (int) getWidth();
                int h = (int) getHeight();
                // Translate used to make sure scale is centered
                g2.translate(w/2, h/2);
                g2.scale(scale, scale);
                g2.translate(-w/2, -h/2);
            }


        };
        JScrollPane scroll = new JScrollPane(outerPanel);
        add(scroll, BorderLayout.CENTER);

        innerPanel = new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g;             
                g2.setColor(Color.white);
                g2.fillRect(0, 0, getWidth(), getHeight());
                g2.setColor(Color.black);
                g2.drawString("String for test", 10, 50);
                g2.drawRect(0, 0, getWidth()-1, getHeight()-1);
                setPreferredSize(new Dimension(595, 842));
            }

        };

        outerPanel.add(innerPanel);
    }


    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setContentPane(new PanelWithZoom());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible(true);
    }

}

you can test it to understand what I mean.

Override the getPreferredSize method of your component, return the size of the component based on the scale and original size of the component.

Because you want to apply scaling to the child components, you will probably want to override paint instead of paintComponent

outerPanel = new JPanel(){
    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g.create();             
        g2.scale(scale, scale);
        super.paint(g);
        g2.dispose()
    }
}    

BUT, Swing components can be painted independently of their parent containers, meaning the the paint method may not be called when the child component is painted...

The problem with this is, it won't scale the mouse events (or a bunch of other properties).

With an ever mounting list of issues, a better solution is to use something like JXLayer, as demonstrated here

Side notes:

  • Use Graphics#create to copy the properties of the Graphics context and Graphics#dispose , it's safer when dealing with translation/transformations/rendering hints and bunch of other properties, as any changes to the copy won't effect the original
  • Don't call any method from within any paint method which might directly or indirectly cause a repaint event to be triggered, you'll end up in a nasty never ending loop which will eventually consume your CPU

Graphics#create and #Dispose example...

outerPanel = new JPanel(){
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g.create();             
        int w = (int) getWidth();
        int h = (int) getHeight();
        // Translate used to make sure scale is centered
        g2.translate(w/2, h/2);
        g2.scale(scale, scale);
        g2.translate(-w/2, -h/2);
        g2.dispose();
    }
}    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM