JDK-8068824 : draggedColumn in JTableHeader is not reset to null after right mouse click
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 8u11
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2014-11-04
  • Updated: 2021-12-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Description
FULL PRODUCT VERSION :
java version "1.8.0_11"
Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
draggedColumn is not reset after right click on the header of the JTable for opening a popup menu. When we call the fireTableStructureChanged method in the table model afterwards, we get an ArrayIndexOutOfBoundsException.

Full stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
	at java.util.Vector.elementData(Vector.java:734)
	at java.util.Vector.elementAt(Vector.java:477)
	at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
	at javax.swing.plaf.basic.BasicTableHeaderUI.getHeaderRenderer(BasicTableHeaderUI.java:693)
	at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderUI.java:709)
	at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:685)
	at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
	at javax.swing.JComponent.paintComponent(JComponent.java:777)
	at javax.swing.JComponent.paint(JComponent.java:1053)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JViewport.paint(JViewport.java:744)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1532)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1455)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1252)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5165)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4976)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:811)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
	at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the example code. Do a mouse right click on the table header to open a pupup menu. Then, do a mouse left click on the menu entry. The exception appears.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The program runs without exception.
ACTUAL -
An ArrayIndexOutOfBoundsException is thrown.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
	at java.util.Vector.elementData(Vector.java:734)
	at java.util.Vector.elementAt(Vector.java:477)
	at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
	at javax.swing.plaf.basic.BasicTableHeaderUI.getHeaderRenderer(BasicTableHeaderUI.java:693)
	at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(BasicTableHeaderUI.java:709)
	at javax.swing.plaf.basic.BasicTableHeaderUI.paint(BasicTableHeaderUI.java:685)
	at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
	at javax.swing.JComponent.paintComponent(JComponent.java:777)
	at javax.swing.JComponent.paint(JComponent.java:1053)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JViewport.paint(JViewport.java:744)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
	at javax.swing.JComponent.paintChildren(JComponent.java:886)
	at javax.swing.JComponent.paint(JComponent.java:1062)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1532)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1455)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1252)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5165)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4976)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:811)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:794)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:794)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
	at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1680)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

/**
 * Created by mhauser on 11/3/2014.
 */
public class DragTestTable extends JTable {

	public DragTestTable(DragTestTableModel model){

		super(model);

		JPopupMenu menu = new JPopupMenu();
		menu.add(new AbstractAction("Bug Test") {
			@Override
			public void actionPerformed(ActionEvent e) {
				((DragTestTableModel)getModel()).fireTableStructureChanged();
			}
		});

		getTableHeader().setComponentPopupMenu(menu);
	}

	public static class DragTestTableModel extends AbstractTableModel {
		private Object rowData[][];
		private Object columnNames[];

		public DragTestTableModel(Object rowData[][], Object columnNames[]){
			super();
			this.rowData = rowData;
			this.columnNames = columnNames;
		}

		public String getColumnName(int column) { return columnNames[column].toString(); }
		public int getRowCount() { return rowData.length; }
		public int getColumnCount() { return columnNames.length; }
		public Object getValueAt(int row, int col) { return rowData[row][col]; }
		public boolean isCellEditable(int row, int column) { return true; }
		public void setValueAt(Object value, int row, int col) {
			rowData[row][col] = value;
			fireTableCellUpdated(row, col);
		}
		public void fireTableStructureChanged(){
			super.fireTableStructureChanged();
		}

	}
}

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;

/**
 * Created by mhauser on 11/3/2014.
 */
public class JTableCreatingDemo {

	public static void main(String args[]) {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		Object rowData[][] = { { "Row1-Column1", "Row1-Column2", "Row1-Column3" },
			{ "Row2-Column1", "Row2-Column2", "Row2-Column3" } };
		Object columnNames[] = { "Test", "Click me with right mouse click!", "Test" };

		DragTestTable.DragTestTableModel model = new DragTestTable.DragTestTableModel(rowData, columnNames);

		JTable table = new DragTestTable(model);

		JScrollPane scrollPane = new JScrollPane(table);
		frame.add(scrollPane, BorderLayout.CENTER);
		frame.setSize(600, 150);
		frame.setVisible(true);
	}
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Execute getTableHeader().setDraggedColumn(null) before ((DragTestTableModel)getModel()).fireTableStructureChanged() is executed.