当setLayout(null)时,JPanel上的组件不显示



有人能说出为什么组合框没有显示?我有一个控制器:

public class TestController extends JPanel {
TestView cgView;
public TestController() 
{
setLayout(null);
cgView=new TestView();
add(cgView);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame fr = new JFrame("testt");
fr.setSize(1200,1000);
fr.setResizable(false);
TestController cgc=new TestController();
fr.setBackground(Color.white);
fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.add(cgc);
}
});
}

}

和一个视图

public class TestView extends JPanel{
private static final long serialVersionUID = 1L;
public JComboBox<String> comboBox; 
public TestView() {
comboBox= new JComboBox<>(new String[] {"option1", "option2" });
comboBox.setBounds(100,500, 100, 20);
add(comboBox);
}
}

由于TestController中的setLayout(null),我看不到comboBox。如果我将add(cgView.comboBox)添加到我的TestContoller()中,那么它看起来像这样:

public TestController() 
{
setLayout(null);
cgView=new TestView();
add(cgView);
add(cgView.comboBox);
}

我看不见。有人能说出原因吗?

所以我的解决方案是总是在TestController中添加组件,或者将TestController作为一个atribute传递给TestView(所以在TestView()中,我会像这样添加它们。parentPanel.add(comboBox)。还有其他解决方案吗?

  • 几乎永远不要使用null布局
  • 相反,使用嵌套在JPanels中的布局的最佳组合来为GUI实现令人满意的布局
  • 如果您确实使用了null布局,那么您将全权负责设置添加到该容器的所有组件的大小和位置
  • 您当前的问题是,您从未给TestView一个大小或位置,然后使用容器将其添加到空布局中
  • 您不应该将一个组件(在上面,您的JComboBox)添加到多个容器中
  • 在添加所有组件并调用JFrame上的pack()之前,不要在JFrame中调用setVisible(true)

例如

import java.awt.*;
import javax.swing.*;
public class TestController extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 800;
TestView cgView;
public TestController() {
setLayout(null);
cgView = new TestView();
cgView.setSize(getPreferredSize());
add(cgView);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame fr = new JFrame("testt");
// fr.setSize(1200, 1000);
fr.setResizable(false);
TestController cgc = new TestController();
fr.setBackground(Color.white);
// fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.add(cgc);
fr.pack(); //!! added 
fr.setVisible(true); // !! moved
}
});
}
}

但最好使用布局:

import java.awt.*;
import javax.swing.*;
public class TestController extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 800;
TestView cgView;
public TestController() {
//!!  setLayout(null);
cgView = new TestView();
//!! cgView.setSize(getPreferredSize());
add(cgView);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame fr = new JFrame("testt");
// fr.setSize(1200, 1000);
fr.setResizable(false);
TestController cgc = new TestController();
fr.setBackground(Color.white);
// fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.add(cgc);
fr.pack(); //!! added 
fr.setVisible(true); // !! moved
}
});
}
}
class TestView extends JPanel {
private static final long serialVersionUID = 1L;
public JComboBox<String> comboBox;
public TestView() {
comboBox = new JComboBox<String>(new String[] { "option1", "option2" });
// comboBox.setBounds(100, 500, 100, 20);
add(comboBox);
}
}

编辑
OP在评论中问道:

"几乎从不"?在哪种情况下你会使用它[空布局]?

我很少使用它,比如当我想通过动画或鼠标定位器移动组件时,但即便如此,许多人还是建议你创建自己的布局来处理它,比如Rob Camick的Drag layout

最新更新