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

JTable's (indiv row) setRowHeight(): implement in the MODEL instead?

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Not an Issue
    • Icon: P3 P3
    • None
    • 1.3.0
    • client-libs
    • x86
    • windows_95, windows_98, windows_nt



      Name: krT82822 Date: 03/08/2000


      orig synopsis: "Variable row height handling in JTable is a hack"

      java version "1.3.0rc1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc1-T)
      Java HotSpot(TM) Client VM (build 1.3.0rc1-S, mixed mode)

      Unless I am missing something, the new support in JTable for variable height
      rows is terrible. I was experimenting with it today and the problem stems from
      the fact that row height can only be set on the JTable itself; it seems that the
      proper place to determine row height is in the TableModel, but JTable does not
      query the TableModel for row height and it doesn't even perform proper checking
      itself. For example, if a cell is an ImageIcon it doesn't even make the row big
      enough for the image.

        To solve these shortcomings I tried to add a table model listener that would set
      the height of a row manually using JTable.setRowHeight(row, height) whenever a
      new row is added to the table model. This approach fails in the general case,
      though, since we have no guarantee when the table model listener will be called
      with respect to the JTable itself. If the table model listener is executed
      before the JTable receives the event, then setting the row height has no effect
      and it also appears that row heights are cleared when the table contents change
      so again we have an implicit ordering requirement here too.

      This is bad, bad, bad. I hope I am missing something.
      (Review ID: 101191)
      ======================================================================

      Name: krT82822 Date: 03/08/2000


      java version "1.3.0rc1"
      Java (TM) 2 Runtime Enviroment Standard Edition (build 1.3.0rc1-T)
      Java HotSpot (TM) Client VM (build 1.3.0rc1-S, mixed mode)

      Once I use the JTable.setRowHeight(int row, int rowHeight) method, the table no
      longer displays additional rows added to it. The getRowCount() method indicates
      the rows are present but they do not display. The source code TestTable listed
      below shows this problem. In the TestTable class, clicking the button
      "addNewRowsButton" doubles the number of rows in the table. When the
      setRowHeight method is used, the number of rows displayed remains constant.
      Once the setRowHeight method is removed, the program works as intended.

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

      public class TestTable extends JFrame implements ActionListener
      {
        JTable testTable;
        JButton addNewRowsButton;
        String[] columnNames = {new String("nums1"),new String("nums2")};
        Integer[][] rowValues;
        
        public TestTable()
        {
          setTitle("Test Table");
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

          rowValues = new Integer[5][2];
          for (int i=0; i< 5; i++)
            rowValues[i][0] = new Integer(i);
          for (int i=0; i< 5; i++)
            rowValues[i][1] = new Integer(i*5);
          testTable = new JTable(rowValues,columnNames);
          
          Container content = getContentPane();
          content.add(new JScrollPane(testTable) );
          
           //**setting row height by row causes bug
          int numRows = testTable.getRowCount();
          for (int i=0; i< numRows; i++)
          {
            testTable.setRowHeight(i, 30); //remove this line, program works fine
          }
            
          addNewRowsButton = new JButton("addNewRows");
          content.add(addNewRowsButton, BorderLayout.SOUTH);
          addNewRowsButton.addActionListener(this);
        }
        
        public static void main(String args[])
        {
          TestTable t = new TestTable();
          t.setSize(300,400);
          t.setVisible(true);
        }
        
        public void actionPerformed(ActionEvent ae)
        {
          int numNewRows = rowValues.length *2;
          rowValues = new Integer[numNewRows][2];
          for (int i=0; i< numNewRows; i++)
            rowValues[i][0] = new Integer(i);
          for (int i=0; i< numNewRows; i++)
            rowValues[i][1] = new Integer(i*5);
            
          DefaultTableModel defaultTblModel = new DefaultTableModel(rowValues,
      columnNames);
          testTable.setModel(defaultTblModel);
          
          System.out.println("DEBUG: table has "+testTable.getRowCount()+" rows");
        }
      }
      (Review ID: 101704)
      ======================================================================

      Name: krT82822 Date: 03/08/2000


      2 Mar 2000, eval1127@eng -- setRowHeight() is the problem.. Need to nail down the specific cycle caused by setRowHeight().

      java version "1.3beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3beta-O)
      Java(TM) HotSpot Client VM (build 1.3beta-O, mixed mode)


      I wanted my JTable to contain each cell a JTextArea so I created a class that
      extends from JTextArea and implements a TableCellRenderer and put it in the
      JTable. This works fine except for some reason JTable calls
      getTableCellRendererComponent method() repeatedly. I suppose it should only
      make a call until it finishes all of the table cell, but not. Once it reach
      the last cell it will start from the first cell again. It does this without any
      stop.

      I saw a similar case before at the bug list where the workaround is to set the
      setToolTip() method to null. But this did not fix the problem. It still
      continously calls the getTableCellRendereComponent method.

      The effect of this problem is when your application need to repaint itself, for
      example a popup window appeared on top of your main window, or if you minimize
      it. The application never calls the repaint. I think it is because of this
      infinite calls to that method.

      if you want me to discuss this any further, please call me at (818) 955-6241
      pacific standard time.

      Here is the code but if you need me to submit a ready-to-run program, please
      tell me where I can email it. Thank you.

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

      class testApp
      {
      public static void main(String[] args)
      {
      JFrame frame = new JFrame();
      frame.getContentPane().add(new Discrp());
      frame.setSize(600, 150);
      frame.setVisible(true);

      frame.addWindowListener(new WindowAdapter()
      {
      public void windowClosing(WindowEvent e)
      {
      System.exit(0);
      }
      });
      }
      }


      class Discrp extends JPanel
      {
        Object oTitle[] = { "Date/Author", "Comment" } ;
        DefaultTableModel dModel = null ;
        TableColumnModel colMod = null ;
        JTable table = null ;
        
        Discrp()
        {
          dModel = new DefaultTableModel(1, 2)
          {
            public Class getColumnClass(int columnIndex)
            {
              return String.class ;
            }
          };
          
          table = new JTable(dModel) ;
          
          table.setToolTipText(null); // Did not fix it. Reffer to Bug ID: 4139656
          table.setEnabled(false) ;
          table.setPreferredScrollableViewportSize(new Dimension(680, 250)) ;
          table.getTableHeader().setReorderingAllowed(false) ;
          table.setDefaultRenderer(String.class, new MultiLineCellRenderer()) ;
          
          colMod = table.getColumnModel() ;
          colMod.getColumn(1).setPreferredWidth(380) ;
          colMod.getColumn(0).setHeaderValue(oTitle[0]) ;
          colMod.getColumn(1).setHeaderValue(oTitle[1]) ;
          
          JScrollPane jsp = new JScrollPane(table) ;
          jsp.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE) ;
          
          add(jsp) ;
        }

        public void showData(Object[][] oVal)
        {
          dModel.setDataVector(oVal, oTitle);
          colMod.getColumn(1).setPreferredWidth(380) ;
        }
      }

      class MultiLineCellRenderer extends JTextArea implements TableCellRenderer
      {
        String sVal = null ;
        int iLine = 0 ;
         
        public MultiLineCellRenderer()
        {
          setLineWrap(true);
          setWrapStyleWord(true);
          setOpaque(true);
        }
        
        public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
        {
          setForeground(table.getForeground());
          setBackground(table.getBackground());
          setFont(table.getFont()) ;
        
          sVal = (value == null) ? "" : value.toString() ;
        
          if (column == 1)
          {
            System.out.println("Calling getTableCellRendererComponent()") ;
        
            iLine = (sVal.length() / 60 + 2) ;
            table.setRowHeight(row, table.getRowHeight() * iLine) ;
          }
          setText(sVal) ;
          return this;
        }
      }
      (Review ID: 101993)
      ======================================================================

            pmilnesunw Philip Milne (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: