Java image zooming japplet

前端 未结 1 1295
鱼传尺愫
鱼传尺愫 2021-01-29 13:23

Im trying to make an applet that will allow me to open, zoom in and out of an image. Ive got a working applet going, but am having trouble with the zoom. Any ideas on where to h

相关标签:
1条回答
  • 2021-01-29 13:49

    You could continue to use a JLabel and scale the image and reset the JLabels icon property, or you could create a custom component dedicated to the job...

    To start with, we need to display the image...

    public class ZoomPane extends JPanel {
    
        private BufferedImage master;
        private Image scaled;
        private float scale = 1f;
    
        public ZoomPane() {
            try {
                master = ImageIO.read(new File("..."));
                scaled = master;
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            return scaled != null ? new Dimension(scaled.getWidth(this), scaled.getHeight(this)) : new Dimension(200, 200);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (scaled != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - scaled.getWidth(this)) / 2;
                int y = (getHeight() - scaled.getHeight(this)) / 2;
                g2d.drawImage(scaled, x, y, this);
                g2d.dispose();
            }
        }
    
    }
    

    Now, you could use a MouseWheelListener to scale the image...

    addMouseWheelListener(new MouseWheelListener() {
        @Override
        public void mouseWheelMoved(MouseWheelEvent e) {
            if (e.getWheelRotation() < 0) {
                scale -= 0.1;
            } else {
                scale += 0.1;
            }
            scaleBy(scale);
        }
    });
    

    And because you'll probably want to allow the users a few different methods to scale the image, a nice convenience method....

    public void scaleBy(float amount) {
        scale += amount;
        scale = Math.min(Math.max(scale, 0.1f), 200);
        scaled = master.getScaledInstance(
                        Math.round(master.getWidth() * scale),
                        Math.round(master.getHeight() * scale),
                        Image.SCALE_SMOOTH);
        revalidate();
        repaint();
    }
    

    Now, it'd probably be nice to allow the user to use the + and - keys, for this, we'll want some kind of Action...

    public class ZoomAction extends AbstractAction {
        private ZoomPane zoomPane;
        private float zoomAmount;
    
        public ZoomAction(ZoomPane zoomPane, String name, float zoomAmount) {
            this.zoomAmount = zoomAmount;
            this.zoomPane = zoomPane;
            putValue(NAME, name);
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            zoomPane.scaleBy(zoomAmount);
            System.out.println("...");
        }
    
    }
    

    This allows us to bind keyboard actions, buttons and menus and re-use the same basic code to do it...

    InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
    ActionMap am = getActionMap();
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0), "zoom-in");
    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0), "zoom-out");
    
    am.put("zoom-in", new ZoomAction(this, "Zoom in", 0.1f));
    am.put("zoom-out", new ZoomAction(this, "Zoom out", -0.1f));
    

    This example works with the numpad + and - keys.

    All this functionality should be added directly within the ZoomPane

    You can re-use the ZoomAction in your menus...

    JMenuBar mb = new JMenuBar();
    JMenu pictureMenu = new JMenu("Picture");
    pictureMenu.add(new ZoomAction(zoomPane, "Zoom In", 0.1f));
    pictureMenu.add(new ZoomAction(zoomPane, "Zoom Out", -0.1f));
    mb.add(pictureMenu);
    

    And even in you buttons...

    JPanel buttons = new JPanel();
    buttons.add(new JButton(new ZoomAction(zoomPane, "Zoom In", 0.1f)));
    buttons.add(new JButton(new ZoomAction(zoomPane, "Zoom Out", -0.1f)));
    frame.add(buttons, BorderLayout.SOUTH);
    

    Warning

    The scaling is pretty rough and ready, you should consider taking a look at:

    • The Perils of Image.getScaledInstance()
    • Java: maintaining aspect ratio of JPanel background image
    • Quality of Image after resize very low -- Java

    ... for more details

    And finally, hacking it all together, as a runnable example...

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.awt.event.MouseWheelEvent;
    import java.awt.event.MouseWheelListener;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import javax.imageio.ImageIO;
    import javax.swing.AbstractAction;
    import javax.swing.ActionMap;
    import javax.swing.InputMap;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JPanel;
    import javax.swing.KeyStroke;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    ZoomPane zoomPane = new ZoomPane();
    
                    JMenuBar mb = new JMenuBar();
                    JMenu pictureMenu = new JMenu("Picture");
                    pictureMenu.add(new ZoomAction(zoomPane, "Zoom In", 0.1f));
                    pictureMenu.add(new ZoomAction(zoomPane, "Zoom Out", -0.1f));
    
                    mb.add(pictureMenu);
    
                    JFrame frame = new JFrame("Testing");
                    frame.setJMenuBar(mb);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(zoomPane);
    
                    JPanel buttons = new JPanel();
                    buttons.add(new JButton(new ZoomAction(zoomPane, "Zoom In", 0.1f)));
                    buttons.add(new JButton(new ZoomAction(zoomPane, "Zoom Out", -0.1f)));
                    frame.add(buttons, BorderLayout.SOUTH);
    
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class ZoomPane extends JPanel {
    
            private BufferedImage master;
            private Image scaled;
            private float scale = 1f;
    
            public ZoomPane() {
                try {
                    master = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo\\megatokyo_omnibus_1_3_cover_by_fredrin-d4oupef.jpg"));
                    scaled = master;
    
                    addMouseWheelListener(new MouseWheelListener() {
                        @Override
                        public void mouseWheelMoved(MouseWheelEvent e) {
                            if (e.getWheelRotation() < 0) {
                                scale -= 0.1;
                            } else {
                                scale += 0.1;
                            }
                            scaleBy(scale);
                        }
                    });
    
                    InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                    ActionMap am = getActionMap();
                    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD, 0), "zoom-in");
                    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SUBTRACT, 0), "zoom-out");
    
                    am.put("zoom-in", new ZoomAction(this, "Zoom in", 0.1f));
                    am.put("zoom-out", new ZoomAction(this, "Zoom out", -0.1f));
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            public void scaleBy(float amount) {
                scale += amount;
                scale = Math.min(Math.max(scale, 0.1f), 200);
                scaled = master.getScaledInstance(
                                Math.round(master.getWidth() * scale),
                                Math.round(master.getHeight() * scale),
                                Image.SCALE_SMOOTH);
                revalidate();
                repaint();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return scaled != null ? new Dimension(scaled.getWidth(this), scaled.getHeight(this)) : new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (scaled != null) {
                    Graphics2D g2d = (Graphics2D) g.create();
                    int x = (getWidth() - scaled.getWidth(this)) / 2;
                    int y = (getHeight() - scaled.getHeight(this)) / 2;
                    g2d.drawImage(scaled, x, y, this);
                    g2d.dispose();
                }
            }
    
        }
    
        public class ZoomAction extends AbstractAction {
            private ZoomPane zoomPane;
            private float zoomAmount;
    
            public ZoomAction(ZoomPane zoomPane, String name, float zoomAmount) {
                this.zoomAmount = zoomAmount;
                this.zoomPane = zoomPane;
                putValue(NAME, name);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                zoomPane.scaleBy(zoomAmount);
                System.out.println("...");
            }
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题