【问题标题】:Grid Bag Layout doesnt recognize my commands?网格包布局无法识别我的命令?
【发布时间】:2015-05-18 22:34:05
【问题描述】:

我正在制作一个使用大量构造函数的应用程序,我知道你不能使用 netbeans 的拖放工具来制作构造函数,我认为学习如何编写完全组织的窗口是个好主意,无论如何我读了一本 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);

}

该方法是在构造函数所在的同一个类中声明的,它仅以一个网格分隔。但是当我把它放在最后一个对象的 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.add(componente, c);。使用setConstraints 可能不起作用,因为该组件尚未由GridBagLayout 管理(尚未添加)
  • 没用,它只是在同一行显示所有内容,但感谢您阅读这篇大文章。
  • 我可以看到运行代码的结果是什么,但我不知道你在期待什么。尝试发布一些您想要获得的图片。
  • 另外,类名应该以大写开头。
  • @user1803551 请不要留下讽刺的 cmets - 解决问题。您可以编辑帖子,使用它并花 30 秒时间让网站变得更好,而不是添加不必要的讽刺和敌意。

标签: java swing layout layout-manager gridbaglayout


【解决方案1】:

你做事的顺序很重要。这样做毫无意义...

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.

这也适用于你建立一个窗口...

public agregaringreso(){

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

这毫无意义,因为您实际上并没有在窗口中添加任何东西,所以pack 不能真正完成它的工作(它没有什么要打包的)

相反,首先构建 UI,“设置”窗口属性...

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

【讨论】:

  • 我爱你,我仍然有同样的问题,但感谢您解释“功能”,因为我问了一个关于 Windows 居中的问题,他们告诉我就是这样。谢谢..如果我可以发布图片,我会这样做...
  • @AntonioGonzalez 很高兴它可以提供帮助
【解决方案2】:

它只隔了一个网格。但是当我把它放在最后一个对象的 2 或更多的地方时,它就像我放 1 一样。

如果您的意思是跳跃gridy 的值并没有做任何事情,那么您是对的,这是故意的。网格仅由包含组件的行和列组成。

示例:如果您有 2 个组件,第一个位于 (0,0),第二个位于 (0,4),则不计算 gridy 值 1 到 3。结果是第二个组件实际上位于(0,1)gridx 也是如此。

锚也不能正常工作,除了 LINE START 之外,中心的也失败了。

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

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

图片对比

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

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

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

代码对比

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; 是多余的,因为它是默认值,但它可以使代码更清晰。

注意事项:

  • 您不需要将JLabels 作为字段,因为您可能不需要对它们进行引用。局部变量也能起到同样的作用,并且会减少内存使用量。
  • 类名应以大写字母 (Agregaringreso) 开头。
  • 至于我的“设置”(正如 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);
    

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多