JPanel的FlowLayout()没有在flowlayout中显示JLabel

时间:2014-07-10 11:41:09

标签: java swing layout-manager flowlayout

我是CS学生的第二年(冬假),我正在尝试自学Swing。最终,这只是一个项目,可以添加到我的代码组合中,并加强我在Data Structures&整个学期的算法。

然而,潜入Swing,我遇到了封锁(可能会立刻咬掉太多)。我被困在试图获得我的两个JLabelsheading& dets,在JPanel tbdItem中显示在彼此之下。

我已经四处搜索并尝试了一个解决方案here(使用GridLayout()的解决方案),但这也没有用。

如果您检查我的代码,我相信我已经正确使用了FlowLayout()布局管理器,但实际上输出看起来像忽略了我的JPanel而是使用了布局我JFrame的经理?这里(错误)输出的图像:

http://i.imgur.com/k6RrYHU.png

这是我的代码供参考。我真的不明白为什么它不起作为JPanel我插入的是FlowLayout()

    super("To Be Done");
    setLocationRelativeTo(null); //Center window on open
    setSize(WIDTH, HEIGHT);
    setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE );
    getContentPane().setBackground(Color.LIGHT_GRAY);
    addWindowListener( new CheckOnExit() );
    setLayout( new BorderLayout() );

    JPanel buttonPanel = new JPanel();
    buttonPanel.setBackground(Color.LIGHT_GRAY);

    JButton newTask = new JButton("New Task");
    newTask.addActionListener( new NewTask() );
    newTask.setPreferredSize(new Dimension(130, 40));
    buttonPanel.add(newTask);

    JButton editTask = new JButton("Edit Task");
    editTask.addActionListener( new EditTask() );
    editTask.setPreferredSize(new Dimension(130, 40));
    buttonPanel.add(editTask);

    JButton deleteTask = new JButton("Delete Task");
    deleteTask.addActionListener( new DeleteTask() );
    deleteTask.setPreferredSize(new Dimension(130, 40));
    buttonPanel.add(deleteTask);

    add(buttonPanel, BorderLayout.SOUTH);


    /* TBD Box to display matters TBD */
    JPanel tbdPanel = new JPanel( new FlowLayout() );


    JPanel tbdItem = new JPanel( new FlowLayout() ); //

    JLabel heading = new JLabel("Heading");
    JLabel dets = new JLabel("The Body of the text goes here");

    // Make heading bold -- find out if there's a better way to do this
    Font font = heading.getFont();
    Font boldFont = new Font(font.getFontName(), Font.BOLD, font.getSize());
    heading.setFont(boldFont);      

    tbdItem.add(heading);   
    tbdItem.add(dets);      
    tbdPanel.add(tbdItem);

    add( tbdPanel, BorderLayout.CENTER ); // Add TBD Panel to CENTER of JFrame

非常感谢。如果解决方案在某个地方的网站上,我会道歉。老实说,如果是的话我真的找不到它。

4 个答案:

答案 0 :(得分:2)

您描述的对FlowLayout不自然的行为确实是FlowLayout工作的实际方式。 默认情况下FlowLayout会在Container的顶部中间添加组件,当您尝试添加更多组件时,它会将之前添加的组件移到左侧,但是当行被填充时,它会移动新组件到下一行,再次从下一行的中间开始整个过程​​。

如何使这个用例工作,是使用嵌套布局

在冒险进入Swing世界之前要记住一些要点:

  1. 尽量不要在代码中随机使用setXxXSize()方法。代替 让LayoutManager选择担心这方面。这个帖子 关于should I avoid the use of setXxXSize() methods,是一个 关于这个话题的良好起点
  2. 由于这是Swing,请尝试使用frame.pack(),而不是设置 手动尺寸就可以了。这样,GUI看起来会更具吸引力 Swing用于计算所有内容,GUI应该如何显示 屏幕,以某种方式,不同于任意值 做
  3. 您可能需要深入了解various layouts,并将它们一起使用或单独使用以完成需求。

    一个小程序:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class ToBeDone {
    
        private JButton newTaskButton;
        private JButton editTaskButton;
        private JButton deleteTaskButton;
    
        private static final int GAP = 5;
    
        private void displayGUI() {
            JFrame frame = new JFrame("Swing Worker Example");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
            JPanel contentPane = new JPanel();
            contentPane.setLayout(new BorderLayout(GAP, GAP));
    
            JPanel centerPanel = new JPanel();
            JPanel labelPanel = new JPanel();
            labelPanel.setLayout(new GridLayout(2, 1, GAP, GAP));
            JLabel headingLabel = new JLabel(
                "<html><h1>Heading</h1><html>", JLabel.CENTER);
            JLabel subHeadingLabel = new JLabel(
                "<html><h2>The body of the text goes here</h2>" +
                                            "</html>",JLabel.CENTER);
            labelPanel.add(headingLabel);
            labelPanel.add(subHeadingLabel);
            centerPanel.add(labelPanel);
            contentPane.add(centerPanel, BorderLayout.CENTER);
    
            JPanel buttonPanel = new JPanel();
            newTaskButton = new JButton("New Task");
            editTaskButton = new JButton("Edit Task");
            deleteTaskButton = new JButton("Delete Task");
            buttonPanel.add(newTaskButton);
            buttonPanel.add(editTaskButton);
            buttonPanel.add(deleteTaskButton);
            contentPane.add(buttonPanel, BorderLayout.PAGE_END);
    
            frame.setContentPane(contentPane);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    new ToBeDone().displayGUI();
                }
            };
            EventQueue.invokeLater(runnable);
        }
    }
    

答案 1 :(得分:1)

您将tbdPanel设置为FlowLayout,当您前往此面板时,它们将被添加到一行中。这可能就是你并排拥有它们的原因。尝试使用另一种tbdPanel布局,例如BorderLayout

答案 2 :(得分:1)

问题的原因是tbdItem被赋予new FlowLayout(),如果有空格(有),这将水平布局项目

Swing中的布局管理器可能是一个痛苦的学习曲线 - 尤其是最可配置的; GridBagLayout

我建议首先学习BorderLayout如何工作,然后使用大量的(在层次结构中)来包装你需要的项目。所以相反,你需要做一些像......

JPanel tbdItem = new JPanel( new BorderLayout() );
...
tbdItem.add(heading, BorderLayout.NORTH);
tbdItem.add(dets, BorderLayout.SOUTH);

答案 3 :(得分:1)

看起来创建这些简单的布局(FlowLayoutGridLayout)对用户来说是一种伤害。开始学习布局管理的人自然会从这些开始 简单的管理者没有意识到他们在实践中做不了多少。他们感到困惑和挣扎。答案在于更强大的布局管理器,如GridBagLayoutGroupLayoutMigLayout(外部)。我总是提倡MigLayout,因为它 非常灵活且易于使用。

为了便于说明,我使用MigLayout经理创建了一个示例:

package com.zetcode;

import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;


public class MigLayoutToBeDone extends JFrame {

    public MigLayoutToBeDone() {

        initUI();

        setTitle("To Be Done");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    private void initUI() {

        setLayout(new MigLayout("ins 15", "[grow]", "[][]30:push[]"));

        JLabel heading = new JLabel("Heading");
        JLabel dets = new JLabel("The body of the text goes here");

        add(heading, "center, gapbottom 15,  wrap");
        add(dets, "center, wrap");

        JButton newTask = new JButton("New Task");
        JButton editTask = new JButton("Edit Task");
        JButton deleteTask = new JButton("Delete Task");

        add(newTask, "split 3, center, sgx");
        add(editTask, "sgx");
        add(deleteTask, "sgx");

        pack();

    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                MigLayoutToBeDone ex = new MigLayoutToBeDone();
                ex.setVisible(true);
            }
        });
    }
}

布局由一列组成;该列被拉伸以占据整个窗口区域。 两个标签在列的单元格内水平居中。标签下面, 有一个贪婪的差距占据了所有可用的空间,从而推动了三个 按钮到底部。最后,按钮被放置在一个单元的三个子单元中,它们居中并且具有相同的大小。

ToBeDone example screenshot