如何更改 JFrame 中 JPanel 的大小?

Posted

技术标签:

【中文标题】如何更改 JFrame 中 JPanel 的大小?【英文标题】:How can I change the size of JPanels in a JFrame? 【发布时间】:2021-12-23 08:52:54 【问题描述】:

我有一个 JFrame,目前包含 4 个面板。其中一个面板是键盘,其他 3 个框架是键盘的控制面板,如下图所示:

我一直在尝试找到一种方法来使用 GridLayout 缩小控制面板的宽度,以便它们不会占用框架的整个宽度,但不幸的是我的代码无法正常工作。另外,我想将钢琴卷推到屏幕底部。到目前为止,这是我的代码:

JFrame frame = new JFrame(); 
JPanel container = new JPanel();
container.setSize(1000, 1000);
container.setLayout(new GridLayout(5,5));

// add control panels to JPanel
int y = 0;
for(int i =0; i < oscillators.length; ++i) 
  JPanel panel = new JPanel();
  panel.setSize(289, 100);
  panel.setBorder(Utils.WindowDesign.LINE_BORDER);
  panel.setLayout(null);
  container.add(oscillators[i]);
  y+=105;


// add keyboard to panel
keyboard = new PianoKeys(this);
keyboard.setFocusable(true);
container.add(keyboard);

// make frame visible
frame.setSize(1000, 1000);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setBackground(Color.WHITE);
frame.setLayout(new BorderLayout());
frame.add(container);
frame.setVisible(true);

有人可以向我解释为什么这不能按预期工作吗?我将控制面板的宽度设置为 289,并且我的网格包含 5 列和 5 行,所以我不确定为什么控制面板最终会扩展到整个宽度。感谢您提供的任何帮助!

【问题讨论】:

1) 以最小尺寸提供 ASCII 艺术或 GUI 的 预期 布局的简单绘图,如果给定更大的宽度和高度。 2) Edit 添加一个 minimal reproducible example 以表示您对 GUI 进行布局的最佳尝试。 一般提示:1) 不要使用null布局。 2) 避免调用setXXXSize 方法(其中XXX 可能代表各种事物,如无或MinimumPreferred)。布局管理器仅将它们作为建议,但更重要的是,GUI 中的组件和容器通常能够更好地自行确定这些尺寸。然后,当所有组件和容器都添加完毕后.. 3) 将 frame.setSize(1000, 1000); 替换为 frame.pack(); - 以获得正确的 GUI 大小。 差点忘了:GridLayout 通常不用作主 GUI 的主布局。我怀疑它的使用是这种情况下问题的核心,但在知道预期的布局之前无法推测更多。 【参考方案1】:

SetPreferredSize 通常用于布局协商。但是,在您的情况下,SetMaxSize 在面板上。

通常不要使用空布局。

JFrame 的默认布局管理器是 BorderLayout。这会将内容放大到 JFrame 的内容窗格。

我不确定 GridLayout 是否是您想要的。 GridBagLayout 还允许网格单元格合并。有些布局允许您将元素锚定到底部。在 GridBagLayout 中,可以使用 constraint 将小于单元格的组件与 SOUTH(底部)对齐。那将是一个差距。


一句话:

我赞成另一种编码风格,即拥有一个内部带有组件的 MyJFrame 类。并做:

public static void main(String[] args) 
    MyJFrame frame = new MyJFrame();
    SwingUtilities.invokeLater(() -> frame.setVisible());

这允许使用 GUI 设计器(=代码生成器),这可以节省大量实验,即使对于经验丰富的程序员也是如此。

【讨论】:

【参考方案2】:

有趣的问题。因此,我做了一些研究。

解决一个思路:从GridLayout切换到BoxLayout

引用文档:

“BoxLayout 类将组件放在单个行或列中。它尊重组件请求的最大尺寸,还允许您对齐组件。有关更多详细信息,请参阅如何使用 BoxLayout。” A Visual Guide to Layout Managers

简短示例:

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;


public class GridLayoutExample extends JFrame 

    GridLayoutExample()
        JPanel listPane = new JPanel();

        //listPane.setLayout(new GridLayout(5,0));
        listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
        this.add(listPane);

        for(int i = 0; i < 5; i++)
            JLabel imgLabel = new JLabel(generateImage(20 + 20 * i, 10 + 10 * i));

            listPane.add(imgLabel);
        

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
    

    public static void main(String[] args) 
        new GridLayoutExample();
    

    private static ImageIcon generateImage(int width, int height)
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        //create random image pixel by pixel
        for(int y = 0; y < height; y++)
            for(int x = 0; x < width; x++)
                int a = (int)(Math.random()*256); //alpha
                int r = (int)(Math.random()*256); //red
                int g = (int)(Math.random()*256); //green
                int b = (int)(Math.random()*256); //blue

                int p = (a<<24) | (r<<16) | (g<<8) | b; //pixel

                img.setRGB(x, y, p);
            
        
        return new ImageIcon(img);
    

您可以通过更改以下几行来比较 GridLayout 和 BoxLayout:

//listPane.setLayout(new GridLayout(5,0));
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));

显示差异 - GridLayout:

框布局:

我希望这会有所帮助。

随机图片生成致dyclas-s-room.com

【讨论】:

以上是关于如何更改 JFrame 中 JPanel 的大小?的主要内容,如果未能解决你的问题,请参考以下文章

JPanel 在调整 Jframe 大小之前不会更新

JAVA:如何调整JPanel的大小

如何将两个 JPanel 添加到中心的 JFrame?

JPanel 更改未在 Jframe 上显示

在 JFrame 上更改 JPanel 组件时无法显示它

调整JFrame大小后更新JFreeChart / JPanel