【问题标题】:How to layout Components when Conponent Size is needed beforehand (Java)事先需要组件大小时如何布局组件(Java)
【发布时间】:2022-06-29 01:32:44
【问题描述】:

所以问题是这样的,我有一个项目,我想在面板中布局组件,并且需要事先知道面板的大小,以便我可以相应地缩放面板上的面板。 但是正如我在许多帖子和博客中所读到的,使用任何 get*Size() 方法都不是好习惯,而是让 LayoutManager 完成所有这些工作。 问题是我应该如何告诉我的面板它们需要多大以及如何调整它们的大小,它们也必须始终保持比例。

由于我不能将任何 CodeSnipped 放在这里,因为它不起作用,我可以展示负责计算面板大小的类。我稍微修改了代码。

public class JColorCardPanel extends JPanel {

    private static final long serialVersionUID = 7038017071626911475L;

    public JColorCardPanel() {
        super(new GridBagLayout());
        this.setBackground(Color.LIGHT_GRAY);
    }

    public void updateColorCardPanel(int maxPanelHeight) {
        this.removeAll();

        Map<TransportMode, SortedMap<Integer, List<ColorCard>>> rankingMap = new HashMap<>();
        SortedMap<Integer, List<ColorCard>> mapTrain = new TreeMap<>();
        mapTrain.put(3, List.of(new ColorCard(MyColor.PURPLE, TransportMode.TRAIN), new ColorCard(MyColor.RAINBOW, TransportMode.TRAIN), new ColorCard(MyColor.YELLOW, TransportMode.TRAIN)));
        mapTrain.put(4, List.of(new ColorCard(MyColor.BLACK, TransportMode.TRAIN), new ColorCard(MyColor.WHITE, TransportMode.TRAIN), new ColorCard(MyColor.RED, TransportMode.TRAIN),
                new ColorCard(MyColor.ORANGE, TransportMode.TRAIN), new ColorCard(MyColor.GREEN, TransportMode.TRAIN)));
        rankingMap.put(TransportMode.TRAIN, mapTrain);
        SortedMap<Integer, List<ColorCard>> mapShip = new TreeMap<>();
        mapShip.put(2, List.of(new ColorCard(MyColor.PURPLE, TransportMode.SHIP), new ColorCard(MyColor.RAINBOW, TransportMode.SHIP), new ColorCard(MyColor.BLACK, TransportMode.SHIP),
                new ColorCard(MyColor.WHITE, TransportMode.SHIP), new ColorCard(MyColor.YELLOW, TransportMode.SHIP)));
        mapShip.put(3, List.of(new ColorCard(MyColor.WHITE, TransportMode.SHIP), new ColorCard(MyColor.RED, TransportMode.SHIP), new ColorCard(MyColor.ORANGE, TransportMode.SHIP),
                new ColorCard(MyColor.GREEN, TransportMode.SHIP)));
        rankingMap.put(TransportMode.SHIP, mapShip);

        int padding = 5;
        double ratio = 2 / 3.0;
        int maxHeight = 150;
        int maxWidth = (int) (maxHeight * ratio);
        int height = 0;
        int width = 0;
        while (width <= (padding * 4)) {
            int maxColumnCount = rankingMap.values().stream().flatMap(t -> Stream.of(t.values().stream().flatMap(List::stream).toList().size())).mapToInt(i -> i).max().getAsInt();
            int maxPossibleHeight = ((maxPanelHeight - 20) / maxColumnCount) - (2 * padding);
            int maxRowCount = rankingMap.values().stream().flatMap(t -> Stream.of(new ArrayList<>(t.keySet()).get(0))).reduce(0, (t, u) -> t + u);
            int maxPossibleWidth = ((this.getWidth() - 20) / maxRowCount) - (2 * padding);
            height = maxPossibleHeight > maxHeight ? maxHeight : maxPossibleHeight;
            width = maxPossibleWidth > maxWidth ? maxWidth : maxPossibleWidth;
            double proportion = width / (double) height;
            if (proportion < ratio) {
                height = (int) (width / ratio);
            } else {
                width = (int) (height * ratio);
            }
            padding--;
        }
        Dimension prefederredDimension = new Dimension(width, height);
        GridBagConstraints gbcTransport = new GridBagConstraints();
        gbcTransport.anchor = GridBagConstraints.NORTH;
        Iterator<Entry<TransportMode, SortedMap<Integer, List<ColorCard>>>> iteratorMap = rankingMap.entrySet().iterator();
        while (iteratorMap.hasNext()) {
            JPanel transportPanel = new JPanel(new GridBagLayout());
            transportPanel.setBackground(Color.LIGHT_GRAY);
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(padding, padding, padding, padding);
            gbc.gridy = 0;
            gbc.gridx = 0;
            gbc.anchor = GridBagConstraints.NORTH;
            gbc.fill = GridBagConstraints.BOTH;

            Entry<TransportMode, SortedMap<Integer, List<ColorCard>>> entryTransportMode = iteratorMap.next();
            Iterator<Entry<Integer, List<ColorCard>>> it = entryTransportMode.getValue().entrySet().iterator();
            while (it.hasNext()) {
                Entry<Integer, List<ColorCard>> entry = it.next();
                JColorCardLabel label;
                List<ColorCard> cards = entry.getValue();
                for (int i = 0, m = cards.size(); i < m; i++) {
                    ColorCard card = cards.get(i);
                    gbc.gridx = 0;
                    for (int j = 0, n = entry.getKey(); j < n; j++) {
                        if (card.color() == MyColor.RAINBOW) {
                            label = new JGradientLabel(card);
                        } else {
                            label = new JColorCardLabel(card);
                        }
                        label.setPreferredSize(prefederredDimension);
                        transportPanel.add(label, gbc);
                        gbc.gridx++;
                    }
                    gbc.gridy++;
                }
            }
            transportPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createRaisedBevelBorder(), entryTransportMode.getKey().getDisplayNameSingular()));
            gbcTransport.gridx++;
            this.add(transportPanel, gbcTransport);
        }
        gbcTransport.weightx = 1;
        gbcTransport.weighty = 1;
        gbcTransport.gridx++;
        gbcTransport.fill = GridBagConstraints.BOTH;
        this.add(new JPanel(), gbcTransport);
    }

    private static class JColorCardLabel extends JLabel {
        private static final long serialVersionUID = -5607808287807778978L;

        public final ColorCard colorCard;

        public JColorCardLabel(ColorCard colorCard) {
            super(colorCard.getColorCardString());
            this.colorCard = colorCard;
            this.setForeground(colorCard.color().getComplementaryColor());
            this.setPreferredSize(new Dimension(60, 20));
            this.setBorder(BorderFactory.createLineBorder(Color.BLACK, 4));
            this.setBackground(colorCard.color().realColor);
            this.setHorizontalAlignment(SwingConstants.CENTER);
            this.setDoubleBuffered(true);
            this.setFocusable(false);
            this.setOpaque(true);
        }
    }

    public static class JGradientLabel extends JColorCardLabel {
        private static final long serialVersionUID = 5469665614084730926L;

        public JGradientLabel(ColorCard colorCard) {
            super(colorCard);
            this.setForeground(Color.BLACK);
            this.setBackground(null);
            this.setOpaque(false);
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();

            MyColor[] colors = MyColor.getNormalMyColors();
            int stripHeigth = this.getHeight() / (colors.length - 1);

            for (int i = 0; i < (colors.length - 1); i++) {
                g2.setPaint(new GradientPaint(new Point(0, i * stripHeigth), colors[i].realColor, new Point(0, (i + 1) * stripHeigth), colors[i + 1].realColor));
                g2.fillRect(0, i * stripHeigth, this.getWidth(), (i + 1) * stripHeigth);
            }
            g2.dispose();
            super.paintComponent(g);
        }
    }
}

这里是需要的 ColorCard 类:


public class ColorCard {

    private final MyColor color;
    private final TransportMode transportMode;

    public ColorCard(MyColor color, TransportMode transportMode) {
        this.color = color;
        this.transportMode = transportMode;
    }

    public MyColor color() {
        return this.color;
    }

    public TransportMode transportMode() {
        return this.transportMode;
    }

    public String getColorCardString() {
        return "<html><body>" + this.transportMode().getDisplayNameSingular() + "<br>" + this.color().getColorNameSingular() + "</body></html>";
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.color, this.transportMode);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) { return true; }
        if (obj == null) { return false; }
        if (this.getClass() != obj.getClass()) { return false; }
        ColorCard other = (ColorCard) obj;
        return (this.color == other.color) && (this.transportMode == other.transportMode);
    }

    @Override
    public String toString() {
        return "[" + this.color + ", " + this.transportMode + "]";
    }

    public enum MyColor {

        BLACK(LanguageKey.BLACK, LanguageKey.BLACKPLURAL, Color.BLACK),
        BLUE(LanguageKey.BLUE, LanguageKey.BLUEPLURAL, Color.BLUE),
        RED(LanguageKey.RED, LanguageKey.REDPLURAL, Color.RED),
        GREEN(LanguageKey.GREEN, LanguageKey.GREENPLURAL, Color.GREEN),
        YELLOW(LanguageKey.YELLOW, LanguageKey.YELLOWPLURAL, Color.YELLOW),
        PURPLE(LanguageKey.PURPLE, LanguageKey.PURPLEPLURAL, Color.MAGENTA),
        WHITE(LanguageKey.WHITE, LanguageKey.WHITEPLURAL, Color.WHITE),
        ORANGE(LanguageKey.ORANGE, LanguageKey.ORANGEPLURAL, Color.ORANGE),
        GRAY(LanguageKey.GRAY, LanguageKey.GRAY, Color.GRAY),
        RAINBOW(LanguageKey.RAINBOW, LanguageKey.RAINBOW, Color.MAGENTA);

        private final LanguageKey colorNameSingular;
        private final LanguageKey colorNamePlural;
        public final Color realColor;

        MyColor(LanguageKey colorNameSingular, LanguageKey colorNamePlural, Color realColor) {
            this.colorNameSingular = colorNameSingular;
            this.colorNamePlural = colorNamePlural;
            this.realColor = realColor;
        }

        public String getColorNameSingular() {
            return Application.resources.getString(this.colorNameSingular);
        }

        public String getColorNamePlural() {
            return Application.resources.getString(this.colorNamePlural);
        }

        public Color getRealColor() {
            return this.realColor;
        }

        public static MyColor getMyColor(String colorName) {
            return MyColor.valueOf(colorName.toUpperCase());
        }

        public static MyColor[] getNormalMyColors() {
            return Stream.of(MyColor.values()).filter(c -> (c != GRAY) && (c != RAINBOW)).toArray(MyColor[]::new);
        }

        public Color getComplementaryColor() {
            return MyColor.getComplementaryColor(this);
        }

        public static Color getComplementaryColor(MyColor myColor) {
            Color color = myColor.realColor;
            if (color == Color.WHITE) { return Color.BLACK; }
            if (color == Color.BLACK) { return Color.WHITE; }
            int r = color.getRed();
            int g = color.getGreen();
            int b = color.getBlue();
            int maxRGB = Math.max(r, Math.max(g, b));
            int minRGB = Math.min(r, Math.min(g, b));
            int addition = maxRGB + minRGB;
            return new Color(addition - r, addition - g, addition - b);
        }

        @Override
        public String toString() {
            return this.getColorNameSingular();
        }
    }

    public enum TransportMode implements Serializable {

        TRAIN(LanguageKey.TRAIN, LanguageKey.TRAINS, "t"),
        SHIP(LanguageKey.SHIP, LanguageKey.SHIPS, "s"),
        AIRPLANE(LanguageKey.AIRPLANE, LanguageKey.AIRPLANES, "a");

        private final LanguageKey displayNameSingular;
        private final LanguageKey displayNamePlural;
        public final String abbreviation;

        TransportMode(LanguageKey displayNameSingular, LanguageKey displayNamePlural, String abbreviation) {
            this.displayNameSingular = displayNameSingular;
            this.displayNamePlural = displayNamePlural;
            this.abbreviation = abbreviation;
        }

        public String getDisplayNameSingular() {
            return Application.resources.getString(this.displayNameSingular);
        }

        public String getDisplayNamePlural() {
            return Application.resources.getString(this.displayNamePlural);
        }

        public static TransportMode getTransportMode(String abbreviation) {
            return Stream.of(TransportMode.values()).filter(t -> t.abbreviation.equalsIgnoreCase(abbreviation)).findAny().get();
        }
    }
}

我的整个项目可以在 github 上找到 https://github.com/MineRickStar/Zug-um-Zug.git

任何关于我可以改变的答案或评论将不胜感激。

【问题讨论】:

  • 对于这种问题,最好发布一张你希望你的 gui 看起来像什么的模型图像
  • 这有点难以描述,但是就像所有的卡片都是等间距的,大小和比例一样,它应该根据组件的大小调整大小。
  • GridBagLayout 应该可以做到这一点。请注意weightxweighty
  • 从我的角度来看,当它们能够像 GridLayout 的顶部组件所说的那样缩放时,告诉标签保持相同的比例是不可能的。

标签: java swing layout jpanel size


【解决方案1】:

请运行它并告诉我这是否是您想要的调整大小行为。如果不是我就删了

import java.awt.*;
import java.awt.event.*;

import java.io.*;

import java.util.*;

import javax.swing.*;

public class F extends JFrame {
    // NOT the same as GrinBagConstraints.gridwidth/gridheight
    private static final int GRID_WIDTH = 4;
    private static final int GRID_HEIGHT = 2;

    private void setGui() {
        try {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Container cp = getContentPane();
            cp.setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.anchor = GridBagConstraints.NORTH;
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 1.0;
            gbc.weighty = 1.0;
            gbc.insets = new Insets(10, 10, 10, 10);
            for (int x = 0; x < F.GRID_WIDTH; x++) {
                for (int y = 0; y < F.GRID_HEIGHT; y++) {
                    gbc.gridx = x;
                    gbc.gridy = y;
                    cp.add(new Card(), gbc);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class Card extends JPanel {
        public Card() {
            super();
            setBackground(new Color((int) (Math.random() * Integer.MAX_VALUE)));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(80, 80);
        }
    }

    public static void main(String[] args) {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    F f = new F();
                    f.setGui();
                    f.pack();
                    f.setVisible(true);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

  • 不,这也不是。我只是采用另一种方法来显示卡片,但感谢您的努力。
  • 那你能告诉我为什么这是错的吗?
猜你喜欢
  • 2019-10-11
  • 1970-01-01
  • 2016-08-29
  • 2017-12-11
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
相关资源
最近更新 更多