我该如何在JFrame中让固定大小的JPanel居中显示?

17

大家好! 我正在尝试解决一个“显然”简单的问题,但是我无法解决它。 我正在使用Java/Swing库开发一个样例应用程序; 我有一个JFrame和一个JPanel。 我只想实现以下目标:

  1. JPanel 必须在JFrame中居中。

  2. JPanel 必须始终具有使用setPreferredSize()方法指定的大小。它不得调整为此大小以下。

我尝试使用GridBagLayout:这是我唯一能够做到的方式。

请见下面的示例:

/* file StackSample01.java */

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

public class StackSample01 {
    public static void main(String [] args) {

        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(100, 100));
        panel.setBackground(Color.RED);  

        frame.setLayout(new GridBagLayout());
        frame.add(panel, new GridBagConstraints());
        frame.setSize(new Dimension(200, 200));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
}

这里有一张截图:

我不会使用GridBagLayout来完成一件过于简单的事情。 我尝试了一个最简单的解决方案,使用了Box,但是没有效果:

示例代码:

/* file StackSample02.java */

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

public class StackSample02 {
    public static void main(String [] args) {

        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(100, 100));
        panel.setBackground(Color.RED); // for debug 

        panel.setAlignmentX(JComponent.CENTER_ALIGNMENT); // have no effect

        Box box = new Box(BoxLayout.Y_AXIS);

        box.add(Box.createVerticalGlue());
        box.add(panel);     
        box.add(Box.createVerticalGlue()); // causes a deformation

        frame.add(box);
        frame.setSize(new Dimension(200, 200));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
}

这里有一张截图,

有什么想法吗?感谢所有人 :-)


你尝试过使用BorderFactory类在“panel”周围放置边框吗?我对它不太熟悉,否则我会给出更具体的例子。 - Tony
1
“我不会使用GridBagLayout来处理过于简单的事情。”为什么不呢?虽然我非常不喜欢GBL,但对于这种情况,它是我首选的布局方式。 - Andrew Thompson
@Andrew - 完全同意,除了使用GBL,我永远不会用它 :-) 相反,我会选择三大工具之一Form、Mig、Design,无论哪个是个人最喜欢的。 - kleopatra
@kleopatra,你因为使用setXxxSize()而对答案进行了投票,能否请您提供一个正确的答案或一个指向正确答案的链接?我已经厌倦了看到你的“对于这个-1,对于那个-1”的评论。 - mostruash
@mostruash 提示:有一个“常见”选项卡..老实说,我已经厌倦了那些不费力寻找问题答案或投票理由(无论是赞同还是反对,都没有什么区别)的开发人员——毕竟,寻找东西是他们工作的本质。 - kleopatra
6个回答

16

BoxLayout可以很好地支持setXxxSize(),只需添加panel.setMaximumSize(new Dimension(100, 100));

这样您的输出会是:

通过setMinimumSize移除(如果容器具有更大的尺寸...)

图片描述 图片描述 图片描述

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

public class CustomComponent12 extends JFrame {

    private static final long serialVersionUID = 1L;

    public CustomComponent12() {
        Box box = new Box(BoxLayout.Y_AXIS);
        box.setAlignmentX(JComponent.CENTER_ALIGNMENT);
        box.add(Box.createVerticalGlue());
        box.add(new CustomComponents12());
        box.add(Box.createVerticalGlue());
        add(box);
        pack();
        setTitle("Custom Component Test / BoxLayout");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMaximumSize(getMinimumSize());
        setMinimumSize(getMinimumSize());
        setPreferredSize(getPreferredSize());
        setLocation(150, 150);
        setVisible(true);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                CustomComponent12 main = new CustomComponent12();
            }
        };
        javax.swing.SwingUtilities.invokeLater(r);
    }
}

class CustomComponents12 extends JPanel {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getMinimumSize() {
        return new Dimension(100, 100);
    }

    @Override
    public Dimension getMaximumSize() {
        return new Dimension(100, 100);
    }

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

    @Override
    public void paintComponent(Graphics g) {
        int margin = 10;
        Dimension dim = getSize();
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2);
    }
}

@kleopatra 有人可以读懂我的话外之意 :-) ,我很好奇(我们只谈论没有任何子组件的最深层JComponents),是否可能以另一种方式返回setXxxSize。 - mKorbel

6

首先,感谢大家。

我回答自己的问题,并展示我所做的选择。 请参考以下示例代码; 正如您所看到的,我仅包含了实现目标所需的最少步骤。

/* file StackResponse.java */

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

public class StackResponse {
    public static void main(String [] args) {

        JPanel panel = new JPanel();
        Dimension expectedDimension = new Dimension(100, 100);

        panel.setPreferredSize(expectedDimension);
        panel.setMaximumSize(expectedDimension);
        panel.setMinimumSize(expectedDimension);

        panel.setBackground(Color.RED); // for debug only

        Box box = new Box(BoxLayout.Y_AXIS);

        box.add(Box.createVerticalGlue());
        box.add(panel);     
        box.add(Box.createVerticalGlue());

        JFrame frame = new JFrame();
        frame.add(box);
        frame.setSize(new Dimension(200, 200));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setMinimumSize(frame.getMinimumSize());   // cannot be resized-

        frame.setVisible(true);

    }
}

这里可以看到一张截图。

问题已解决。 再次感谢所有人。

IT


2
使用GridBagLayout创建名为"FixedPanel"的面板,并将首选大小设置为框架大小,然后将您的框架添加到FixedPanel中。请保留HTML标记。
Frame = new JFrame("CenterFrame");         
Frame.setLocation(0, 0);
Frame.setSize(new Dimension(400,400));//dim

JPanel FixedPanel = new JPanel(new GridBagLayout());
FixedPanel.setPreferredSize(Frame.getSize());

JPanel myPanel = new JPanel();
myPanel.setPreferredSize(new Dimension(100,100));
myPanel.setBackground(Color.BLACK);

FixedPanel.add(myPanel);
Frame.add(FixedPanel);
Frame.setVisible(true);  

-1
你可以做到这一点。我曾经制作过一个国际象棋游戏,我希望棋子始终位于 JLayeredPane 单元格的中心位置:
private void formMouseReleased(java.awt.event.MouseEvent evt) {
    // TODO add your handling code here:
    if (jl != null)
    {
        jl.setLocation(evt.getX()+10, evt.getY()+10);
        Component com = findComponentAt(evt.getPoint());
        if (com instanceof JPanel)
        {
            // System.out.println("Yes, it's a jpanel");
            ((JPanel)com).add(jl);
            ((JPanel)com).validate();
        }
    }
}

-3

只是拥有

jPanel.setBounds(x, y, 1046, 503);

其中x是右侧的空间,y是左侧的空间。 您需要根据屏幕的高度和宽度计算两侧的空间。


-5

使用

panel.setMaximumSize(new Dimension(200,200));
panel.setResizable(false)

改为使用什么?


JPanel没有setResizable(boolean resizable)方法。 - IT.
1
-1 用于 setXXSize 和发明 API - 你知道如果你不知道答案是没有“义务”回答的吗?胡乱猜测绝对是错误的做法。 - kleopatra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接