【问题标题】:GridBagLayout not honoring oblong shape requestGridBagLayout 不遵守长方形形状请求
【发布时间】:2014-08-31 03:40:38
【问题描述】:

我正在使用 swing 来尝试制作一个垄断板。我正在尝试将板上的属性/空间设置为单独的 JPanel,它们可以有自己的实现、信息等,但是我在空间的形状上遇到了一些问题。我正在使用 GridBagLayout(我对这个布局管理器相当陌生),并且我正在尝试布置面板,以便对于侧面 JPanel,gridwidth = 4,gridheight = 3(参见附加代码)。但是,当我运行它并查看它时,面板是方形的。我确认当我将 gridheight 更改为 2 或 1 时这不起作用,它仍然显示为正方形(我希望 JPanel 的形状更加椭圆形)。

请原谅命名方案,我只是在 Eclipse 中的一个单独的临时项目文件中尝试此布局,然后在我的主要垄断程序中实现 gui。

import static java.awt.GridBagConstraints.*;

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

import javax.swing.*;
import javax.swing.border.*;

public class MainFrame extends JFrame {

    private static final long serialVersionUID = 1L;




    public MainFrame() {
        super();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        Dimension screenSize = getToolkit().getScreenSize();
        setSize(screenSize.height, screenSize.height);

        setLocationRelativeTo(null);

        setLayout(new GridBagLayout());

        addCorners();

        addEdges();
        setVisible(true);

        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                System.out.println("Component resized");
                int width = getWidth();
                int height = getHeight();
                System.out.println(width + " " + height);
                super.componentResized(e);
            }
        });
    }

    private int startingColRow = 4;
    private int endingColRow = 28;

    private int bigWidth = 4;
    private int smallWidth = 3;

    private int startingEdge = 0;
    private int endingEdge = 31;




    private void addEdges() {
        addLeftEdge();
        addTopEdge();
        addBottomEdge();
        addRightEdge();
    }




    private void addCorners() {
        addTopLeftCorner();
        addBottomLeftCorner();
        addTopRightCorner();
        addBottomRightCorner();

    }




    private void addCorner(int anchor, int gridx, int gridy) {
        add(getWhiteJPanel(), getGridBagConstraints(anchor, gridx, gridy, bigWidth, bigWidth));
    }




    private void addBottomRightCorner() {
        addCorner(SOUTHEAST, endingEdge, endingEdge);
    }




    private void addTopRightCorner() {
        addCorner(NORTHWEST, endingEdge, startingEdge);
    }




    private void addBottomLeftCorner() {
        addCorner(SOUTHWEST, startingEdge, endingEdge);
    }




    private void addTopLeftCorner() {
        addCorner(NORTHEAST, startingEdge, startingEdge);
    }




    public void addLeftEdge() {
        for (int row = startingColRow; row <= endingColRow; row += smallWidth) {
            add(getWhiteJPanel(), getGridBagConstraints(WEST, startingEdge, row, bigWidth, smallWidth));
        }
    }




    public void addRightEdge() {
        for (int row = startingColRow; row <= endingColRow; row += smallWidth) {
            add(getWhiteJPanel(), getGridBagConstraints(EAST, endingEdge, row, bigWidth, smallWidth));
        }
    }




    public void addBottomEdge() {
        for (int col = startingColRow; col <= endingColRow; col += smallWidth) {
            add(getWhiteJPanel(), getGridBagConstraints(SOUTH, col, endingEdge, smallWidth, bigWidth));
        }
    }




    public void addTopEdge() {
        for (int col = startingColRow; col <= endingColRow; col += smallWidth) {
            add(getWhiteJPanel(), getGridBagConstraints(NORTH, col, startingEdge, smallWidth, bigWidth));
        }
    }




    private static JPanel getWhiteJPanel() {
        JPanel panel = new JPanel();
        panel.setBackground(Color.WHITE);
        panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        return panel;
    }




    private GridBagConstraints getGridBagConstraints(int anchor, int gridx, int gridy, int gridwidth, int gridheight) {
        GridBagConstraints c = new GridBagConstraints();
        c.fill = VERTICAL;
        c.weightx = c.weighty = 1;

        c.anchor = anchor;
        c.gridx = gridx;
        c.gridy = gridy;
        c.gridwidth = gridwidth;
        c.gridheight = gridheight;

        return c;
    }




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

【问题讨论】:

  • 为了尽快获得更好的帮助,请直接在问题中发布MCVE(最小完整和可验证示例)。外部链接过时了,大多数人不会关注它们。
  • 源代码中的一个空白行总是就足够了。 { 之后或 } 之前的空行通常也是多余的。
  • @Andrew:我不知道如何使这个示例成为 MCVE。另外,我知道一行就足够了,但是我试图跟上 Clean Code 的建议(书),即尽可能少地编写函数,我发现添加额外的空间(虽然对某些人来说很难看)对我有帮助挑出什么是函数,什么是成员,内部类等。下次我发布SO时我会更改格式。

标签: java swing layout-manager gridbaglayout


【解决方案1】:

我对你的c.fill = VERTICAL 有点困惑,我以为BOTH。除此之外,如果窗口是方形的,则棋盘将具有方形字段,如果窗口是椭圆形的,则面板将具有椭圆形字段。 Gridwidth 和 grigheight 在这里完全无关紧要。相反,如果您希望对象的区域在其中一个轴上重叠,则可以使用这些。最好将网格包布局视为一个大网格。然后 gridwidth 和 gridheight 告诉布局给定对象应该占据多少列或行。但是没有什么可以说列应该和行一样高。事实上,没有什么可以说行或列具有相同的大小。所以我想说你对 GridBagLayout 的运作方式有一些错误的想法。

如果您想固定纵横比,您应该为各个窗格设置首选尺寸,然后将整个板打包到滚动视图中。这将确保所有内容都以首选大小显示。不过,不确定在您的情况下滚动是否是个好主意。如果没有,您可以尝试使用适当布局的外部容器,这将允许内部容器增长到其首选大小并且不会更大。

【讨论】:

  • 对于纵横比,特别是对于一个JPanel,setPreferredSize()和setSize()有什么区别?
  • @ConnerPike:你打电话给setPreferredSize 告诉组件它应该有多大的尺寸。当被问及它的首选大小时,组件会告诉布局管理器,布局管理器将计算一些布局,然后调用setSizesetPosition。你的代码不应该调用setSize,除非你正在实现一个布局管理器,或者至少禁用了相关容器的所有布局管理器,否则你会干扰它。请注意,许多组件会根据其内容给出一个很好的首选大小,而不需要setPreferredSize
  • 我是否正确地假设 setSize() 只需要为顶级容器(JFrame、JDialog 等)调用?
  • @ConnerPike:是的,通常你只会为顶层窗口调用 setSize。
【解决方案2】:

您确定要使用GridBagLayout 吗?也许如果你看 MigLayout's 解决方案你会改变主意。

package com.zetcode;

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;

/*
 * This program creates a Monopoly board using
 * the MigLayout manager.
 *
 * Author Jan Bodnar
 * Website zetcode.com
 * Last modified: July 2014
 */

public class MigLayoutMonopoly extends JFrame {

    public MigLayoutMonopoly() {

        initUI();

        setTitle("Monopoly");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        setLayout(new MigLayout("fill, gap 2 2"));

        // top row of panels
        add(createPanel2());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel2(), "wrap");

        // left column of panels
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel3(), "wrap");
        add(createPanel2());

        // bottom row of panels
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel1());
        add(createPanel2());

        // right column of panels
        add(createPanel3(), "cell 10 1");
        add(createPanel3(), "cell 10 2");
        add(createPanel3(), "cell 10 3");
        add(createPanel3(), "cell 10 4");
        add(createPanel3(), "cell 10 5");
        add(createPanel3(), "cell 10 6");
        add(createPanel3(), "cell 10 7");
        add(createPanel3(), "cell 10 8");
        add(createPanel3(), "cell 10 9");

        // center panel
        add(createPanel2(), "cell 1 1 9 9, grow");

        pack();
    }

   public JPanel createPanel1() {
        JPanel pnl = new JPanel(){ 

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

            @Override
            public Dimension getMinimumSize() {
                return getPreferredSize();
            }            

        };

        pnl.setBorder(BorderFactory.createEtchedBorder());
        return pnl;
    }    

   public JPanel createPanel2() {
        JPanel pnl = new JPanel(){ 

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

            @Override
            public Dimension getMinimumSize() {
                return getPreferredSize();
            }                  

        };

        pnl.setBorder(BorderFactory.createEtchedBorder());
        return pnl;
    }   

   public JPanel createPanel3() {
        JPanel pnl = new JPanel(){ 

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

            @Override
            public Dimension getMinimumSize() {
                return getPreferredSize();
            }                  

        };

        pnl.setBorder(BorderFactory.createEtchedBorder());
        return pnl;
    }      


    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutMonopoly ex = new MigLayoutMonopoly();
                ex.setVisible(true);
            }
        });
    }
}

MigLayout具有强大的网格结构,我们可以在其中相对放置组件 或使用绝对单元格索引。

这取决于要求,但我认为板面板不应收缩 因为它们要包含位图。 (也许容器应该有固定的尺寸。)因此,我将面板的首选尺寸设置为最小尺寸——面板不会收缩,而是从面板上切割下来。此外,当容器增长时,面板不会 增长,但面板之间的差距。所有这些都可以根据自己的需要进行设置。

【讨论】:

    猜你喜欢
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 2017-08-25
    相关资源
    最近更新 更多