【问题标题】:FlowLayout() of JPanel not displaying JLabels in a flowlayoutJPanel 的 FlowLayout() 不在流布局中显示 JLabels
【发布时间】:2014-07-10 11:41:08
【问题描述】:

我是 CS 的二年级学生(寒假),我正在尝试自学 Swing。归根结底,这只是一个项目,可以添加到我的代码组合中,并加强我在本学期在数据结构和算法中学到的知识。

但是,在进入 Swing 时,我遇到了障碍(也许一次咬得太多)。我一直试图让我的两个JLabelsheadingdets,在JPaneltbdItem 中出现在彼此下方。

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

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

这是我的代码供参考。我真的不明白为什么它不起作用,因为我插入的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

非常感谢。如果解决方案在此站点的某个地方,我深表歉意。如果是的话,我真的找不到。

【问题讨论】:

标签: java swing layout-manager flowlayout


【解决方案1】:

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

您想让这个用例工作的方式是使用嵌套布局

在进入 Swing 世界之前要记住的几点:

  1. 尽量不要在代码中随意使用setXxXSize()方法。反而 让LayoutManager 所以选择担心这方面。这个线程 关于should I avoid the use of setXxXSize() methods,是一个 该主题的良好起点
  2. 由于这是 Swing,请尝试使用frame.pack(),而不是设置 手动尺寸就可以了。鉴于这种方式,GUI 看起来会更吸引人 Swing 用于计算所有内容,GUI 应如何显示 屏幕,在某种程度上,不同于任意值可以 做

您可能需要将见解发送至 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);
    }
}

【讨论】:

    【解决方案2】:

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

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

    我建议先学习BorderLayout 的工作原理,然后使用其中的许多(在层次结构中)来包装您需要的项目。因此,您需要执行类似...

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

    【讨论】:

    • 非常感谢!这解决了它。
    • 我很久以前就赞成这个,不过,这里只是提醒一下,从 Java 1.4 版开始,Java 鼓励使用 PAGE_START/LINE_START/LINE_END/PAGE_END 而不是 NORTH/EAST/WEST/SOUTH
    【解决方案3】:

    您的 tbdPanel 设置为 FlowLayout,当您前往此面板时,它们将被连续添加。这可能就是为什么您将它们并排放置的原因。尝试为 tbdPanel 使用其他布局,例如 BorderLayout

    【讨论】:

      【解决方案4】:

      看起来创建这些简单的布局(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);
                  }
              });
          }
      }
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-07
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        • 2016-05-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多