根据JLabel的大小调整Java Swing中的ImageIcon

4

我是一名新手程序员,有一个问题要问,我在我的GUI中浏览了一张图片(也在文本框中设置了路径),并将其显示在标签上,但是标签的尺寸仅为100x100,而图片要大得多,因此当我将其打开/显示到标签时,它被裁剪了,是否有任何方法使其自动调整到标签大小?下面是我在浏览按钮和打开对话框中的逻辑代码,请告诉我哪里出了问题。

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");
        }

    }

}

请发布您的整个代码,包括NetBeans生成的“initComponents”方法。它在那里,您只需要展开折叠的“Generated Code”部分即可。 - tbodt
2个回答

5
除非你真的想要一个难以解决的问题,否则我建议利用布局管理系统。
在尽可能的情况下,不要试图设置组件的大小和位置,让它们自己决定如何显示。
虽然我个人喜欢使用Netbeans表单设计器,但我鼓励你花时间学习如何手动构建UI,这将使你更加欣赏表单设计器所能做到的事情,以及可以采用的高级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;
        }
    }
}       

我在这里加入了Rob Camick的WrapLayout(他经常出没于此),因为说实话,其他布局管理器都没有给我想要的效果。
我还用图片路径设置了标签的文本
请查看使用布局管理器布局管理器视觉指南 请查看WrapLayout 更新后包括文本字段 如果您想将文本字段与图像相关联,则建议您将标签和文本字段都添加到一个JPanel中(使用类似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();
    }
}

并且更新了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();
                }
        }
    }
});

实际上,我想在文件选择框的“打开”按钮被点击时显示图像并在文本字段中设置路径... - Rohit
1
好的,你遇到了哪个部分的问题? - MadProgrammer

0

你应该删除对 label.setSize 的调用。同时,你应该将所有组件放置在表单设计器中,而不是在单击按钮时生成它们。也许你还可以顺便添加一个布局管理器?这将真正涉及到反对 NetBeans 的革命。


实际上,我想要在文件选择框的“打开”按钮被点击时显示图像并将路径设置在文本字段中。 - Rohit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接