【问题标题】:Java Swing - Difficulty achieving desired layoutJava Swing - 难以实现所需的布局
【发布时间】:2013-03-14 17:09:12
【问题描述】:

我正在使用 Swing 在 Java 中编写 GUI。目前,我正在尝试创建一个“模块”(一个黄色块),它的左右边缘都有一个小部件支架(黑条)。每个持有人将持有几个我想在垂直线上显示的小块。这是一张图片:

示例模块:

我希望能够将洋红色/青色块均匀地分布在小部件支架上。

我查看了一些关于 Swing 的教程,并尝试将小部件持有者的布局实现为 GridLayout 和 BoxLayout,但都没有运气。单列 GridLayout 似乎是这里的自然选择,但我似乎无法让它工作,即使我编写了正确使用网格的小型测试程序。

布局管理器在简单的示例中工作,但在这个稍微复杂的程序中却没有,这让我感到困惑。

在我的程序中,

  • 模块是一个JPanel
  • 小部件支架/黑条也是 JPanel
  • 小部件本身(青色/洋红色块)目前是 JPanel,但我也尝试将它们作为 JLabels 和 JButton。我只是希望他们能够监听鼠标事件并拥有一个区域和颜色。

顺便说一句,我在模块本身的布局上也遇到了问题,无法将小部件支架放置在左侧和右侧。我尝试使用水平 BoxLayout(支架、水平胶水、支架),还有一次我尝试使用 BorderLayout(对任一支架使用 EAST/WEST),但无论我做什么,支架都不会让步 - 就像我一样不想,我用 setBounds() 来定位它们。

模块类(小部件持有者是 inputLine 和 outputLine):

public class Module extends JPanel
{
private static final int MOD_WIDTH  = 86;
private static final int MOD_HEIGHT = 60;

private int screenX, screenY, myX, myY;

private boolean moving = false;

// figure out the layout !
private JPanel inputLine, outputLine;

public Module()
{
    //super(new BorderLayout());

    initPanel();
    initWidgets();
    initMouse();

    setLayout(null);

    list();
}

private final void initPanel()
{
    this.setSize(new Dimension(MOD_WIDTH, MOD_HEIGHT));
    this.setBackground(Color.ORANGE);
}

private void initWidgets()
{
    inputLine   = new JPanel(new GridLayout(0, 1, 5, 5));
    outputLine  = new JPanel(new GridLayout(0, 1, 5, 5));

    inputLine.setBounds (0, 0, 18, 60);
    outputLine.setBounds(68, 0, 18, 60);

    this.add(inputLine);
    this.add(outputLine);

    /* adding IOWidgets to test */
    inputLine.add(new InputWidget());
    inputLine.add(new InputWidget());
    inputLine.add(new InputWidget());

    outputLine.add(new OutputWidget());
    outputLine.add(new OutputWidget());
    outputLine.add(new OutputWidget());
    outputLine.add(new OutputWidget());

    inputLine.setBackground(Color.BLACK);
    outputLine.setBackground(Color.BLACK);
}


这是两种类型的小部件(输入[洋红],输出[青色])派生的抽象 IOWidget 类。稍后会添加功能。

public abstract class IOWidget extends JLabel
{   

    private static final int EDGE_SIZE = 8;

    public IOWidget()
    {
        this.setSize(new Dimension(EDGE_SIZE, EDGE_SIZE));
    }
}


这是 InputWidget 类。目前,在我添加额外功能之前,它与 OutputWidget 相同,所以我只发布这个:

public class InputWidget extends IOWidget
{
    public InputWidget()
    {
        this.setBackground(Color.MAGENTA);
    }
}


在我的应用程序中,模块被添加到更大的 JPanel。我希望模块的布局独立于它如何添加到另一个 JComponent,因此我将省略其余代码。

这是程序运行时的样子:

为了完整起见,这里是单个模块上调用列表的输出:

rhopkins.honors.Dataflow.Module[,0,0,86x60,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
 javax.swing.JPanel[,0,0,18x60,invalid,layout=java.awt.GridLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
  rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
  rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
  rhopkins.honors.Dataflow.InputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
 javax.swing.JPanel[,68,0,18x60,invalid,layout=java.awt.GridLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
  rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
  rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
  rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]
  rhopkins.honors.Dataflow.OutputWidget[,0,0,8x8,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=java.awt.Dimension[width=8,height=8]]

我非常想知道我做错了什么。另外,我知道我是 Swing 和 GUI 开发的新手,因此欢迎对样式/约定/任何内容提出任何批评。

【问题讨论】:

  • 这是一个包含 10 个组件的复杂布局。根据您的描述,您似乎做得正确。如果没有一段简短、独立、正确、可运行的代码,恐怕我无法为您提供进一步的帮助。
  • 嗯。我刚刚写了一个小小的 Tester 类,它只是扩展了 JFrame,创建了一个新模块并添加了它。在这种情况下,模块按照我想要的方式自行格式化。另外,我注意到当我最小化窗口并将其重新打开时,模块会正确显示自己。所以我想这只是重新粉刷或重新验证的问题。

标签: java swing layout jpanel


【解决方案1】:

不要使用空布局。

您的主面板应该是 BorderLayout。您可以将小部件持有者添加到主面板的 WEST 和 EAST。

小部件面板应该能够使用垂直 BoxLayout。您需要在添加到面板的每个小部件之前/之后添加胶水。由于 BoxLayout 尊重组件的大小,因此您需要覆盖 getPreferredSize()、getMinimumSize() 和 getMaximumSize() 方法以返回相同的值。这样,面板中的任何额外空间都应在您添加的胶水之间平均分配。

【讨论】:

  • 谢谢,我不想使用空布局,但我使用了它,因为它似乎是“强制”它工作的唯一方法。我只是将其恢复为 BorderLayout,并且效果很好(在我解决了潜在问题之后)!另外,感谢您对盒子布局的建议 - 它非常完美!这样我就不必处理边界或任何事情。
  • 确保接受这个(和任何其他)回答这个(或任何其他)stackoverflow 问题的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 2018-06-25
  • 2013-09-25
  • 2012-01-29
  • 2019-04-04
  • 2018-05-03
  • 2014-12-20
相关资源
最近更新 更多