簡體   English   中英

SpringLayout問題/挑戰

[英]SpringLayout problem/challenge

據說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();
}

}

更新/結論

到現在已經24小時了,反響勢不可擋。 單獨的響應(感謝Camickr!)甚至沒有嘗試觸摸SpringLayout。 我認為這不是在SO社區而是在SpringLayout的實用程序上反映不佳!

我的印象是SpringLayout是布局管理器的紅發繼子,在某些方面很有用,但很少使用,以至於沒有人有工作經驗,也沒有人願意向Sun報告錯誤。

對我來說,事實證明GroupLayout可以完成我所需的一切,並允許我以合理的編碼量准確地完成我想要的事情。 對GridBagLayout而言,這是一個可喜的變化,從一開始我就很清楚我需要采取的步驟以實現預期的布局,而我只需要坐下來編寫代碼。

對於任何關心的人,這些都是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);
    }
}

您需要設置容器的約束(框架的內容窗格),更確切地說是其約束的東邊和南邊。 閱讀有關此內容的教程:
http://java.sun.com/docs/books/tutorial/uiswing/layout/spring.html
SpringDemo3解釋了所有這些

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM