【问题标题】:How would I position a JComponent to true center in a BorderLayout?如何将 JComponent 定位到 BorderLayout 中的真正中心?
【发布时间】:2015-09-01 02:45:22
【问题描述】:

我正在开发一个 Swing 应用程序,使用 BorderLayout 来定位组件。由于BorderLayout.CENTER 将组件定位到放置其他组件后剩下的任何位置,而这一事实使我的 GUI 看起来很奇怪,我想知道是否有办法将组件定位到 true 中心,而不是比在两边之间。由于BorderLayout 空格使组件填满整个空间,我猜测解决方案是将组件包装到JPanel 中。但是,如果您在另一侧有组件,则将组件定位到此面板的中心将使组件比另一侧更靠近另一侧。我该如何解决这个问题?

这些图片展示了问题和理想的解决方案;灰色边框代表主框架的BorderLayout.SOUTH(包裹在JPanel 中)。黑色方块代表正在抛弃中心组件的组件。红色方块代表需要居中的组件。

问题:

理想的解决方案:

【问题讨论】:

  • 问题图像在我看来更加平衡和合乎逻辑。例如,如果栗色矩形是宽度的两倍,会发生什么?在“理想解决方案”中,它将与左侧的黑色矩形重叠。
  • 我建议您创建自己的 LayoutManager 实现。简单实现java.awt.LayoutManagerjava.awt.LayoutManager2,重点实现layoutContainer方法在你的JPanel中布局所有组件。
  • @AndrewThompson Swing 架构根本不允许这样做。这来自 LayoutManager java doc“Swing 的绘画架构假定 JComponent 的子级不重叠”。除非您使用 isOptimizedDrawingEnabled 创建自己的组件以返回 false,否则您还可以制作自己的 LayoutManager。
  • @AndrewThompson 图片被夸大以显示效果。在我的应用程序(和其他应用程序)中,正方形有更大的空间。
  • "..图片被夸大了" 所以?我最小化了我的示例以适应显示的确切图像。替换为三重或四重,原始规范完全一样有意义(没有,对于那些还没有看到它的人)。

标签: java swing border-layout


【解决方案1】:

正如我看到的问题,为了使红色组件居中,左右组件的大小必须相等。

您也许可以使用Relative Layout

RelativeLayout 将允许您使右/左组件的大小相同,同时将中心组件保持在其首选大小。随着框架的大小调整,空间将从右/左组件中添加/删除。

例如:

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

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        JPanel left = new JPanel( new FlowLayout(FlowLayout.LEFT) );
        JPanel leftBox = new JPanel();
        leftBox.setPreferredSize( new Dimension(200, 50) );
        leftBox.setBackground( Color.BLACK );
        left.add( leftBox );

        JPanel center = new JPanel( new FlowLayout(FlowLayout.CENTER) );
        JPanel centerBox = new JPanel();
        centerBox.setPreferredSize( new Dimension(50, 50) );
        centerBox.setBackground( Color.RED );
        center.add( centerBox );

        JPanel right = new JPanel( new FlowLayout(FlowLayout.RIGHT) );
        JPanel rightBox = new JPanel();
        rightBox.setPreferredSize( new Dimension(50, 50) );
        rightBox.setBackground( Color.BLACK );
        right.add( rightBox );

        setLayout( new RelativeLayout(RelativeLayout.X_AXIS, 5) );
        add(left, new Float(1));
        add(center);
        add(right, new Float(1));
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

相对布局的一个问题是,当您打包框架时,组件将显示得太小,因为首选尺寸只是组件的总和。所以左边的面板会被截断。

在上面的示例中,您可以添加以下内容来解决此问题:

right.add( rightBox );
right.setPreferredSize( left.getPreferredSize() ); // added

另一个选项可能是使用OverlayLayout,它可以设置为在包含其他两个组件的面板上方显示红色面板:

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

public class SSCCE extends JPanel
{
    public SSCCE()
    {
        JPanel left = new JPanel( new FlowLayout(FlowLayout.LEFT) );
        JPanel leftBox = new JPanel();
        leftBox.setPreferredSize( new Dimension(200, 50) );
        leftBox.setBackground( Color.BLACK );
        left.add( leftBox );

        JPanel center = new JPanel( new FlowLayout(FlowLayout.CENTER) );
        center.setOpaque(false);
        JPanel centerBox = new JPanel();
        centerBox.setPreferredSize( new Dimension(50, 50) );
        centerBox.setBackground( Color.RED );
        center.add( centerBox );

        JPanel right = new JPanel( new FlowLayout(FlowLayout.RIGHT) );
        JPanel rightBox = new JPanel();
        rightBox.setPreferredSize( new Dimension(50, 50) );
        rightBox.setBackground( Color.BLACK );
        right.add( rightBox );

        JPanel main = new JPanel( new BorderLayout() );
        main.add(left, BorderLayout.LINE_START);
        main.add(right, BorderLayout.LINE_END);

        setLayout( new OverlayLayout(this) );
        add(center);
        add(main);
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new SSCCE());
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
    }
}

【讨论】:

    猜你喜欢
    • 2015-03-07
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    • 2022-12-07
    相关资源
    最近更新 更多