Grid Bag Layout 无法识别我的命令?

Grid Bag Layout doesnt recognize my commands?

我正在制作一个使用大量构造函数的应用程序,我知道您不能使用 netbeans 的拖放工具来制作构造函数,我认为学习如何完全组织代码是个好主意windows, 无论如何我读了一本 DEITEL Java 的书,它使用一种方法将对象添加到容器中,这里是:

private void addobject(Component componente, int column, int row, int width
int height){

//C will be the GridBagConstraints
//And I made a new GridBagLayout called "v"
//My Panel or container is called objcontainer and the LayoutManager is v 

c.gridx = column;
c.gridy = row; 

c.gridwidth = width;
c.gridheight = height;

v.setConstraints(componente, c);    
objcontainer.add(componente);

}

该方法在构造函数所在的同一个 class 中声明,它只用一个网格分隔。但是当我把它放在最后一个物体 2 或更多的地方时,它就像我放 1 一样。

我不知道它是不是这样工作的,锚也不能很好地工作,除了 LINE START 之外,中心的都失败了。

这是代码,无论如何谢谢:

package Windows;

import java.awt.*;

import javax.swing.*;


public class agregaringreso extends JDialog{

    private int ingreso;
    private String nombreingreso;   
    private String Frecuencia [] = {"Solo una vez", "Cada semana","Cada 2 semanas", "Cada 3 semanas", "Cada mes,"};

    Container contenedor;
    JPanel objcontainer;
    GridBagLayout esquema;
    GridBagConstraints c;

    JButton aceptar;
    JLabel title;
    JLabel ingreso2;
    JLabel nombreingreso2;
    JLabel frecuencia2;

    JTextField ingreso3;
    JTextField nombreingreso3;
    JComboBox frecuencia3;

    private void addobjeto(Component componente, int columna, int fila, int ancho, int alto){

        c.gridx = columna;  
        c.gridy = fila;

        c.gridwidth = ancho;
        c.gridheight = alto;

        esquema.setConstraints(componente, c);
        objcontainer.add(componente);


        }

  public agregaringreso(){

      setDefaultCloseOperation(DISPOSE_ON_CLOSE);
      setTitle("Agregar Nuevo Ingreso - EkPek");
      pack();
      setResizable(false);
      setSize(500, 200);
      setLocationRelativeTo(null);

      //FASE DE INICIALIZACION

      contenedor = getContentPane();
      objcontainer = new JPanel();
      esquema = new GridBagLayout();
      c = new GridBagConstraints();

      aceptar = new JButton("Aceptar");
      title = new JLabel("Agregar Nuevo Ingreso");
      ingreso2 = new JLabel("Monto del Ingreso: ");
      nombreingreso2 = new JLabel("Nombre del Ingreso: ");
      frecuencia2 = new JLabel("Frecuencia con la cual recibe el ingreso: ");
      ingreso3 = new JTextField("Escriba aqui el monto");


      nombreingreso3 = new JTextField("Escriba aqui el nombre");

      frecuencia3 = new JComboBox(Frecuencia);

      //FASE DE ACOMODO

      c.anchor = GridBagConstraints.CENTER;
      addobjeto(title, 0, 0, 1, 1);

      c.anchor = GridBagConstraints.LINE_START;
      addobjeto(nombreingreso2 , 0, 4, 1, 1);
      addobjeto(nombreingreso3, 1, 4, 1, 1);

      addobjeto(ingreso2, 0, 5, 1, 1);
      addobjeto(ingreso3, 1, 5, 1, 1 );

      addobjeto(frecuencia2, 0 , 6, 1, 1);
      addobjeto(frecuencia3, 1, 6, 1, 1);

      c.anchor = GridBagConstraints.CENTER;
      addobjeto(aceptar,0 ,7 ,1, 1);


      contenedor.add(objcontainer);
      objcontainer.setLayout(esquema);




      setVisible(true);

}


}

做事的顺序非常重要。做这样的事情毫无意义...

objcontainer = new JPanel();
esquema = new GridBagLayout();
// Add a bunch of stuff
objcontainer.setLayout(esquema);

您基本上已经将组件添加到容器(使用 FlowLayout),然后更改了布局管理器。这些约束不会继续​​存在,它们通常在布局之间不兼容(无论如何,FlowLayoutGridBagConstraints 有什么关系)

而是先设置布局

objcontainer = new JPanel();
esquema = new GridBagLayout();
objcontainer.setLayout(esquema);
// Add components.

这也适用于当您建立 window...

public agregaringreso(){

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setTitle("Agregar Nuevo Ingreso - EkPek");
    pack();
    setResizable(false);
    setSize(500, 200);
    setLocationRelativeTo(null);

这一切都毫无意义,因为您实际上没有向 window 添加任何东西,所以 pack 实际上无法完成它的工作(没有任何东西可以打包)

相反,首先构建 UI,"set up" window 属性...

public agregaringreso(){

    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setTitle("Agregar Nuevo Ingreso - EkPek");

    //FASE DE INICIALIZACION
    contenedor = getContentPane();
    contenedor.setBackground(Color.RED);
    objcontainer = new JPanel();
    esquema = new GridBagLayout();
    objcontainer.setLayout(esquema);
    c = new GridBagConstraints();

    // Add components

    setResizable(false);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
}

it worked separating only by one gridy. But when I put it 2 or more away that the last object it just stays like if I put 1.

如果您的意思是跳转 gridy 的值没有任何作用,那么您是对的,这是有意为之的。网格仅由包含组件的行和列组成。

示例:如果您有 2 个组件,第一个在 (0,0),第二个在 (0,4),则 gridy 值 1 到 3 不计算在内。结果是第二个分量实际上在 (0,1)gridx.

也是如此

also the anchors dont work perfectly, besides the LINE START one, the Center ones are failing.

在您的示例中,CENTER anchor 值按预期运行。如果组件小于其可用的 space(并且未指示用 fill 填充 space),它将与 space 的中心对齐。

您可能希望组件位于整个网格的中心,而不是其可用 space 的中心。为此,您必须对其进行设置,以便通过适当地设置其 gridwidth 来使组件跨越网格的宽度(或高度)。

图片对比

已经解释了如何修复您的设置(我将在下面的注释中提及)。你应该在这些更正之后得到最上面的图片。红线分隔行,蓝线分隔列 - 这是您的网格。

您看到第一行和最后一行中的组件居中在第 0 列 中,因为这是它们可用的 space。在底部图片中,它们在两列中居中,因为我指示它们跨越 2 列。

我还注意到顶部图片中带有黄色矩形的 space 差异。发生这种情况是因为组件没有填满所有可用的 space。虽然这是您的选择,但通常在这种布局中按照底部图片所示进行操作。

代码比较

c.anchor = GridBagConstraints.CENTER; // Redundant - default
addobjeto(title, 0, 0, 2, 1);

c.anchor = GridBagConstraints.LINE_START;
c.fill = GridBagConstraints.HORIZONTAL;
addobjeto(nombreingreso2, 0, 1, 1, 1);
addobjeto(nombreingreso3, 1, 1, 1, 1);

addobjeto(ingreso2, 0, 2, 1, 1);
addobjeto(ingreso3, 1, 2, 1, 1);

addobjeto(frecuencia2, 0, 3, 1, 1);
addobjeto(frecuencia3, 1, 3, 1, 1);

c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.NONE;
addobjeto(aceptar, 0, 4, 2, 1);
  • titleaceptargridwidth 设置为 2(GridBagConstraints.REMAINDER 也可以)以允许它们跨越 2 列。
  • 对于其余组件,设置 c.fill = GridBagConstraints.HORIZONTAL; 以允许它们与自身很好地对齐(黄色矩形)。如果您不希望按钮伸展,请记住将其重置为 c.fill = GridBagConstraints.NONE;aceptar
  • 指定c.anchor = GridBagConstraints.CENTER;对于第一个组件是多余的,因为它是默认的,但它可以使代码更清晰。

备注:

  • 您不需要 JLabel 是字段,因为您可能不需要保存对它们的引用。局部变量也可以,并且会减少内存使用量。
  • Class 名称应以大写开头 (Agregaringreso)。
  • 至于我的 "setup"(正如 MadProgrammer 解释的那样):在添加我拥有的组件之前

    esquema = new GridBagLayout();
    objcontainer = new JPanel(esquema);
    c = new GridBagConstraints();
    

    最后我有

    getContentPane().add(objcontainer);
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setTitle("Agregar Nuevo Ingreso - EkPek");
    pack();
    setResizable(false);
    setLocationRelativeTo(null);
    setVisible(true);
    

    (您不需要保留对内容窗格的引用。)