Results 1 to 5 of 5
  1. #1
    elemenryloz is offline Member
    Join Date
    Sep 2014
    Posts
    2
    Rep Power
    0

    Default Problem removing column from JTable with AbstractTableModel

    Hi, I have an application that uses a JTable with an AbstractTableModel that holds generated data.
    I like to allow the user to remove unwanted columns from the table view via a popup menu invoked by right-clicking a column header.
    Everything works fine unless the user wants to remove the column where he invoked the popup from.

    The following simplified code works unless you right-click the 1st column header:

    Java Code:
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JFrame;
    import javax.swing.JMenuItem;
    import javax.swing.JPanel;
    import javax.swing.JPopupMenu;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.AbstractTableModel;
    
    
    public class Main {
    
    	Main(){
    		JFrame myFrame=new JFrame();
    		JPanel myPanel = new JPanel();
    		myPanel.setLayout(new BorderLayout());
    		MyModel myModel = new MyModel(5,5);
    		final JTable myTable=new JTable();
    		myTable.setModel(myModel);;
    		myPanel.add(new JScrollPane(myTable),BorderLayout.CENTER);
            
    		JPopupMenu my = new JPopupMenu();
    		JMenuItem menuItem = new JMenuItem("delete 1st columns...");
    		menuItem.addActionListener(new ActionListener(){
    			public void actionPerformed(ActionEvent e) {
    				myTable.removeColumn(myTable.getColumnModel().getColumn(0));
    			}		    	
    		});
    		my.add(menuItem);
    		myTable.getTableHeader().setComponentPopupMenu(my);
    		myTable.setAutoCreateRowSorter(true);
            
    		myFrame.setContentPane(myPanel);
    		myFrame.setSize(400,400);
    		myFrame.setVisible(true);
    	}
    	
    	class MyModel extends AbstractTableModel {
    
    		int cols;
    		int rows;
        	
    		MyModel(int numCols, int numRows){
    			this.cols=numCols;
    			this.rows=numRows;
    		}
        	
    		@Override
    		public int getColumnCount() {
    			return cols;
    		}
    
    		@Override
    		public int getRowCount() {
    			return rows;
    		}
    
    		@Override
    		public Object getValueAt(int row, int col) {
    			return ""+row+"/"+col;
    		}
    		
    		@Override 
    		public String getColumnName(int col) { 
    			return "Col "+col; 
    		}
    	};
    	
    	public static void main(String args[]){
    		new Main();
    	}
    }
    And here is the Exception stack trace:

    Java Code:
    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    	at java.util.Vector.elementData(Unknown Source)
    	at java.util.Vector.elementAt(Unknown Source)
    	at javax.swing.table.DefaultTableColumnModel.getColumn(Unknown Source)
    	at javax.swing.plaf.basic.BasicTableHeaderUI.getHeaderRenderer(Unknown Source)
    	at javax.swing.plaf.basic.BasicTableHeaderUI.paintCell(Unknown Source)
    	at javax.swing.plaf.basic.BasicTableHeaderUI.paint(Unknown Source)
    	at javax.swing.plaf.ComponentUI.update(Unknown Source)
    	at javax.swing.JComponent.paintComponent(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JViewport.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JLayeredPane.paint(Unknown Source)
    	at javax.swing.JComponent.paintChildren(Unknown Source)
    	at javax.swing.JComponent.paint(Unknown Source)
    	at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(Unknown Source)
    	at javax.swing.RepaintManager$PaintManager.paint(Unknown Source)
    	at javax.swing.RepaintManager.paint(Unknown Source)
    	at javax.swing.JComponent._paintImmediately(Unknown Source)
    	at javax.swing.JComponent.paintImmediately(Unknown Source)
    	at javax.swing.RepaintManager$3.run(Unknown Source)
    	at javax.swing.RepaintManager$3.run(Unknown Source)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    	at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    	at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    	at javax.swing.RepaintManager.access$1100(Unknown Source)
    	at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    	at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    	at java.awt.EventQueue.access$200(Unknown Source)
    	at java.awt.EventQueue$3.run(Unknown Source)
    	at java.awt.EventQueue$3.run(Unknown Source)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    	at java.awt.EventQueue.dispatchEvent(Unknown Source)
    	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    	at java.awt.EventDispatchThread.run(Unknown Source)
    Anyone any idea?

  2. #2
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,458
    Rep Power
    20

    Default Re: Problem removing column from JTable with AbstractTableModel

    You can file a bug report, but as Swing has long been declared to be in 'maintenance mode' nothing might come of it.

    If you don't need to allow column reordering, an easy workaround is
    Java Code:
    myTable.getTableHeader().setReorderingAllowed(false);
    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  3. #3
    camickr is offline Senior Member
    Join Date
    Jul 2009
    Posts
    1,236
    Rep Power
    7

    Default Re: Problem removing column from JTable with AbstractTableModel

    Not sure what the problem is.

    You can check out: Table Column Manager Java Tips Weblog which appears to work. Don't know if it makes a difference but this class uses a MouseListener to display the popup instead of the setComponentPopupMenu(...) method.

  4. #4
    DarrylBurke's Avatar
    DarrylBurke is offline Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,458
    Rep Power
    20

    Default Re: Problem removing column from JTable with AbstractTableModel

    Quote Originally Posted by camickr View Post
    Not sure what the problem is.
    Me too, but I can see where this is coming from.
    -- if reordering is allowed, mousePressed sets a TableColumn draggedColumn on the TableHeader (BasicTableHeaderUI, line 155)
    -- the painting routine translates that to an index via viewIndexForColumn (BasicTableHeaderUI, lines 698 to 706)
    -- as the column has already been removed, this returns -1 (BasicTableHeaderUI, lines 705)

    Here's a much shorter SSCCE that demonstrates the error and the proposed workaround.
    Java Code:
    public class RemoveFirstColumnTable {
    
      public RemoveFirstColumnTable() {
        final JTable table = new JTable(5, 5);
        // uncomment the next line for a workaround
        //table.getTableHeader().setReorderingAllowed(false);
        table.getTableHeader().addMouseListener(new MouseAdapter() {
    
          @Override
          public void mousePressed(MouseEvent e) {
            table.removeColumn(table.getColumnModel().getColumn(0));
          }
        });
    
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.setSize(400, 400);
        frame.setVisible(true);
      }
    
      public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
    
          @Override
          public void run() {
            new RemoveFirstColumnTable();
          }
        });
      }
    }
    db
    If you're forever cleaning cobwebs, it's time to get rid of the spiders.

  5. #5
    elemenryloz is offline Member
    Join Date
    Sep 2014
    Posts
    2
    Rep Power
    0

    Default Re: Problem removing column from JTable with AbstractTableModel

    Thank you camickr and DarryBurke!

    The MouseListener did the trick!

Similar Threads

  1. JTable not updating with my AbstractTableModel
    By agarta in forum New To Java
    Replies: 5
    Last Post: 03-31-2013, 11:34 PM
  2. problem in adding values in jtable column
    By blustar angel in forum New To Java
    Replies: 22
    Last Post: 08-28-2012, 08:41 PM
  3. Replies: 3
    Last Post: 03-21-2012, 06:57 PM
  4. Replies: 4
    Last Post: 04-01-2009, 03:03 AM
  5. Jtable Column Selection Problem
    By REVANSIDDHA in forum Advanced Java
    Replies: 0
    Last Post: 03-31-2009, 08:53 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •