繁体   English   中英

JPanel的FlowLayout()在流布局中不显示JLabel

[英]FlowLayout() of JPanel not displaying JLabels in a flowlayout

我是CS的二年级学生(寒假期间),并且我正在尝试自学Swing。 最终,这只是一个项目,可以添加到我的代码组合中,并巩固我在整个学期中从数据结构和算法中学到的知识。

但是,进入Swing后,我遇到了一个障碍(也许一下子咬得太多了)。 我被困在试图让我的两个JLabelsheadingdets ,在彼此的下面出现JPanel tbdItem

我到处搜索并在这里尝试了一个解决方案(使用GridLayout()的解决方案),但这也不起作用。

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

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

这是我的代码供参考。 我真的不明白为什么它不起作用,因为我要插入的JPanelFlowLayout()

    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

非常感谢。 对于此网站上的解决方案,我深表歉意。 老实说,我找不到它。

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

您想如何使用此用例,是通过使用嵌套布局

在进入Swing的世界之前,需要记住一些要点:

  1. 尽量不要在代码中随机使用setXxXSize()方法。 相反,让LayoutManager选择担心该方面。 关于该线程, 应该避免使用setXxXSize()方法 ,这是该主题的一个很好的起点
  2. 由于这是Swing,请尝试使用frame.pack() ,而不要在其上设置手动大小。 这样,如果使用Swing来计算所有内容,则GUI看起来将更具吸引力,其显示方式与任意值可以执行的方式有所不同

您可能需要深入了解各种布局 ,然后一起使用或单独使用它们来满足需求。

一个小程序:

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);
    }
}

您将tbdPanel设置为FlowLayout,并且在前往此面板的标题和说明时,它们将被添加到一行中。 这可能就是为什么您将它们并排放置的原因。 尝试为tbdPanel使用其他布局,例如BorderLayout

您的问题的原因是,给tbdItem一个new FlowLayout() ,如果有空间(有new FlowLayout() ,它将水平布置项目

Swing中的布局管理器可能是一个痛苦的学习过程,尤其是其中最可配置的学习器。 GridBagLayout

我建议从学习BorderLayout首先如何工作开始,并使用它们中的许多(在层次结构中)包装所需的项目。 因此,相反,您将需要执行以下操作:

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

看起来创建这些简单的布局( 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示例屏幕截图

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM