【问题标题】:Error while using group layout使用组布局时出错
【发布时间】:2014-10-14 14:22:44
【问题描述】:

代码:添加名称和描述(名称的组合框和描述的文本字段)

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.BoxLayout;


public class Sample extends JFrame {
private JPanel contentPane;
private JTextField textField;
private JTextField textField_1;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Sample frame = new Sample();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */
public Sample() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);

    JPanel panel = new JPanel();
    contentPane.add(panel, BorderLayout.CENTER);
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    JPanel panel_1 = new JPanel();
    panel.add(panel_1);

    GroupLayout group1 = new GroupLayout(panel_1);
    panel_1.setLayout(group1);
    group1.setAutoCreateGaps(true);
    GroupLayout.SequentialGroup hseq1 = group1.createSequentialGroup();
    GroupLayout.Group hg1 = group1.createParallelGroup(Alignment.TRAILING);
    GroupLayout.Group hg2 = group1.createParallelGroup();
    hseq1.addGroup(hg1);
    hseq1.addGroup(hg2);

    GroupLayout.SequentialGroup vseq1 = group1.createSequentialGroup();

    ArrayList<JLabel> labels = new ArrayList<>();
    ArrayList fields = new ArrayList();

    JLabel labelC = new JLabel("Name : ");
    labels.add(labelC);
    JComboBox<String> box = new JComboBox<>();
    fields.add(box);

    JLabel desc = new JLabel("Desc : ");
    labels.add(desc);

    JTextField descfield = new JTextField(20);
    fields.add(descfield);


    //Adding to the group
    for(int i=0; i<labels.size(); i++){
        hg1.addComponent(labels.get(i));
    }

    for(int i=0; i<fields.size(); i++){
        if(i==0){
            hg2.addComponent((JComboBox)fields.get(i));
        }
        else{
            hg2.addComponent((JTextField)fields.get(i));
        }
    }

    for(int i=0; i<labels.size(); i++){
        if(i==0){
            vseq1.addGroup(group1.createParallelGroup().addComponent(labels.get(i)).addComponent((JComboBox)fields.get(i)));
        }
        else{
            vseq1.addGroup(group1.createParallelGroup().addComponent(labels.get(i)).addComponent((JTextField)fields.get(i)));
        }
    }
}

}

例外:

java.lang.IllegalStateException: javax.swing.JTextField[,0,0,0x0,invalid,layout=javax.swing.plaf.basic.BasicTextUI$UpdateHandler,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@46faf015,flags=296,maximumSize=,minimumSize=,preferredSize=,caretColor=sun.swing.PrintColorUIResource[r=51,g=51,b=51],disabledTextColor=javax.swing.plaf.ColorUIResource[r=184,g=207,b=229],editable=true,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],selectedTextColor=sun.swing.PrintColorUIResource[r=51,g=51,b=51],selectionColor=javax.swing.plaf.ColorUIResource[r=184,g=207,b=229],columns=20,columnWidth=0,command=,horizontalAlignment=LEADING] is not attached to a horizontal group
at javax.swing.GroupLayout.checkComponents(Unknown Source)
at javax.swing.GroupLayout.prepare(Unknown Source)
at javax.swing.GroupLayout.minimumLayoutSize(Unknown Source)
at java.awt.Container.minimumSize(Unknown Source)
at java.awt.Container.getMinimumSize(Unknown Source)
at javax.swing.JComponent.getMinimumSize(Unknown Source)
at javax.swing.BoxLayout.checkRequests(Unknown Source)
at javax.swing.BoxLayout.layoutContainer(Unknown Source)
at java.awt.Container.layout(Unknown Source)
at java.awt.Container.doLayout(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validate(Unknown Source)
at java.awt.Container.validateUnconditionally(Unknown Source)
at java.awt.Window.show(Unknown Source)
at java.awt.Component.show(Unknown Source)
at java.awt.Component.setVisible(Unknown Source)
at java.awt.Window.setVisible(Unknown Source)
at main.Sample$1.run(Sample.java:34)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at javax.swing.SizeRequirements.calculateAlignedPositions(Unknown Source)
    at javax.swing.BoxLayout.layoutContainer(Unknown Source)
    at java.awt.Container.layout(Unknown Source)
    at java.awt.Container.doLayout(Unknown Source)
    at java.awt.Container.validateTree(Unknown Source)
    at java.awt.Container.validateTree(Unknown Source)
    at java.awt.Container.validateTree(Unknown Source)
    at java.awt.Container.validateTree(Unknown Source)
    at java.awt.Container.validateTree(Unknown Source)
    at java.awt.Container.validate(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

【问题讨论】:

    标签: java swing layout-manager grouplayout


    【解决方案1】:

    关于您的代码的一些提示:

    • 不要将框架的内容窗格设置为 JPanel 明确:setContentPane(contentPane)。将此面板添加到内容窗格中:add(contentPane)。这样您就可以利用框架的默认布局管理器:BorderLayout

    • 将布局管理器与setBounds(...) 混用不是一个好主意。只需 pack() 将组件添加到其内容窗格之后并使其可见之前的框架。

    • 虽然您可以完美地使用GroupLayout 来手写您的 GUI,但它旨在供 GUI 构建者使用。请参阅this question 的答案。拐角处有更好的选择。

    • 如果您不想使用任何第三方布局管理器,那么Nested Layout approach 也是一个不错的选择。

    关于这个例外:

    java.lang.IllegalStateException: javax.swing.JTextField[...] is not attached to a horizontal group
    

    真的很难说问题出在哪里,因为创建的组太多。由于某种原因,布局管理器无法解析此文本字段(我猜是descfield)附加到的水平组。预期布局的图片可能有助于找出问题所在。

    更新

    在最小化(删除数组迭代)并测试您的代码后,问题是您创建了多个组,但您从未将水平组或垂直组设置为group1,导致IllegalStateException。要解决此问题,您只需像这样设置两个组:

        group1.setHorizontalGroup(hseq1);
        group1.setVerticalGroup(vseq1);
    

    这是我用来解决问题的固定代码。请注意变量的名称:它们必须有意义。

    import java.awt.BorderLayout;
    import javax.swing.BorderFactory;
    import javax.swing.GroupLayout;
    import javax.swing.GroupLayout.Alignment;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;
    
    public class Demo {
    
        private void createAndShowGUI() {
    
            JPanel groupLayoutPanel = new JPanel();        
            GroupLayout groupLayout = new GroupLayout(groupLayoutPanel);
            groupLayout.setAutoCreateGaps(true);        
            groupLayoutPanel.setLayout(groupLayout);
    
            GroupLayout.Group hg1 = groupLayout.createParallelGroup(Alignment.TRAILING);
            GroupLayout.Group hg2 = groupLayout.createParallelGroup();
    
            GroupLayout.Group vg1 = groupLayout.createParallelGroup();
            GroupLayout.Group vg2 = groupLayout.createParallelGroup();
    
            JLabel nameLabel = new JLabel("Name : ");
            hg1.addComponent(nameLabel);
            vg1.addComponent(nameLabel);
    
            JComboBox<String> nameComboBox = new JComboBox<>();
            hg2.addComponent(nameComboBox);
            vg1.addComponent(nameComboBox);
    
            JLabel descriptionLabel = new JLabel("Desc : ");
            hg1.addComponent(descriptionLabel);
            vg2.addComponent(descriptionLabel);
    
            JTextField descriptionTextField = new JTextField(20);
            hg2.addComponent(descriptionTextField);
            vg2.addComponent(descriptionTextField);
    
            // Horizontal group
            GroupLayout.SequentialGroup hseq1 = groupLayout.createSequentialGroup();
            hseq1.addGroup(hg1);
            hseq1.addGroup(hg2);
    
            // Vertical group
            GroupLayout.SequentialGroup vseq1 = groupLayout.createSequentialGroup();
            vseq1.addGroup(vg1);
            vseq1.addGroup(vg2);
    
            groupLayout.setHorizontalGroup(hseq1);
            groupLayout.setVerticalGroup(vseq1);
    
            JPanel contentPane = new JPanel(new BorderLayout(4, 4));
            contentPane.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
            contentPane.add(groupLayoutPanel);
    
            JFrame frame = new JFrame("Demo");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(contentPane);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
    
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new Demo().createAndShowGUI();
                }
            });
        }
    }
    

    截图

    【讨论】:

    • 谢谢@dic19。我只有两个 JLabels : Name 和 Desc 以及 JcomboBoxJTextField 分别代表这两个。关于组,我只是将其分组为水平,我使用前两个 for 循环,垂直使用最后一个 for 循环
    • 欢迎您@Mercenary。请看我的更新。您必须将水平组和垂直组都设置为group1(布局)。不过我强烈建议您使用其他布局管理器。
    • 谢谢!我重新设计了我编写它的方式并且它有效!是的,我觉得这是因为没有将他们添加到组中。
    猜你喜欢
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多