选择布局管理器 - Java

时间:2016-02-25 17:54:48

标签: java swing layout miglayout flowlayout

我无法找到合适的布局管理器。我在JPanel中有一些图像,它们都是不同的大小,所以我想使用Flow Layout让管理器处理它们。管理器尽可能填充所有第一行,然后转换到另一行。这一切都很好,但我想要的是停在第二个“扭曲”。我只想显示2行图像,如果你想看到更多,你必须单击一个JButton来加载其他图像。实际上,FlowLayout继续插入第三行,并且图像被切割了一半,因为面板不够“高”。有小费吗? 我已经尝试过使用Flow Layout和Mig Layout而没有成功。

2 个答案:

答案 0 :(得分:0)

将FlowLayout(outerPanel)与GridBagLayout(innerPannel)结合使用 你可以自己定义行,然后你把JScrollPane放在它上面所以它不会剪切你的照片你仍然可以看到它们的全尺寸(我的建议)

答案 1 :(得分:0)

我无法抗拒试图解决这个问题。我本来希望使用FlowLayouts,但最后,我最终只使用了GridBagLayouts:每行图像一个,加上整个容器一个。我可能在灵活性方面过度设计,但我想这样的事情对我或将来的其他人可能有用。

实际上,每次容器更改大小,或添加/删除图像或其任何可视属性发生更改时,都会调用updateLayout(),从头开始重建所有GridBagLayout面板。我确信有一些方法可以提高效率,而且我确信可以从scatch编写一个LayoutManager2实现来完成这项工作,但这对我来说表现得相当不错。

import java.util.List;
import java.util.ArrayList;
import java.util.Objects;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;

import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;

import java.awt.image.BufferedImage;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class ImagePanel
extends JPanel {
    private static final long serialVersionUID = 1;

    /** @serial */
    private final List<Icon> images = new ArrayList<>();

    /** @serial */
    private final List<Icon> scaledImages = new ArrayList<>();

    /** @serial */
    private int maxRowCount = 2;

    /** @serial */
    private int hgap = 6;

    /** @serial */
    private int vgap = 6;

    /** @serial */
    private int maxImageWidth = 200;

    /** @serial */
    private int maxImageHeight = 200;

    public ImagePanel() {
        setLayout(new GridBagLayout());
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent event) {
                updateLayout();
            }
        });
    }

    @Override
    public void addNotify() {
        super.addNotify();
        updateLayout();
    }

    @Override
    public Dimension getPreferredSize() {
        Rectangle screen = findGraphicsConfiguration().getBounds();

        Dimension size = new Dimension();
        Dimension row = new Dimension();
        int rowsComputed = 0;
        int gap = 0;
        for (Icon image : scaledImages) {
            if (row.width > 0 &&
                row.width + gap + image.getIconWidth() > screen.width) {

                if (++rowsComputed >= maxRowCount) {
                    break;
                }

                size.width = Math.max(size.width, row.width);
                size.height += (size.height > 0 ? vgap : 0) + row.height;
                row.setSize(0, 0);
                gap = 0;
            }
            row.width += gap + image.getIconWidth();
            row.height = Math.max(row.height, image.getIconHeight());
            gap = hgap;
        }

        size.width = Math.max(size.width, row.width);
        size.height += (size.height > 0 ? vgap : 0) + row.height;

        return size;
    }

    private void updateLayout() {
        int width = getWidth();
        if (width == 0) {
            return;
        }

        for (Component rowContainer : getComponents()) {
            ((JComponent) rowContainer).removeAll();
        }

        GridBagConstraints rowConstraints = new GridBagConstraints();
        rowConstraints.gridwidth = GridBagConstraints.REMAINDER;
        rowConstraints.weightx = 1;
        rowConstraints.anchor = GridBagConstraints.FIRST_LINE_START;

        int row = -1;
        int rowWidth = 0;
        GridBagConstraints gbc = new GridBagConstraints();
        for (Icon image : scaledImages) {
            JComponent rowContainer = (row >= 0 && row < getComponentCount() ?
                (JComponent) getComponent(row) : null);
            int gap = (rowWidth > 0 ? hgap : 0);

            if (rowContainer == null ||
                rowWidth + gap + image.getIconWidth() > width) {

                if (++row >= maxRowCount) {
                    break;
                }

                gap = 0;
                rowWidth = 0;

                if (row < getComponentCount()) {
                    rowContainer = (JComponent) getComponent(row);
                } else {
                    rowContainer = new JPanel(new GridBagLayout());
                    add(rowContainer, rowConstraints);
                }
                rowConstraints.insets.top = vgap;
            }

            gbc.insets.left = gap;
            JComponent imageContainer = new JLabel(image);
            rowContainer.add(imageContainer, gbc);

            rowWidth += gap + image.getIconWidth();
        }

        for (int i = getComponentCount() - 1; i >= maxRowCount; i--) {
            remove(i);
        }
    }

    private GraphicsConfiguration findGraphicsConfiguration() {
        GraphicsConfiguration config = getGraphicsConfiguration();
        if (config == null) {
            GraphicsEnvironment env =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
            config = env.getDefaultScreenDevice().getDefaultConfiguration();
        }
        return config;
    }

    private Icon scale(Icon image) {
        int imageWidth = image.getIconWidth();
        int imageHeight = image.getIconHeight();
        if (imageWidth > maxImageWidth || imageHeight > maxImageHeight) {
            float scale = Math.min((float) maxImageWidth / imageWidth,
                                   (float) maxImageHeight / imageHeight);
            if (scale < 1) {
                GraphicsConfiguration config = findGraphicsConfiguration();
                BufferedImage scaledImage = config.createCompatibleImage(
                    (int) (imageWidth * scale),
                    (int) (imageHeight * scale));
                Graphics2D g = scaledImage.createGraphics();
                g.scale(scale, scale);
                image.paintIcon(this, g, 0, 0);
                g.dispose();

                image = new ImageIcon(scaledImage);
            }
        }

        return image;
    }

    public List<Icon> getImages() {
        return new ArrayList<>(images);
    }

    public void clearImages() {
        images.clear();
        updateLayout();
        revalidate();
    }

    public void addImage(Icon image) {
        Objects.requireNonNull(image, "Image cannot be null");
        images.add(image);
        scaledImages.add(scale(image));
        updateLayout();
        revalidate();
    }

    public void removeImage(Icon image) {
        int index = images.indexOf(image);
        if (index >= 0) {
            removeImage(index);
        }
    }

    public void removeImage(int index) {
        images.remove(index);
        scaledImages.remove(index);
        updateLayout();
        revalidate();
    }

    public int getHgap() {
        return hgap;
    }

    public void setHgap(int gap) {
        if (gap < 0) {
            throw new IllegalArgumentException("Gap must be at least zero");
        }

        int old = this.hgap;
        this.hgap = gap;

        if (old != gap) {
            updateLayout();
            revalidate();
        }

        firePropertyChange("hgap", old, gap);
    }

    public int getVgap() {
        return vgap;
    }

    public void setVgap(int gap) {
        if (gap < 0) {
            throw new IllegalArgumentException("Gap must be at least zero");
        }

        int old = this.vgap;
        this.vgap = gap;

        if (old != gap) {
            updateLayout();
            revalidate();
        }

        firePropertyChange("vgap", old, gap);
    }

    public int getMaxRowCount() {
        return maxRowCount;
    }

    public void setMaxRowCount(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("Count must be at least zero");
        }

        int old = this.maxRowCount;
        this.maxRowCount = count;

        if (old != count) {
            updateLayout();
            revalidate();
        }

        firePropertyChange("maxRowCount", old, count);
    }

    public int getMaxImageWidth() {
        return maxImageWidth;
    }

    private void recomputeScaledImages() {
        scaledImages.clear();
        for (Icon image : images) {
            scaledImages.add(scale(image));
        }
    }

    public void setMaxImageWidth(int width) {
        if (width <= 0) {
            throw new IllegalArgumentException("Width must be positive");
        }

        int old = this.maxImageWidth;
        this.maxImageWidth = width;

        if (old != width) {
            recomputeScaledImages();
            updateLayout();
            revalidate();
        }

        firePropertyChange("maxImageWidth", old, width);
    }

    public int getMaxImageHeight() {
        return maxImageHeight;
    }

    public void setMaxImageHeight(int height) {
        if (height <= 0) {
            throw new IllegalArgumentException("Height must be positive");
        }

        int old = this.maxImageHeight;
        this.maxImageHeight = height;

        if (old != height) {
            recomputeScaledImages();
            updateLayout();
            revalidate();
        }

        firePropertyChange("maxImageHeight", old, height);
    }

    public static void main(final String[] args)
    throws java.io.IOException {
        if (args.length == 0) {
            System.err.println("Usage: java " + ImagePanel.class.getName()
                + " <directory> | <url1> <url2> ...");
            System.exit(2);
        }

        final List<java.net.URL> urls;
        if (args.length == 1 && !args[0].contains(":")) {
            urls = new ArrayList<>();
            try (java.nio.file.DirectoryStream<java.nio.file.Path> dir =
                java.nio.file.Files.newDirectoryStream(
                    java.nio.file.Paths.get(args[0]))) {

                for (java.nio.file.Path file : dir) {
                    urls.add(file.toUri().toURL());
                }
            }
        } else {
            urls = new ArrayList<>(args.length);
            for (String url : args) {
                urls.add(new java.net.URL(url));
            }
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                ImagePanel imagePanel = new ImagePanel();
                for (java.net.URL url : urls) {
                    imagePanel.addImage(new ImageIcon(url));
                }

                javax.swing.JFrame frame =
                    new javax.swing.JFrame("ImagePanel");
                frame.setDefaultCloseOperation(
                    javax.swing.JFrame.EXIT_ON_CLOSE);

                JPanel panel = new JPanel(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.fill = GridBagConstraints.HORIZONTAL;
                gbc.anchor = GridBagConstraints.FIRST_LINE_START;
                gbc.weightx = 1;
                gbc.weighty = 1;
                panel.add(imagePanel, gbc);

                frame.getContentPane().add(panel);
                frame.pack();
                frame.setLocationByPlatform(true);
                frame.setVisible(true);
            }
        });
    }
}