Java SpringLayout问题/挑战

Java SpringLayout问题/挑战,java,swing,layout,Java,Swing,Layout,SpringLayout据说非常强大。我试图用SpringLayout实现我认为相当简单的布局,但我失败了 减少到最低限度,我希望我的JFrame上有4个并排的JButton: *=====================* | +--+ +--+ +--+ +--+ | | |b1| |b2| |b3| |b4| | | +--+ +--+ +--+ +--+ | *=====================* 我希望所有4个有相同的大小,而不管不同的文本 我希望最外层的(b1和b4)与容器

SpringLayout据说非常强大。我试图用SpringLayout实现我认为相当简单的布局,但我失败了

减少到最低限度,我希望我的JFrame上有4个并排的JButton:

*=====================*
| +--+ +--+ +--+ +--+ |
| |b1| |b2| |b3| |b4| |
| +--+ +--+ +--+ +--+ |
*=====================*
我希望所有4个有相同的大小,而不管不同的文本

我希望最外层的(b1和b4)与容器的边界保持5 px的恒定水平距离,与按钮的北部和南部保持5 px的边界,所有按钮的高度相同

我希望按钮之间的间隙也是5像素

到目前为止,很容易。我有更多的限制:

  • 当框架变宽(用户/鼠标)时,我希望按钮(b1/b2、b2/b3、b3/b4)之间的间隙变宽,而不是按钮

  • 如果框架变小了,我希望在其他东西让路之前,按钮之间的间隙缩小到1或0

  • 我希望框架上有一个
    pack()
    ,为按钮提供一个大小刚好合适的窗口,默认为5px间距,周围有5px边框

我编写了以下相当简单的代码,结果非常糟糕。间隙不会缩小,并且仅在最右边的按钮(b4)上发生膨胀

现在,我有了可以统一调整大小的自定义按钮,我可以用GridBagLayout很容易地满足这些要求,用MigLayout可能更容易。这不是我想要的答案。具体来说,我的问题是:

能否使用SpringLayout使此布局正常工作?怎么做?

布局甚至忽略了我的按钮“
getMaximumSize()
。我是做错了什么还是SpringLayout被窃听了

非常感谢

public class SpringLayoutTest extends JFrame {

public SpringLayoutTest() {
  setLocation(100,100);
  setSize(400, 300);
  Container cp = getContentPane();
  SpringLayout layout = new SpringLayout();
  cp.setLayout(layout);

  SiblingButton b1, b2, b3, b4;
  cp.add(b1 = new SiblingButton("..."));
  cp.add(b2 = new SiblingButton("iii"));
  cp.add(b3 = new SiblingButton("xxx"));
  cp.add(b4 = new SiblingButton("WWW"));

  layout.putConstraint(NORTH, b1, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b1, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b2, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b2, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b3, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b3, Spring.minus(Spring.constant(5)), SOUTH, cp);
  layout.putConstraint(NORTH, b4, 5, NORTH, cp);
  layout.putConstraint(SOUTH, b4, Spring.minus(Spring.constant(5)), SOUTH, cp);

  layout.putConstraint(WEST, b1, 5, WEST, cp);
  layout.putConstraint(WEST, b2, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b1);
  layout.putConstraint(WEST, b3, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b2);
  layout.putConstraint(WEST, b4, Spring.constant(1, 5, Integer.MAX_VALUE), EAST, b3);

  layout.putConstraint(EAST, b4, Spring.minus(Spring.constant(5)), EAST, cp);

  layout.putConstraint(WEST, cp, Spring.minus(Spring.constant(5)), WEST, b1);
}

public static void main(String[] args) {
  (new SpringLayoutTest()).setVisible(true);
}
SiblingButton是一个非常自然的实现。请忽略它的设计缺陷,这只是为了演示

class SiblingButton extends JButton {

static ArrayList<SiblingButton> siblings = new ArrayList<SiblingButton>();

public SiblingButton(String text) {
  super(text);
  siblings.add(this);
}

public Dimension getMaximumSize() {
  return getPreferredSize();
}

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

public Dimension getPreferredSize() {
  Dimension mx = new Dimension(0, 0);
  for (SiblingButton sb : siblings) {
     mx = new Dimension(Math.max(mx.width, sb.originalPreferredSize().width), 
           Math.max(mx.height, sb.originalPreferredSize().height));
  }
  return mx;
}

Dimension originalPreferredSize() {
  return super.getPreferredSize();
}

}
类同级按钮扩展JButton{
静态ArrayList同级=新ArrayList();
公共同级按钮(字符串文本){
超级(文本);
兄弟姐妹。添加(此);
}
公共维度getMaximumSize(){
返回getPreferredSize();
}
公共维度getMinimumSize(){
返回getPreferredSize();
}
公共维度getPreferredSize(){
维度mx=新维度(0,0);
对于(兄弟姐妹按钮sb:兄弟姐妹){
mx=新尺寸(数学最大值(mx.width,sb.originalPreferredSize().width),
max(mx.height,sb.originalPreferredSize().height));
}
返回mx;
}
标注原始参考尺寸(){
返回super.getPreferredSize();
}
}

更新/结论 到现在已经24小时了,人们的反应令人难以置信。唯一的回应(谢谢你,卡米克!)甚至都没有触及SpringLayout。我不认为这反映的不是SO社区,而是SpringLayout的实用性

我的印象是SpringLayout是布局经理的红发继子,在某些方面很有用,但利用率很低,以至于没有人有使用它的工作经验,也没有人费心向Sun报告bug

对我来说,结果证明GroupLayout做了我需要的一切,并允许我用合理的编码量完全完成我想要的。GridBagLayout的一个值得欢迎的变化,我需要采取的步骤,以实现我的预期布局,从一开始我就很清楚,我只需要坐下来写代码

对于任何关心GroupLayout的人来说,以下是GroupLayout的特点,这些特点使它对我非常有用:

  • 水平方向和垂直方向的布局或多或少是分开进行的。大量的灵活性和更简单的代码
  • 可以嵌套网格,而不需要引入容器来容纳布局
  • 可以插入具有指定约束的间隙
  • 可以形成具有共享尺寸规格的任意组件组,即所有组件的尺寸与组中最大组件的尺寸相同;及
  • 可以改变组件的大小(例如,maximumSize=preferredSize),而无需对组件进行子类化

您可以使用BoxLayout:

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

public class BoxExample extends JFrame
{
    public BoxExample()
    {
        Box box = Box.createHorizontalBox();
        box.setBorder( new EmptyBorder(5, 5, 5, 5) );
        Dimension size = new Dimension(100, 25);

        box.add( createButton("Button1", size) );
        box.add( createStrut() );
        box.add( createButton("Button2", size) );
        box.add( createStrut() );
        box.add( createButton("Button3", size) );
        box.add( createStrut() );
        box.add( createButton("Button4", size) );

        add( box );
    }

    private JButton createButton(String text, Dimension size)
    {
        JButton button = new JButton(text);
        button.setPreferredSize( size );
        button.setMinimumSize( size );
        button.setMaximumSize( size );
        return button;
    }

    private Component createStrut()
    {
        JComponent component = (JComponent)Box.createHorizontalStrut(5);
        component.setMinimumSize(new Dimension(0, 0));
        component.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
        return component;
    }

    public static void main(String[] args)
    {
        BoxExample frame = new BoxExample();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

您可以使用BoxLayout:

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

public class BoxExample extends JFrame
{
    public BoxExample()
    {
        Box box = Box.createHorizontalBox();
        box.setBorder( new EmptyBorder(5, 5, 5, 5) );
        Dimension size = new Dimension(100, 25);

        box.add( createButton("Button1", size) );
        box.add( createStrut() );
        box.add( createButton("Button2", size) );
        box.add( createStrut() );
        box.add( createButton("Button3", size) );
        box.add( createStrut() );
        box.add( createButton("Button4", size) );

        add( box );
    }

    private JButton createButton(String text, Dimension size)
    {
        JButton button = new JButton(text);
        button.setPreferredSize( size );
        button.setMinimumSize( size );
        button.setMaximumSize( size );
        return button;
    }

    private Component createStrut()
    {
        JComponent component = (JComponent)Box.createHorizontalStrut(5);
        component.setMinimumSize(new Dimension(0, 0));
        component.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
        return component;
    }

    public static void main(String[] args)
    {
        BoxExample frame = new BoxExample();
        frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }
}

您需要设置容器(框架的内容窗格)的约束,更准确地说,设置其东面和南面的约束。 阅读有关此的教程:


SpringDemo3解释了这一切

您需要设置容器(框架的内容窗格)的约束,更精确地说,设置容器东面和南面的约束。 阅读有关此的教程:


SpringDemo3解释了这一切

不是答案,但您是否查看了TableLayout?TableLayout会比GBL更简单地满足我的要求,甚至可能是MigL-谢谢!我想使用SL的原因是GUI实际上有更多的功能,其他行中的组件将独立于这些按钮以列的形式排列,我不想推测它们将跨越多少列。当您希望在同一布局中使用不同的列宽时,这会迅速减少您的备选方案。我可能最终会使用嵌套容器。哦,我想要SpringLayout的另一个原因是:它是唯一一个允许我在不子类化按钮或直接修改其尺寸设置的情况下,通过那个时髦的spring算法,强制所有按钮具有相同的最小/首选/最大大小的布局。如果它像广告宣传的那样工作,那就太酷了。我的示例使用子类按钮只是为了简化我的spring twiddling代码。这不是答案,但您是否签出了TableLayout?TableLayout会比GBL更简单地满足我的要求,甚至可能是MigL-谢谢!我想使用SL的原因是GUI实际上有更多的功能,其他行中的组件将独立于这些按钮以列的形式排列,我不想推测它们将跨越多少列。当您需要不同的列宽时