Problem resizing JDialog and JTable columns

Omar Aguirre :

I'm creating a JDialog window with a JTable on it and I'm trying to make it some "responsive" for different screen sizes. Due the window and the table size may change, I set by percentages the columns width.

No problems at this point. Everything looks good the first time the table gets shown. Once the table gets reloaded (due a modification or something), the columns sizes look different, the table and window still the same size though. This happens just the first time gets reloaded and then everything keeps the same size every next reload.

I used a JOptionPane message dialog to show the table width every time it gets loaded and I found the problem. The first time the table gets loaded is using a different size (the JScrollPane preferred size) and then the next times uses the one it should be due the resize operations.

1st time loaded (image)

enter image description here

2nd time loaded (image)

enter image description here

The real question is why?

I already tried to move the JDialog resizing code to different places on the initComponents() method (creating a global Dimension variable), but the same still happening. If I remove the resizing JDialog code everything works great but that's the coward way lol.

This is the code I'm using, at least what I think is relevant.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Test extends JDialog {
  private javax.swing.JButton bUpdate;
  private javax.swing.JPanel jPanel1;
  private javax.swing.JTable tabla;
  private javax.swing.JScrollPane tablaSP;  
  public Test(Dimension d){
    initComponents();
    int w = (int) (Math.round(d.getWidth())/2);
    int h = (int) (Math.round(d.getHeight())/2);
    setSize(w, h);
    setLocationRelativeTo(null);
    bUpdate.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e){
        cargarProductos();
      }
    });
    cargarProductos();
  }
  private void cargarProductos(){
    try{
      String atr[] = {"Código", "Proveedor", "Nombre", "Clasificación", "Descripción", "Tipo", "P. Compra", "P. Venta"};
      DefaultTableModel model = new DefaultTableModel(null, atr){
          @Override
          public boolean isCellEditable(int row, int column) {
              return false;
          }
      };
      //Filling table model
      tabla.setModel(model);
      int tw = tablaSP.getWidth();
      TableColumnModel cm=tabla.getColumnModel();
      cm.getColumn(0).setPreferredWidth((int) (tw*.10));
      cm.getColumn(1).setPreferredWidth((int) (tw*.15));
      cm.getColumn(2).setPreferredWidth((int) (tw*.15));
      cm.getColumn(3).setPreferredWidth((int) (tw*.10));
      cm.getColumn(4).setPreferredWidth((int) (tw*.19));
      cm.getColumn(5).setPreferredWidth((int) (tw*.10));
      cm.getColumn(6).setPreferredWidth((int) (tw*.10));
      cm.getColumn(7).setPreferredWidth((int) (tw*.10));
      tabla.setAutoCreateRowSorter(true);
      JOptionPane.showMessageDialog(null, tw, "Table width", JOptionPane.PLAIN_MESSAGE);
    }catch(Exception e){
      JOptionPane.showMessageDialog(this, e.getMessage(), "Error llenando tabla de productos", JOptionPane.PLAIN_MESSAGE);
    }
  }
  public static void main(String[]args){
    try {
      for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
        if ("Windows".equals(info.getName())) {
          UIManager.setLookAndFeel(info.getClassName());
          break;
        }
      }
    } catch(Exception e) {
      JOptionPane.showMessageDialog(null, e.getMessage());
    } 
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        Test dialog = new Test(new Dimension (Toolkit.getDefaultToolkit().getScreenSize()));
        dialog.setVisible(true);
      }
    });
  }
  private void initComponents() {
    jPanel1 = new javax.swing.JPanel();
    bUpdate = new javax.swing.JButton();
    tablaSP = new javax.swing.JScrollPane();
    tabla = new javax.swing.JTable();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
    setSize(new java.awt.Dimension(0, 0));

    bUpdate.setText("Update");

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(bUpdate, javax.swing.GroupLayout.DEFAULT_SIZE, 83, Short.MAX_VALUE)
        .addContainerGap())
    );
    jPanel1Layout.setVerticalGroup(
      jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(jPanel1Layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(bUpdate)
        .addContainerGap(242, Short.MAX_VALUE))
    );

    tabla.setModel(new javax.swing.table.DefaultTableModel(
      new Object[][]{ {},{},{},{} },
      new String[]{}
    ));
    tablaSP.setViewportView(tabla);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(tablaSP)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(tablaSP, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
        .addContainerGap())
    );

    pack();
  }
}

I want it to be a JDialog because I need it as a modal Window, but I also need to make it bigger and some "responsive" due the content table may be huge.

second :

The original issue is that you call initComponents to early, namely before you have applied the dimensions you want it to have. As such the call of pack in the initComponents components method reduces your panel to the minimum size.

Afterwards you changed the size of the dialog (by calling setSize(w,h)), but that didn't directly affect the involved components. However when the dialog was set to visible the components were automatically adjusted to fit the defined size. That did not apply to your column size as you did not define a ComponentListener that would have triggered this (see 2nd example below).

This caused a click on the update button to consider the adjusted size of the component for the first time and thus they were applied to the columns.

To fix your issue with the different sizes change your method calls in the constructor to
(complete example of the constructor further below):

int w = (int) (Math.round(d.getWidth()) / 2);
int h = (int) (Math.round(d.getHeight()) / 2);
setPreferredSize(new Dimension(w, h));

initComponents();

You might want to remove the setSize(new java.awt.Dimension(0, 0)); from your initComponents() methods.


If you want to maintain the column size when the user manually resizes the Dialog consider adding a ComponentListener, for another example check this answer.

This could also be used as an alternative solution with your original code, but it might be cleaner to define the sizes correctly in the first place.

public Test(Dimension d) {

    int w = (int) (Math.round(d.getWidth()) / 2);
    int h = (int) (Math.round(d.getHeight()) / 2);
    setPreferredSize(new Dimension(w, h));

    initComponents();

    setLocationRelativeTo(null);
    bUpdate.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            cargarProductos();
        }
    });

    this.addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
             cargarProductos();
         }
    });
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=165989&siteId=1