【问题标题】:Swing layout with miglayout and nested panels带有 miglayout 和嵌套面板的 Swing 布局
【发布时间】:2012-09-04 21:19:35
【问题描述】:

我有一个使用 SwingLayout 的 Swing 程序。 Swing 组件的结构如下所示。

JFrame
    JPanel (Cardlayout)
        JPanel (Miglayout) - Main panel
            Jpanel (Flowlayout) - Checkbox Panel
            JPanel (Flowlayout) - Option Panel

我现在的问题是我不确定如何防止复选框面板增长。我不希望它“推出”它在右侧的列。我希望 Wraplayout(在选项面板上工作正常)在复选框面板变得太大时包装它的内容。

这是 Eclipse 内的 Windowsbuilder GUI 的视图。带有“站点”标签的面板是复选框面板。复选框面板的右侧是选项面板。包含它们的大面板是主面板。 http://i.imgur.com/S7Njo.png

当我添加太多复选框时会发生这种情况 http://i.imgur.com/f2SZz.png

我的主要问题是我不明白为什么在主面板中的第一列的列约束上设置“增长 0”并不能阻止它在内部组件变得太大时增长,因为我添加了新的复选框站点面板(站点面板可以有任意数量的复选框)。

这是我的主面板miglayout。

mainPanel.setLayout(new MigLayout("", "[][grow]", "[][][][][][][][grow]"));

这是我添加复选框面板时的组件约束

siteCheckBoxPanel = new JPanel();
mainPanel.add(siteCheckBoxPanel, "cell 0 0,alignx left,gapx 0px,aligny center");
siteCheckBoxPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

我也尝试过不使用流布局,但这并不能解决任何问题。您能提供的任何见解都会很棒!如果人们有问题,我也很乐意提供更多信息。仅供参考,我还尝试在复选框面板所在的单元格的列和行约束上“增长 0”。

这是一个 SSCCE。您可以获取以下来源。您需要的唯一依赖项是 miglayout。您可以点击按钮添加复选框。

https://dl.dropbox.com/u/20614368/Test.java

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

import net.miginfocom.swing.MigLayout;


public class Test extends JFrame {


    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            private Test frame;

            public void run() {
                try {
                    frame = new Test();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private JPanel contentPane;
    private JPanel mainPanel;
    private JPanel optionPanel;
    private JButton btnUploadImages;
    private JLabel thumbnailLabel;
    private JTextArea textArea;
    private JPanel checkboxPanel;
    private final Action action = new SwingAction();

    /**
     * Create the frame.
     */
    public Test() {
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 1098, 846);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(new CardLayout(0, 0));

        mainPanel = new JPanel();
        mainPanel.setName("");
        contentPane.add(mainPanel, "name_329556913535654");
        mainPanel.setLayout(new MigLayout("", "[][grow]", "[][][][][][][][grow]"));


        JLabel lblPicture = new JLabel("Picture");
        mainPanel.add(lblPicture, "cell 0 1");

        optionPanel = new JPanel();
        optionPanel.setBackground(Color.red);
        mainPanel.add(optionPanel, "cell 1 0 1 5,grow");

        btnUploadImages = new JButton("Upload Images");
        btnUploadImages.setAction(action);

        thumbnailLabel = new JLabel("");
        mainPanel.add(thumbnailLabel, "cell 0 4");

        textArea = new JTextArea();
        mainPanel.add(btnUploadImages, "cell 0 6");

        checkboxPanel = new JPanel();
        checkboxPanel.setBackground(Color.green);
        mainPanel.add(checkboxPanel, "flowx,cell 0 0");

        JLabel lblSites = new JLabel("Sites");
        checkboxPanel.add(lblSites);


    }
    private class SwingAction extends AbstractAction {
        public SwingAction() {
            putValue(NAME, "Add checkbox");
            putValue(SHORT_DESCRIPTION, "Some short description");
        }
        public void actionPerformed(ActionEvent e) {
            JCheckBox box = new JCheckBox();
            box.setName("Foobar!");
            checkboxPanel.add(box);
            contentPane.validate();
            contentPane.repaint();
        }
    }
}

【问题讨论】:

  • 虽然我完全理解您的意思,但如果您提供 [sscce.org/](SSCCE),则提供有效的解决方案会更容易。

标签: java swing miglayout flowlayout


【解决方案1】:

理论上,您的设置应该按预期工作 - 只要您告诉布局

  • 使第一列不超过最大值,f.i。通过将最大值设置为百分比
  • 不收缩其首选项 f.i 下的 optionPanel 列通过在列约束中将 min 设置为 pref

列约束示例:

// first column - restrict max  
"[grow, fill, n:pref:30%]" +
// second column - restrict min 
"[grow, pref:pref:n]" 

实际上,无论有什么限制,我都无法让 FlowLayout 和 MigLayout 很好地协同工作:即使是初始布局也被破坏了(例如 optionPanel 被推离了框架宽度)。将 FlowLayout 替换为 Rob's WrapLayout 看起来更好,虽然不是完全最佳,因为盒子没有完全对齐。

/*
 * Created on 12.09.2012
 *
 */
package layout;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;

import net.miginfocom.swing.MigLayout;

public class MigLayoutNested extends JFrame {


    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            private MigLayoutNested frame;

            public void run() {
                try {
                    frame = new MigLayoutNested();
                    frame.pack();
//                    frame.setSize(frame.getWidth(), frame.getHeight()* 2);
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private JPanel contentPane;
    private JPanel mainPanel;
    private JPanel optionPanel;
    private JButton btnUploadImages;
    private JLabel thumbnailLabel;
    private JTextArea textArea;
    private JPanel checkboxPanel;
    private final Action action = new SwingAction();

    /**
     * Create the frame.
     */
    public MigLayoutNested() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        contentPane = (JPanel) getContentPane(); //new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new CardLayout(0, 0));

        mainPanel = new JPanel();
        contentPane.add(mainPanel, "name_329556913535654");

        mainPanel.setLayout(new MigLayout("debug", 
                "[grow, fill][grow, pref:pref:n]" 
               , "[grow, fill][][][][][][][grow]"
                ));

        // stand-in to simulate a row-spanning all-growing component
        optionPanel = new JPanel();
        ((FlowLayout) optionPanel.getLayout()).setAlignment(JLabel.RIGHT);
        JLabel option = new JLabel("just some label so we see the trailing corner, long enough");
        optionPanel.add(option);
        optionPanel.setBackground(Color.YELLOW);
        mainPanel.add(optionPanel, "cell 1 0 1 5, grow");

        // the panel to dynamically add components to  
        // expected behaviour is to wrap on revalidate if needed
        // not working with FlowLayout, but looks half-way fine
        // with Rob's WrapLayout
        checkboxPanel = new JPanel(new WrapLayout()); 
        checkboxPanel.setBackground(Color.green);
        JLabel lblSites = new JLabel("Sites");
        checkboxPanel.add(lblSites);
        mainPanel.add(checkboxPanel, "cell 0 0");

        JLabel lblPicture = new JLabel("Picture");
        mainPanel.add(lblPicture, "cell 0 1");

        thumbnailLabel = new JLabel("thumb");
        mainPanel.add(thumbnailLabel, "cell 0 3");
        textArea = new JTextArea(10, 10);
        mainPanel.add(textArea, "cell 0 4");

        btnUploadImages = new JButton("Upload Images");
        btnUploadImages.setAction(action);
        mainPanel.add(btnUploadImages, "cell 0 6");


    }
    private class SwingAction extends AbstractAction {
        public SwingAction() {
            putValue(NAME, "Add checkbox");
            putValue(SHORT_DESCRIPTION, "Some short description");
        }
        @Override
        public void actionPerformed(ActionEvent e) {
            JCheckBox box = new JCheckBox();
            box.setName("Foobar!");
            checkboxPanel.add(box);
            checkboxPanel.revalidate();
        }
    }
}

【讨论】:

  • 太棒了!这基本上是我想要的。我不得不通过更改代码中的列约束以匹配示例列约束来摆弄提供的代码。这是我修改后的 mainPanel 布局以匹配您提供的列约束后的样子。 mainPanel.setLayout(new MigLayout("debug", "[grow, fill, n:pref:20%][grow, pref:pref:n]" , "[grow, fill][][][][][ ][][成长]"));
  • 在将左对齐常量添加到 WrapLayout 构造函数后,我还能够让它们很好地对齐。可以在这里看到效果imgur.com/uLggocheckboxPanel = new JPanel(new WrapLayout(WrapLayout.LEFT));
  • 很高兴你做到了 :-) 就我个人而言,我希望所有复选框都对齐,即使是第一行中的复选框。但这超出了简单 LayoutManager 的范围。可惜 Mig 不支持包装(或者也许只有我没有找到那个选项..)
  • 我可以通过将“站点”标签放在复选框上方的单元格中来对齐所有内容。在我的程序代码中,我最终使用了未选择图像和未选择缩略图的像素长度作为最大值,现在它很完美!此外,Miglayout 不支持包装或包装在单个单元格中,并且可能永远不会:( 尽管这似乎是一个非常有用的功能。stackoverflow.com/questions/5715833/…
猜你喜欢
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 2022-07-24
  • 2020-04-05
  • 2020-12-21
相关资源
最近更新 更多