选择布局管理器 - Java



我找不到合适的布局管理器。我在 JPanel 中有一些图像,它们的大小都不同,所以我想使用流布局让经理处理它们。管理器尽可能填充所有第一行,然后翘曲到另一行。这一切都没关系,但我想要的是停止第二次"扭曲"。我只想显示 2 行图像,如果您想查看更多图像,则必须单击 JButton 以加载其他图像。实际上,FlowLayout一直在第三行中插入,并且由于面板不够"高",图像被削减了一半。有什么提示吗?我已经尝试过流布局和米格布局,但没有成功。

将 FlowLayout(outerPanel) 与 GridBagLayout(innerPannel) 组合在一起您可以自己定义行,然后在其上放置一个JScrollPane,这样它就不会剪切您的图片,并且您仍然可以完整地看到它们(我的建议)

我忍不住试图解决这个问题。 我曾希望使用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);
            }
        });
    }
}

相关内容

  • 没有找到相关文章

最新更新