Difficulty in resizing an image which is stored in a JLabel

非 Y 不嫁゛ 提交于 2019-12-24 20:37:48

问题


I managed to increase an image of JLabel(which has an imageIcon stored in). When I press the increase size button, the original size of the image is increased on the panel, which is exactly what I want. However, when I click on my decrease size button(I figured dividing it by the scale might fix it)the label decreases, but the actual image appearance(size I guess)is changed. It's not decreasing the size, the same way my increase button increases the size. I have spent hours trying to figure out why by multiplying it, I am able to increase the size of a the label and the image in it(which implies that not just the label is increasing, the actual image is too)but for decrease(I'm dividing instead of multiplying)it doesn't work. Here is both my increase and decrease listener.

    public class IncreaseSizeListener implements ActionListener {
    static JLabel increasedLabel;
    @Override
    public void actionPerformed(ActionEvent e) {        
        increasedLabel = CardLabelListener.selectedLabel;
        Icon icon = CardLabelListener.selectedLabel.getIcon();
        int scale =2;
        System.out.println("Increased size fired");
        //I can now resize images, based on my needs
        BufferedImage bi = new BufferedImage(
            scale*icon.getIconWidth(),
            scale*icon.getIconHeight(),
            BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = bi.createGraphics();
            g.scale(scale,scale);
            icon.paintIcon(null,g,0,0);
            g.dispose();
            JLabel temp = new JLabel(new ImageIcon(bi));
            //to ensure proper size is kept for the enlarged image
            CardLabelListener.selectedLabel.setSize(icon.getIconWidth()*scale, icon.getIconHeight()*(scale));
            CardLabelListener.selectedLabel.setIcon(temp.getIcon());
            CardLabelListener.selectedLabel.updateUI(); 
    }


}


public class DecreaseSizeListener implements ActionListener {
    static JLabel increasedLabel;
    @Override
    public void actionPerformed(ActionEvent e) {        
        increasedLabel = CardLabelListener.selectedLabel;
      Icon icon = CardLabelListener.selectedLabel.getIcon();

        int scale =2;
        //I can now resize images, based on my needs
        BufferedImage bi = new BufferedImage(
            icon.getIconWidth()/scale,
            icon.getIconHeight()/scale,
            BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = bi.createGraphics();
            g.scale(scale,scale);
            icon.paintIcon(null,g,0,0);
            g.dispose();
            JLabel temp = new JLabel(new ImageIcon(bi));
            //to ensure proper size is kept for the enlarged image
        CardLabelListener.selectedLabel.setSize( (icon.getIconWidth()/scale), (icon.getIconHeight()/(scale)));
            CardLabelListener.selectedLabel.setIcon(temp.getIcon());
            CardLabelListener.selectedLabel.updateUI();

    }


}

回答1:


Change g.scale(scale,scale); to g.scale(0.5d,0.5d); in your decrease action listener

Or you could do this...

int scale = 0.5;
//I can now resize images, based on my needs
BufferedImage bi = new BufferedImage(
    icon.getIconWidth() * scale,
    icon.getIconHeight() * scale,
    BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.scale(scale,scale);
icon.paintIcon(null,g,0,0);
g.dispose();
// This really isn't required...
//JLabel temp = new JLabel(new ImageIcon(bi));
//to ensure proper size is kept for the enlarged image
// There is a better way...
//CardLabelListener.selectedLabel.setSize( (icon.getIconWidth()/scale), (icon.getIconHeight()/(scale)));
// This isn't required
//CardLabelListener.selectedLabel.setIcon(temp.getIcon());
// This doesn't do what you think it does...
//CardLabelListener.selectedLabel.updateUI();

CardLabelListener.selectedLabel.setIcon(new ImageIcon(bi));
CardLabelListener.selectedLabel.setSize(CardLabelListener.selectedLabel.getPreferredSize());

Now both the increase and decrease algorithm's are just about the same (except for the factor), you should be able to use a single method ;)

This is pretty much the code I ended up with...

public class ScaleMyIcon {

    public static void main(String[] args) {
        new ScaleMyIcon();
    }

    public ScaleMyIcon() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ScaleMyIconPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    protected class ScaleMyIconPane extends JPanel {

        public ScaleMyIconPane() {

            setLayout(new BorderLayout());

            ImageIcon image = null;

            try {
                image = new ImageIcon(ImageIO.read(getClass().getResource("/stormtrooper-tie.jpg")));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            JLabel label = new JLabel(image);
            add(label);

            JPanel buttons = new JPanel();
            JButton increase = new JButton("+");
            JButton decrease = new JButton("-");

            buttons.add(increase);
            buttons.add(decrease);

            increase.addActionListener(new IncreaseSizeListener(label));
            decrease.addActionListener(new DecreaseSizeListener(label));

            add(buttons, BorderLayout.SOUTH);
        }
    }

    public class Scaler {

        public Icon getScaledInstance(Icon original, double scale) {
            BufferedImage bi = new BufferedImage(
                    (int)Math.round(scale * original.getIconWidth()),
                    (int)Math.round(scale * original.getIconHeight()),
                    BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = bi.createGraphics();
            g.scale(scale, scale);
            original.paintIcon(null, g, 0, 0);
            g.dispose();

            return new ImageIcon(bi);
        }
    }

    public class IncreaseSizeListener extends Scaler implements ActionListener {

        private JLabel increasedLabel;

        private IncreaseSizeListener(JLabel label) {
            increasedLabel = label;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Icon icon = increasedLabel.getIcon();
            int scale = 2;
            increasedLabel.setIcon(getScaledInstance(icon, scale));
        }
    }

    public class DecreaseSizeListener extends Scaler implements ActionListener {

        private JLabel decreasedLabel;

        private DecreaseSizeListener(JLabel label) {
            decreasedLabel = label;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Icon icon = decreasedLabel.getIcon();
            decreasedLabel.setIcon(getScaledInstance(icon, 0.5d));
        }
    }
}

UPDATED with different approach

While I was mucking around with it, I noticed two issues. There was no coalition between the up and down scales and you were never using the original image to scale against, you were always scaling the dirty image. Try scaling the image down and back up again.

This is my take on how to overcome those issues

public class ScaleMyIcon {

    public static void main(String[] args) {
        new ScaleMyIcon();
    }

    public ScaleMyIcon() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ScaleMyIconPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    protected class ScaleMyIconPane extends JPanel {

        public ScaleMyIconPane() {

            setLayout(new BorderLayout());

            ImageIcon image = null;

            try {
                image = new ImageIcon(ImageIO.read(getClass().getResource("/stormtrooper-tie.jpg")));
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            JLabel label = new JLabel(image);
            add(label);

            JPanel buttons = new JPanel();
            JButton increase = new JButton("+");
            JButton decrease = new JButton("-");

            buttons.add(increase);
            buttons.add(decrease);

            increase.addActionListener(new IncreaseSizeListener(label));
            decrease.addActionListener(new DecreaseSizeListener(label));

            add(buttons, BorderLayout.SOUTH);

        }
    }

    public static class Scalable {

        private JLabel label;
        private Icon original;
        private static double scale = 1;

        private Scalable(JLabel label) {
            this.label = label;
            original = label.getIcon();
        }

        public JLabel getLabel() {
            return label;
        }

        public double getScale() {
            return scale;
        }

        public void setScale(double scale) {
            this.scale = scale;
        }

        public void incrementScale(double factor) {

            setScale(getScale() + factor);

        }

        public Icon getScaledInstance() {

            BufferedImage bi = new BufferedImage(
                    (int) Math.round(scale * original.getIconWidth()),
                    (int) Math.round(scale * original.getIconHeight()),
                    BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = bi.createGraphics();
            g.scale(scale, scale);
            original.paintIcon(null, g, 0, 0);
            g.dispose();

            return new ImageIcon(bi);

        }
    }

    public class IncreaseSizeListener extends Scalable implements ActionListener {

        public IncreaseSizeListener(JLabel label) {
            super(label);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            incrementScale(0.05);
            getLabel().setIcon(getScaledInstance());
        }
    }

    public class DecreaseSizeListener extends Scalable implements ActionListener {

        private DecreaseSizeListener(JLabel label) {
            super(label);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            incrementScale(-0.05);
            getLabel().setIcon(getScaledInstance());
        }
    }
}


来源:https://stackoverflow.com/questions/13149624/difficulty-in-resizing-an-image-which-is-stored-in-a-jlabel

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!