java swing根据jLabel调整ImageIcon的大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18010803/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:46:51  来源:igfitidea点击:

java swing resize ImageIcon according to jLabel

javaswingimageicon

提问by Rohit

i am a new programmer here and i have something to ask, i have browse a picture into my GUI (and set the path in text box also)which displays on a Label, but the label dimension is set only 100,100 while the picture is much bigger so when i open/display it into the label it get cropped , is there anyway to make it auto resize to the label size? below is my logic code on browse button and open dialog box please any one tell me where i am wrong..

我是这里的一名新程序员,我有一些事情要问,我已将图片浏览到我的 GUI(并在文本框中设置路径),它显示在标签上,但标签尺寸仅设置为 100,100,而图片很多更大,所以当我将它打开/显示到标签中时,它会被裁剪,无论如何让它自动调整到标签大小?下面是我在浏览按钮和打开对话框上的逻辑代码,请任何人告诉我我错在哪里..

public class ImagePath extends javax.swing.JFrame {
    private JPanel contentPane;

    JLabel jLabel1;
    String s2;
    File targetFile;
    BufferedImage targetImg;

    public ImagePath() {
        initComponents();
    }

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

        JFileChooser jFileChooser1 = new JFileChooser();

        int state = jFileChooser1.showOpenDialog(new JFrame());

        jTextField1.setText("");
        if (state == JFileChooser.APPROVE_OPTION) {
            JOptionPane.showMessageDialog(new JFrame(), "hii");
            File file = jFileChooser1.getSelectedFile();
            s2 = file.toString();
            jTextField1.setText(s2);
            jLabel1 = new JLabel();
            jLabel1.setName(s2);
            jLabel1.setLocation(50, 50);
            jLabel1.setSize(300, 300);
            add(jLabel1);
            BufferedImage bi1;

            try {
                bi1 = ImageIO.read(file);
                ImageIcon icon1 = new ImageIcon(bi1);
                jLabel1.setIcon(icon1);

                Image img = icon1.getImage();
                ImageIcon icon = new ImageIcon(file.getPath());
                Image scaleImage = icon.getImage().getScaledInstance(28, 28, Image.SCALE_DEFAULT);

                repaint();
                pack();

            } catch (Exception e) {
                System.out.println(e);
            }
        } else if (state == JFileChooser.CANCEL_OPTION) {
            JOptionPane.showMessageDialog(new JFrame(), "Canceled");
        }

    }

}

回答by tbodt

You should cut out the call to label.setSize. You should also place all your components in in the form designer instead of producing them when you click the button. Maybe you could also add a layout manager in the bargain? This will really involve a revolt against NetBeans.

你应该切断对 的调用label.setSize。您还应该将所有组件放在表单设计器中,而不是在单击按钮时生成它们。也许您还可以在讨价还价时添加布局管理器?这将真正涉及对 NetBeans 的反抗。

回答by MadProgrammer

Unless you really want a nasty head ache, I would suggest taking advantage of the layout management system.

除非你真的想头疼,否则我建议利用布局管理系统。

Instead of trying to set the size and location of components, let them decide how they wan to be displayed where possible.

与其尝试设置组件的大小和位置,不如让它们决定如何尽可能地显示它们。

While I personally take advantage of Netbeans form designer, I would encourage you to take the time to learn how to build your UI's by hand, it will give a greater apprication for what the form designers can do, as well ideas you can employee to make advanced UIs - IMHO

虽然我个人利用 Netbeans 表单设计器,但我鼓励您花时间学习如何手动构建您的 UI,这将对表单设计器可以做什么以及您可以员工制作的想法有更大的了解高级用户界面 - 恕我直言

enter image description here

在此处输入图片说明

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class SimpleImageBrowser {

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

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new SimpleImageBrowser.ImageBrowserPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ImageBrowserPane extends JPanel {

        private JFileChooser fcImage = new JFileChooser();
        private SimpleImageBrowser.ImagePane imagePane;

        public ImageBrowserPane() {
            setLayout(new BorderLayout());

            imagePane = new SimpleImageBrowser.ImagePane();
            add(new JScrollPane(imagePane));

            JButton add = new JButton("Add");
            add.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

                    int state = fcImage.showOpenDialog(SimpleImageBrowser.ImageBrowserPane.this);
                    switch (state) {

                        case JFileChooser.APPROVE_OPTION:
                            File file = fcImage.getSelectedFile();

                            try {
                                BufferedImage bi1 = ImageIO.read(file);
                                ImageIcon icon1 = new ImageIcon(bi1);
                                JLabel label = new JLabel(icon1);
                                label.setText(file.getPath());
                                label.setHorizontalTextPosition(JLabel.CENTER);
                                label.setVerticalTextPosition(JLabel.BOTTOM);
                                label.setForeground(Color.WHITE);
                                label.setBorder(new LineBorder(Color.WHITE));
                                imagePane.add(label);
                                imagePane.revalidate();
                            } catch (Exception exp) {
                                exp.printStackTrace();
                            }
                    }
                }
            });

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

        }
    }

    public class ImagePane extends JPanel {

        public ImagePane() {
            setLayout(new SimpleImageBrowser.WrapLayout());
            setBackground(Color.BLACK);
        }

        @Override
        public Dimension getPreferredSize() {
            return getComponentCount() == 0 ? new Dimension(200, 200) : super.getPreferredSize();
        }
    }

    /**
     * FlowLayout subclass that fully supports wrapping of components.
     */
    public class WrapLayout extends FlowLayout {

        private Dimension preferredLayoutSize;

        /**
         * Constructs a new
         * <code>WrapLayout</code> with a left alignment and a default 5-unit
         * horizontal and vertical gap.
         */
        public WrapLayout() {
            super();
        }

        /**
         * Constructs a new
         * <code>FlowLayout</code> with the specified alignment and a default 5-unit
         * horizontal and vertical gap. The value of the alignment argument must be
         * one of
         * <code>WrapLayout</code>,
         * <code>WrapLayout</code>, or
         * <code>WrapLayout</code>.
         *
         * @param align the alignment value
         */
        public WrapLayout(int align) {
            super(align);
        }

        /**
         * Creates a new flow layout manager with the indicated alignment and the
         * indicated horizontal and vertical gaps.
         * <p>
         * The value of the alignment argument must be one of
         * <code>WrapLayout</code>,
         * <code>WrapLayout</code>, or
         * <code>WrapLayout</code>.
         *
         * @param align the alignment value
         * @param hgap the horizontal gap between components
         * @param vgap the vertical gap between components
         */
        public WrapLayout(int align, int hgap, int vgap) {
            super(align, hgap, vgap);
        }

        /**
         * Returns the preferred dimensions for this layout given the
         * <i>visible</i> components in the specified target container.
         *
         * @param target the component which needs to be laid out 
         * @return the preferred dimensions to lay out the subcomponents of the
         * specified container
         */
        @Override
        public Dimension preferredLayoutSize(Container target) {
            return layoutSize(target, true);
        }

        /**
         * Returns the minimum dimensions needed to layout the <i>visible</i>
         * components contained in the specified target container.
         *
         * @param target the component which needs to be laid out
         * @return the minimum dimensions to lay out the subcomponents of the
         * specified container
         */
        @Override
        public Dimension minimumLayoutSize(Container target) {
            Dimension minimum = layoutSize(target, false);
            minimum.width -= (getHgap() + 1);
            return minimum;
        }

        /**
         * Returns the minimum or preferred dimension needed to layout the target
         * container.
         *
         * @param target target to get layout size for
         * @param preferred should preferred size be calculated
         * @return the dimension to layout the target container
         */
        private Dimension layoutSize(Container target, boolean preferred) {
            synchronized (target.getTreeLock()) {
                //  Each row must fit with the width allocated to the containter.
                //  When the container width = 0, the preferred width of the container
                //  has not yet been calculated so lets ask for the maximum.

                int targetWidth = target.getSize().width;

                if (targetWidth == 0) {
                    targetWidth = Integer.MAX_VALUE;
                }

                int hgap = getHgap();
                int vgap = getVgap();
                Insets insets = target.getInsets();
                int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
                int maxWidth = targetWidth - horizontalInsetsAndGap;

                //  Fit components into the allowed width

                Dimension dim = new Dimension(0, 0);
                int rowWidth = 0;
                int rowHeight = 0;

                int nmembers = target.getComponentCount();

                for (int i = 0; i < nmembers; i++) {
                    Component m = target.getComponent(i);

                    if (m.isVisible()) {
                        Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

                        //  Can't add the component to current row. Start a new row.

                        if (rowWidth + d.width > maxWidth) {
                            addRow(dim, rowWidth, rowHeight);
                            rowWidth = 0;
                            rowHeight = 0;
                        }

                        //  Add a horizontal gap for all components after the first

                        if (rowWidth != 0) {
                            rowWidth += hgap;
                        }

                        rowWidth += d.width;
                        rowHeight = Math.max(rowHeight, d.height);
                    }
                }

                addRow(dim, rowWidth, rowHeight);

                dim.width += horizontalInsetsAndGap;
                dim.height += insets.top + insets.bottom + vgap * 2;

                //    When using a scroll pane or the DecoratedLookAndFeel we need to
                //  make sure the preferred size is less than the size of the
                //  target containter so shrinking the container size works
                //  correctly. Removing the horizontal gap is an easy way to do this.

                Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);

                if (scrollPane != null && target.isValid()) {
                    dim.width -= (hgap + 1);
                }

                return dim;
            }
        }

        /*
         *  A new row has been completed. Use the dimensions of this row
         *  to update the preferred size for the container.
         *
         *  @param dim update the width and height when appropriate
         *  @param rowWidth the width of the row to add
         *  @param rowHeight the height of the row to add
         */
        private void addRow(Dimension dim, int rowWidth, int rowHeight) {
            dim.width = Math.max(dim.width, rowWidth);

            if (dim.height > 0) {
                dim.height += getVgap();
            }

            dim.height += rowHeight;
        }
    }
}       

I've included WrapLayoutby Rob Camick (who lurks about the place) because, to be quite frank, none of the other layout managers gave me the effect I wanted.

WrapLayout被 Rob Camick(潜伏在这个地方)包括在内,因为坦率地说,其他布局管理器都没有给我想要的效果。

I also set the label's text with the path of the image

我还用图像的路径设置了标签的文本

Take a look at Using layout Managersand A Visual Guide to Layout Managers

看看使用布局管理器布局管理器的可视化指南

Take a look at WrapLayout

看一眼 WrapLayout

Updated with text fields

更新了文本字段

If you want to associate a text field with the image, then I suggest you add both the label and text field to a JPanel(using something like a BorderLayout) and then add that to your image pane...

如果您想将文本字段与图像相关联,那么我建议您将标签和文本字段都添加到 a JPanel(使用类似 a 的东西BorderLayout),然后将其添加到您的图像窗格中...

enter image description here

在此处输入图片说明

public class ImagePane extends JPanel {

    public ImagePane() {
        setLayout(new SimpleImageBrowser.WrapLayout());
        setBackground(Color.BLACK);
    }

    public void addImage(File file) throws IOException {
        BufferedImage bi1 = ImageIO.read(file);
        ImageIcon icon1 = new ImageIcon(bi1);
        JPanel imgPane = new JPanel(new BorderLayout());
        imgPane.setOpaque(false);
        JLabel label = new JLabel(icon1);
        imgPane.add(label);
        JTextField field = new JTextField(file.getPath(), 20);
        field.setEditable(false);
        imgPane.add(field, BorderLayout.SOUTH);
        add(imgPane);
        revalidate();
    }

    @Override
    public Dimension getPreferredSize() {
        return getComponentCount() == 0 ? new Dimension(200, 200) : super.getPreferredSize();
    }
}

And the updated ActionListener...

和更新的ActionListener...

add.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {

        int state = fcImage.showOpenDialog(SimpleImageBrowser.ImageBrowserPane.this);
        switch (state) {

            case JFileChooser.APPROVE_OPTION:
                File file = fcImage.getSelectedFile();
                try {
                    imagePane.addImage(file);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
        }
    }
});