United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4127936 : JTable Horizontal Scrollbar doesn't work

Details
Type:
Bug
Submit Date:
1998-04-10
Status:
Open
Updated Date:
2013-05-17
Project Name:
JDK
Resolved Date:
Component:
client-libs
OS:
windows_nt,generic,windows_95
Sub-Component:
javax.swing
CPU:
x86,generic
Priority:
P4
Resolution:
Unresolved
Affected Versions:
1.1.5,1.2.0,1.2.1,1.4.0,6
Targeted Versions:

Related Reports
Duplicate:

Sub Tasks

Description
Name: rk38400			Date: 04/10/98


If the table autoresizes and the minimum
column size is greater than the viewport area
the horizontal scroll bars don't show up or
allow you to scroll.

Below is a short example that will show the bug.
Run it and size the window so that a column
is cut off.  The horizontal scrollbar show up
but the slider has no where to go.

import com.sun.java.swing.*;
import com.sun.java.swing.table.*;
import com.sun.java.swing.event.*;
import com.sun.java.swing.border.*;

import java.awt.*;
import java.awt.event.*;
import java.util.*;


public class TableTest extends JFrame
{

  public static void main( String[] args)
    {
      Frame f = new TableTest();
    }

  public TableTest()
    {
      super("TableTest");
      this.getContentPane().add(createTable());
      setSize(new Dimension(200,200));
      show();
}
    
      public JScrollPane createTable() {

        // final
        final String[] names = {"First\nName", "Last\nName"};

	//ImageIcon burger = loadIcon("burger.gif","burger");
	//ImageIcon fries = loadIcon("fries.gif","fries");
	//ImageIcon softdrink = loadIcon("softdrink.gif","soft drink");
	//ImageIcon hotdog = loadIcon("hotdog.gif","hot dog");
	//ImageIcon pizza = loadIcon("pizza.gif","pizza");
	//ImageIcon icecream = loadIcon("icecream.gif","ice cream");
	//ImageIcon pie = loadIcon("pie.gif","pie");
	//ImageIcon cake = loadIcon("cake.gif","cake");
	//ImageIcon donut = loadIcon("donut.gif","donut");
	//ImageIcon treat = loadIcon("treat.gif","treat");
	//ImageIcon grapes = loadIcon("grapes.gif","grapes");
	//	ImageIcon banana = loadIcon("banana.gif","banana");
	//	ImageIcon watermelon = loadIcon("watermelon.gif","watermelon");
	//	ImageIcon cantaloupe = loadIcon("cantaloupe.gif","cantaloupe");
	//	ImageIcon peach = loadIcon("peach.gif","peach");
	//	ImageIcon broccoli = loadIcon("broccoli.gif","broccoli");
	//	ImageIcon carrot = loadIcon("carrot.gif","carrot");
	//	ImageIcon peas = loadIcon("peas.gif","peas");
	//	ImageIcon corn = loadIcon("corn.gif","corn");
	//	ImageIcon radish = loadIcon("radish.gif","radish");

        
        // Create the dummy data (a few rows of names)
        final Object[][] data = {
	  {"Mike", "Albers",        Color.green, "Soccer", new Integer(44)},
	  {"Mark", "Andrews",       Color.red, "Baseball", new Integer(2)},
	  {"Tom", "Ball",           Color.blue, "Football", new Integer(99)},
	  {"Alan", "Chung",         Color.green, "Baseball", new Integer(838)},
	  {"Jeff", "Dinkins",       Color.magenta, "Football", new Integer(8)},
	  {"Amy", "Fowler",         Color.yellow, "Hockey", new Integer(3)},
	  {"Brian", "Gerhold",      Color.green, "Rugby", new Integer(7)},
	  {"James", "Gosling",      Color.pink, "Tennis", new Integer(21)},
	  {"David", "Karlton",      Color.red, "Baseball", new Integer(1)},
	  {"Dave", "Kloba",         Color.yellow, "Football", new Integer(14),},
	  {"Peter", "Korn",         new Color(100, 100, 255), "Scuba Diving", new Integer(12)},
	  {"Dana", "Miller",        Color.blue, "Ice Skating", new Integer(8)},
	  {"Phil", "Milne",         Color.magenta, "Rugby", new Integer(3)},
	  {"Dave", "Moore",         Color.green, "Tennis", new Integer(88)},
	  {"Hans", "Muller",        Color.magenta, "Baseball", new Integer(5)},
	  {"Rick", "Levenson",      Color.blue, "Football", new Integer(2)},
	  {"Tim", "Prinzing",       Color.blue, "Baseball", new Integer(22)},
	  {"Chester", "Rose",       Color.black, "Hockey", new Integer(0)},
	  {"Chris", "Ryan",         Color.black, "None", new Integer(6)},
	  {"Ray", "Ryan",           Color.gray, "Football", new Integer(77)},
	  {"Georges", "Saab",       Color.red, "Hockey", new Integer(4)},
	  {"Tom", "Santos",         Color.blue, "Football", new Integer(3)},
	  {"Rich", "Schiavi",       Color.blue, "Hockey", new Integer(4)},
	  {"Nancy", "Schorr",       Color.blue, "Hockey", new Integer(8)},
	  {"Violet", "Scott",       Color.magenta, "Basketball", new Integer(44)},
	  {"Joseph", "Scheuhammer", Color.green, "Hockey", new Integer(66)},
	  {"Jeff", "Shapiro",       Color.black, "Skiing", new Integer(42)},
	  {"Willie", "Walker",      Color.blue, "Hockey", new Integer(4)},
	  {"Kathy", "Walrath",      Color.blue, "Baseball", new Integer(8)},
	  {"Arnaud", "Weber",       Color.green, "Football", new Integer(993)},
	  {"Steve", "Wilson",       Color.green, "Baseball", new Integer(7)}
        };

        // Create a model of the data.
        TableModel dataModel = new AbstractTableModel() {
            public int getColumnCount() { return names.length; }
            public int getRowCount() { return data.length;}
            public Object getValueAt(int row, int col) {return data[row][col];}
            public String getColumnName(int column) {return names[column];}
            public Class getColumnClass(int c) {return getValueAt(0, c).getClass();}
            public boolean isCellEditable(int row, int col) {return getColumnClass(col) == String.class;} 
            public void setValueAt(Object aValue, int row, int column) { data[row][column] = aValue; }
         };


        // Create the table
        JTable tableView = new JTable(dataModel);

        // Show colors by rendering them in their own color. 
        DefaultTableCellRenderer colorRenderer = new DefaultTableCellRenderer() {
	    public void setValue(Object value) { 
	        if (value instanceof Color) {
	            Color c = (Color)value; 
	            setForeground(c);
	            setText(c.getRed() + ", " + c.getGreen() + ", " + c.getBlue());
	        }
	    } 

        }; 

        colorRenderer.setHorizontalAlignment(JLabel.RIGHT); 
        //tableView.getColumn("Favorite Color").setCellRenderer(colorRenderer); 
	Enumeration columns = tableView.getColumnModel().getColumns();
	while(columns.hasMoreElements())
	  {
	    ((TableColumn)columns.nextElement()).setMinWidth(200);
	  }

        tableView.setRowHeight(20);
        
        JScrollPane scrollpane = JTable.createScrollPaneForTable(tableView);
        return scrollpane;
    }
  //    private ImageIcon loadIcon(String name, String description) {
  //	String path = "images/ImageClub/food/" + name;
  //return JPanel.sharedInstance().loadImageIcon(path, description);
  //}



}
(Review ID: 26070)
======================================================================
###@###.### 10/12/04 18:22 GMT

                                    

Comments
EVALUATION

Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=11783&forumID=1463
                                     
2006-03-03
EVALUATION

It's still not clear what the best way to fix this is in a backward compatible way. In the work-around section I've provided a work-around that very clearly solves the problem. It requires overriding both getScrollableTracksViewportWidth() AND getPreferredSize() to have them work together for the desired result. Ideally, we'd put this code into JTable, but it's much too dangerous. The problem is that the fix requires making getPreferredSize() call getMinimumSize() in some cases. It's quite possible that developers have done the opposite (having getMinimumSize() call getPreferredSize()). As such, this fix would result in their application crashing with a stack overflow.

The investigation continues. This will be high priority for Dolphin.
                                     
2005-11-15
EVALUATION

It has been suggested during code review that having JTable.getScrollableTracksViewportWidth() returning true and then not honoring it when less than minimum size in JScrollPane may not be the right thing. More investigation is needed.
                                     
2005-08-30
EVALUATION

Unfortunately, the suggested fix and work-around do not take care of this. We want the user to be able to shrink the table down to it's minimum size, and at THAT POINT, then respect the minimum size and show the scrollbar. This has been fixed by having JScrollPane respect the minimum size even with auto resize turned on for JTables.
                                     
2005-08-26
SUGGESTED FIX

Safe fix is unknown at this time.
                                     
2004-09-24
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mustang


                                     
2004-09-24
WORK AROUND

Override BOTH getScrollableTracksViewportWidth() AND getPreferredSize() to have them work together:

// when the viewport shrinks below the preferred size, stop tracking the viewport width
public boolean getScrollableTracksViewportWidth() {
    if (autoResizeMode != AUTO_RESIZE_OFF) {
        if (getParent() instanceof JViewport) {
            return (((JViewport)getParent()).getWidth() > getPreferredSize().width);
        }
    }
    return false;
}

// when the viewport shrinks below the preferred size, return the minimum size
// so that scrollbars will be shown
public Dimension getPreferredSize() {
    if (getParent() instanceof JViewport) {
        if (((JViewport)getParent()).getWidth() < super.getPreferredSize().width) {
            return getMinimumSize();
        }
    }

    return super.getPreferredSize();
}
                                     
2004-09-24
EVALUATION

Yes, this is a reproducable bug that needs to be fixed before FCS with JDK1.2.
sky 1998-05-28

The implementation of JTable's getScrollableTracksViewportWidth method 
does not take into account the minimum/preferred size of the table, so
if autoresizing is turned on for any mode (ALL, LAST, NEXT, or SUBSEQUENT),
it assumes that the table always fits in the viewport, and hence does not
show horizontal scrollbars. It is possible that even with with autoresizing
the table can be larger than the viewport.

The suggested fix contains a better implementation of the method which 
bases the display of horizontal scrollbars solely on the comparison of
the viewport and table sizes.

###@###.### 2001-10-29
                                     
2001-10-29



Hardware and Software, Engineered to Work Together