我是CS学生的第二年(冬假),我正在尝试自学Swing。最终,这只是一个项目,可以添加到我的代码组合中,并加强我在Data Structures&整个学期的算法。
然而,潜入Swing,我遇到了封锁(可能会立刻咬掉太多)。我被困在试图获得我的两个JLabels
:heading
& dets
,在JPanel
tbdItem
中显示在彼此之下。
我已经四处搜索并尝试了一个解决方案here(使用GridLayout()
的解决方案),但这也没有用。
如果您检查我的代码,我相信我已经正确使用了FlowLayout()
布局管理器,但实际上输出看起来像忽略了我的JPanel
而是使用了布局我JFrame
的经理?这里(错误)输出的图像:
这是我的代码供参考。我真的不明白为什么它不起作为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
非常感谢。如果解决方案在某个地方的网站上,我会道歉。老实说,如果是的话我真的找不到它。
答案 0 :(得分:2)
您描述的对FlowLayout
不自然的行为确实是FlowLayout
工作的实际方式。
默认情况下FlowLayout
会在Container
的顶部中间添加组件,当您尝试添加更多组件时,它会将之前添加的组件移到左侧,但是当行被填充时,它会移动新组件到下一行,再次从下一行的中间开始整个过程。
如何使这个用例工作,是使用嵌套布局
在冒险进入Swing世界之前要记住一些要点:
setXxXSize()
方法。代替
让LayoutManager
选择担心这方面。这个帖子
关于should I avoid the use of setXxXSize() methods,是一个
关于这个话题的良好起点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);
}
}
答案 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)
看起来创建这些简单的布局(FlowLayout
,GridLayout
)对用户来说是一种伤害。开始学习布局管理的人自然会从这些开始
简单的管理者没有意识到他们在实践中做不了多少。他们感到困惑和挣扎。答案在于更强大的布局管理器,如GridBagLayout
,
GroupLayout
或MigLayout
(外部)。我总是提倡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);
}
});
}
}
布局由一列组成;该列被拉伸以占据整个窗口区域。 两个标签在列的单元格内水平居中。标签下面, 有一个贪婪的差距占据了所有可用的空间,从而推动了三个 按钮到底部。最后,按钮被放置在一个单元的三个子单元中,它们居中并且具有相同的大小。