Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4243683

JTable column width setting ignored upon data model updates

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • None
    • 1.1.6, 1.2.2
    • client-libs
    • generic, x86
    • generic, windows_95



      Name: vi73552 Date: 06/03/99


      My environ is Win95/NT using JDK 1.2 & above. This one has been around for a while (since jdk 1.2 at least and is NOT a dup of 4194022), but I didn't have the time to submit it. It is kinda ugly, if you do not use the workaround it makes for unprofessional behaving apps.

      Code below illustrates 2 apparent JTable bugs:

      1) If you set the width of a JTable column (using setPreferredWidth) then update its datamodel, the JTable loses the column width you set (reverting to default col width) AND you cannot set it back to the original constant (using just setPreferredWidth). After much fooling around, I found that you must use setPreferredWidth AND setWidth upon datamodel update to get the desired col width.

      Using the code below do this:

      a) Press MakeFrame

      b) Press UpdateModel button (which sets a new datamodel & resets the preferred width). Note, the col 1 width reverts to default and a bunch of white space is left on right.

      c) If you resize col 1, the whitespace disappears and upon the NEXT UpdateModel press, TableColumn respects the setPreferredWidth.... But alas, upon a subsequent UpdateModel it doesn't.

      Seems that the TableColumn knows it should be the preferredwidth (since it resets if the tablecolumn is reset by the user), it just errantly reverts to default width.

      If you uncomment the additional setWidth in actionPerformed, col 1 width behaves as it should for the datamodel update.

      2) setMinWidth has strange behavior. Leaving the additional setWidth in actionPerformed commented out, uncomment the 2 setMinWidths in the code and comment out the 2 setPreferredWidths. Run the code (pressing MakeFrame, UpdateModel), and you'll see that setMinWidth yields funny looking table displays.

      Code (indentation & line wraps courtesy of cut&paste):
      // Demonstrates JList column sizing problem (when data model is updated)

      import javax.swing.*;
      import javax.swing.event.*;
      import java.beans.*;
      import java.awt.*;
      import java.awt.event.*;
      import java.util.*;
      import javax.swing.table.*;

      public class JFrame1 extends JFrame {
         static int frameCount = 1;
         
         public JFrame1() {
            super("Internal Frames Demo");
            
            final JDesktopPane desktop = new JDesktopPane();
            getContentPane().add(desktop,BorderLayout.CENTER);
            JInternalFrame makeFrame = new JInternalFrame("Frame Maker",true,false,true,true);
            
            JButton button = new JButton("Make Frame");
            button.addActionListener(new ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent event) {
                  final JInternalFrame internal =
                      new JInternalFrame("Frame #" + frameCount,true,true,true,true);
                  internal.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
                  Container contentPane = internal.getContentPane();
                  contentPane.setLayout(new BoxLayout(contentPane,BoxLayout.Y_AXIS));
                  
                  final JTable table = new JTable(new DataModel());
                  // widen 1st col
                  TableColumn first = table.getColumnModel().getColumn(0);
                  //first.setMinWidth(first.getWidth() + 120);
                  first.setPreferredWidth(first.getWidth() + 120);
                  
                  table.setToolTipText(null);
                  table.getTableHeader().setToolTipText(null);
                  table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                  
                  JScrollPane scrollPane = new JScrollPane(table);
                  contentPane.add(scrollPane);
                  
                  final JButton ZapModel = new JButton("Update Model");
                  ZapModel.addActionListener(new ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent event) {
      table.setModel(new DataModel());
                          // widen 1st col
                          TableColumn one = table.getColumnModel().getColumn(0);
                          //one.setMinWidth(one.getWidth() + 120);
                          one.setPreferredWidth(one.getWidth() + 120);
                          // UNCOMMENT for WORKAROUND one.setWidth(one.getWidth() + 120);
      }
                  });
                  contentPane.add(ZapModel);
                  
                  internal.setBounds(frameCount*20,frameCount*75,300,150);
                  desktop.add(internal);
                  frameCount++;
                  if (frameCount > 10) frameCount=0;
      }
            });
            makeFrame.getContentPane().add(button,BorderLayout.CENTER);
            makeFrame.setBounds(200,0,200,75);
            desktop.add(makeFrame);
            setSize(500,500);
            this.addWindowListener( new WindowAdapter() {
              public void windowClosing(WindowEvent event) {
                  setVisible(false);
                  dispose();
                  System.exit(0);
              }
            });
            show();
         }
         class DataModel extends AbstractTableModel {
                  public int getColumnCount() { return 2; }
                  public int getRowCount() { return 5;}
                  public Object getValueAt(int row, int col) {
                      return new String("Product:"+(row*col));
                  }
         }
          public static void main(String args[]) {
              new JFrame1();
          }
       }
      (Review ID: 83877)
      ======================================================================

      Name: vi73552 Date: 06/16/99


      Hi folks,

      I have a data thread that periodically acquires data and calls
      a method of my extended JPanel class to display the data by
      means of a JTable within a JScollPane. My JPanel class uses the
      fireTableStructureChanged( ) method of my table model extended
      from the abstractTableModel to handle data structure changes.
      The problem is two fold: First, the columns displayed by the
      JTable do not fill the JScroll Pane and, second, column
      re-ordering is "restored" to the original order. Use the
      following example to drag a column to a new column location or
      grab the panel edge to change the display size and you'll see
      what I mean.

      Thanks,
      Don


      I am using JDK1.1.6 with Swing1.1.1Beta2 on Windows95.


      Example Code Follows:
      ============================================================

      import javax.swing.*;
      import javax.swing.table.*;
      import java.awt.*;
      import java.awt.event.*;
      import java.util.*;

      public class TestColumnSize extends JPanel
      {
            private TableModel tableModel;
            private JTable table;
            private Vector columnData;
        
            public TestColumnSize( )
            {
                  super();
                  columnData = new Vector( );
                  tableModel = new TableModel( columnData );
                  table = new JTable( tableModel );
                  JScrollPane scrollpane = new JScrollPane( table );
                  this.setLayout( new BorderLayout( ) );
                  this.add( scrollpane, BorderLayout.CENTER );
            }
            
            public void processData( String message )
            {
                  StringTokenizer t = new StringTokenizer( message );
                  
                  columnData.removeAllElements( );
                  int dataCount = t.countTokens();
                  
                  for( int i = 0; i < dataCount; i++ )
                        columnData.addElement( t.nextToken( ) );

                  tableModel.fireTableStructureChanged( ); // This doesn't work!
                  //tableModel.fireTableDataChanged( ); // This works!
            }
            
            public static void main( String args[] )
            {
                  TestColumnSize testPanel = new TestColumnSize( );
                  JFrame frame = new JFrame( );
                  Data data = new Data( testPanel );
                  
                  frame.setTitle( "Column Size Test" );
                  frame.setSize( 700, 400 );
                  frame.getContentPane().add( testPanel );
                  frame.addWindowListener( new WindowAdapter( )
                  {
                        public void windowClosing( WindowEvent e )
                              { System.exit( 0 ); }
                  });
                  frame.show( );
                  data.start( );
            }
      }

      class TableModel extends AbstractTableModel
      {
            private Vector columnData;
            private int COLUMN_COUNT = 5;
            
            public TableModel( Vector columnData )
            {
                  super();
                  this.columnData = columnData;
            }
            public int getColumnCount( )
                  { return COLUMN_COUNT; }
                  
            public int getRowCount( )
                  { return ( columnData.size( ) / COLUMN_COUNT ); }
            
            public Object getValueAt( int row, int col )
                  { return columnData.elementAt( row * COLUMN_COUNT + col ); }
      }

      class Data extends Thread
      {
            private TestColumnSize panel;
            private Random rand = new Random( );
            String agent_1 = "agent_1 earth.moon disconnected idle ";
            String agent_2 = "agent_2 jupiter disconnected idle ";
            String agent_3 = "agent_3 saturn connected idle ";
            String agent_4 = "agent_4 mercury disconnected idle ";
            String agent_5 = "agent_5 venus connected idle ";
            String agent_6 = "agent_6 mars connected idle ";
            String agent_7 = "agent_7 neptune offline idle ";
            String agent_8 = "agent_8 pluto offline idle ";
            String agent_9 = "agent_9 uranus offline idle ";

            public Data( TestColumnSize panel )
                  { this.panel = panel; }
            
            public void run( )
            {
                  while( true )
                  {
                        panel.processData( agent_1 + numberGenerator( ) +
                              agent_2 + numberGenerator( ) +
                              agent_3 + numberGenerator( ) +
                              agent_4 + numberGenerator( ) +
                              agent_5 + numberGenerator( ) +
                              agent_6 + numberGenerator( ) +
                              agent_7 + numberGenerator( ) +
                              agent_8 + numberGenerator( ) +
                              agent_9 + numberGenerator( ) );
                        try{ sleep( 4000 ); }
                        catch(InterruptedException e) { }
                  }
            }
            
            public String numberGenerator( )
                  { return ( ( java.lang.Math.abs( rand.nextInt( ) % 1000 ) ) + " " ); }
      }
      (Review ID: 84336)
      ======================================================================

            pmilnesunw Philip Milne (Inactive)
            vasya Vassili Igouchkine (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: