• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 934
  • Last Modified:

Drag & Drop functionality for JTable removes JTable column headers

I've been scratching my head for days trying to sort out why the following problem occurs but have been unable to find a solution.  So I would appreciate someone's help, thanks.

I'm using Java 1.3.1

I have a JTable derived class that implements drag and drop - this works fine, no problems here.  However, I want to display column headers for my JTable, so USING a created JScrollPane instance variable, I add the JTable class to it, then add it to the JPanel container that they're both contained in.  Compile, run and........

NOTHING HAPPENS!  No table column headers appear in the table!  Code wise everything seems to be present, and in my derived JTable class I override getColumnName() and return the appropriate column name.

Now here's the strange bit.  If I remove the call to add my JTable class to the JPanel container, the table column headers appear but the drag and drop operation stops working.  Reintroducing the JPanel.add(JTable) line, enables drag a drop but removes the table column headers!  Bizarre - but very annoying!

Can anyone tell me if I'm doing anything wrong or if there's some bug in JTable that doesn't allow both of these features to exist happily together. I think I read somewhere that this could possibly be a bug?  Any working code examples would be much appreciated, and I can provide code snippets of the problem if it helps.

Thanks in advance.
0
carlpaddick
Asked:
carlpaddick
  • 5
  • 4
1 Solution
 
objectsCommented:
How can the table headers appear (and dnd work) if you DON'T add the table to the container? You must be adding the table to something.
Can u post the relevant parts of your code pls.
0
 
OviCommented:
"I add the JTable class to it, then add it to the JPanel container that they're both contained in." - you add the table twice? Once to scrollPane and secont to the JPanel? If yes add only to the scrollpane and then add the scrollpane to the panel. Anyway, you should post some code so we can test'it. Create a dummy testing aplication which follows your design and post'it here.
0
 
carlpaddickAuthor Commented:
Thanks for your information both of you.  I've attached snippets of the code for your inspection.  What the code does is basically allow dropping of files from the desktop into a table in a dialog.

I'm using Metroworks Code Warrior to generate my dialog.  If you haven't used it before, it basically creates a special form file (.jfrm) which you create your gui in.  After you save it, it writes out the dialog controls etc to your .java file enclosing them in sections you can't edit but it can read for later form design.  You'll see that the bits you can't edit are enclosed between // GENERATED CODE lines.

You'll also see that I've used the dialog designer to add the JScrollPane variable - jFilesScrollPane.  I then call

       jFilesScrollPane.setViewportView(jFilesTable);

a little later on to associate the table with it.  I also found that the only way that I can get drag and drop to the table to work, is to give the table variable jFilesTable a size (dimension):

        jFilesTable = new FilesTable();
        jFilesTable.setSize(new java.awt.Dimension(180, 150));
        jFilesTable.setLocation(new java.awt.Point(20, 30));
        jFilesTable.setVisible(true);

It's as if it doesn't have a size, then there's no designated droppable area defined for it and nothing happens.  Also you HAVE to add the table to the Panel that the ScrollPane's included in, aswell as the ScrollPane itself:

       FilesPanel.add(jFilesTable);
 
I haven't a clue why this is so.

The rest of the code snippets are hopefully self explanatory, but I'll explain more if need be.  I've tried many variations to get this to work, for example

1) trying jFilesScrollPane = new javax.swing.JScrollPane(jFilesTable);
2) removing the FilesPanel.add(jFilesTable); call and just adding jFilesScrollPane to the Panel

I've commented out sections of code, re-introduced it a bit of a time and still I can only get drag and drop to work WITHOUT table headers if I add the line:

       FilesPanel.add(jFilesTable);

If I comment it out then table headers are displayed but drag and drop DOESN'T work:

//       FilesPanel.add(jFilesTable);

I hope the above helps and here's the code below:

Thanks,

public class MyClass extends JDialog implements ActionListener
{

// IMPORTANT: Source code between BEGIN/END comment pair will be regenerated
// every time the form is saved. All manual changes will be overwritten.
// BEGIN GENERATED CODE
    // member declarations
    //
    // ...more control declarations here....
    //
    javax.swing.JScrollPane jFilesScrollPane = new javax.swing.JScrollPane(); // Variable that represents the Scroll Pane
// END GENERATED CODE

    // Variable that represents my table
    private FilesTable jFilesTable;

    public MyClass()
    {
        initComponents();
    }

    public void initComponents()
    {
// IMPORTANT: Source code between BEGIN/END comment pair will be regenerated
// every time the form is saved. All manual changes will be overwritten.
// BEGIN GENERATED CODE
        // the following code sets the frame's initial state
        //
        // ...more control sizing here....
        //
        jFilesScrollPane.setSize(new java.awt.Dimension(180, 150));
        jFilesScrollPane.setLocation(new java.awt.Point(20, 30));
        jFilesScrollPane.setVisible(true);

        // FilesPanel is a JPanel and declared earlier
        FilesPanel.add(jFilesScrollPane);
        getContentPane().add(FilesPanel);

// END GENERATED CODE
        addTableInfo();
        pack();
        show();
    }

    private void addTableInfo()
    {
        jFilesTable = new FilesTable();
        jFilesTable.setSize(new java.awt.Dimension(180, 150));
        jFilesTable.setLocation(new java.awt.Point(20, 30));
        jFilesTable.setVisible(true);

        jFilesTable.setModel(new FileListTableModel( fileArrayList ) );
        jFilesTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
        jFilesTable.getModel().addTableModelListener(new FilesListTabelModelListener());

        jFilesTable.getTableHeader().setFont(new Font("Dialog", 0, nFontSize));
              
        jFilesScrollPane.setViewportView(jFilesTable);

        FilesPanel.add(jFilesTable);
    }

    private class FilesListTabelModelListener implements TableModelListener
    {
        public void tableChanged( TableModelEvent e)
        {
            // tableChanged code......
        }
    }

    private class FilesTable extends javax.swing.JTable implements DropTargetListener
    {
        Border originalBorder = null;
        DropTarget dropTarget = new DropTarget(this, this);

        public boolean isDragAcceptable( DropTargetDragEvent event )
        {
            return event.isDataFlavorSupported( DataFlavor.javaFileListFlavor );
        }
        public boolean isDropAcceptable( DropTargetDropEvent event )
        {
            return event.isDataFlavorSupported( DataFlavor.javaFileListFlavor );
        }
        public void dragEnter( DropTargetDragEvent event )
        {
            if( !isDragAcceptable( event ) )
            {
                event.rejectDrag();
                return;
            }

            originalBorder = getBorder();

            LineBorder      theLineBorder = new LineBorder( Color.black, 2 );
            setBorder(theLineBorder);
        }
        public void dragExit( DropTargetEvent event )
        {
            setBorder(originalBorder);
        }
        public void dragOver( DropTargetDragEvent event )
        {
        }
        public void dropActionChanged( DropTargetDragEvent event )
        {
            if( !isDragAcceptable( event ) )
            {
                event.rejectDrag();
                return;
            }
        }
        public void drop( DropTargetDropEvent event )
        {
            if( isDropAcceptable( event ) )
            {
                event.acceptDrop( DnDConstants.ACTION_MOVE );
                Transferable transferable = event.getTransferable();

                try
                {
                    java.util.List filesdropped = (java.util.List)transferable.getTransferData( DataFlavor.javaFileListFlavor );

                    Iterator iter = filesdropped.iterator();
                    while( iter.hasNext() )
                    {
                        java.io.File chosenFile = (java.io.File) iter.next();

                        if (fileArrayList.contains(chosenFile) != true)
                        {
                            fileArrayList.add(chosenFile); // fileArrayList is an ArrayList
                        }
                        else
                        {
                            Toolkit.getDefaultToolkit().beep();
                        }
                    }
                    jFilesTable.revalidate();
                    jFilesTable2.getModel().broadcastTableChanged();
                }
                catch( Exception e)
                {
                    System.out.println("Exception "+ e );
                }
            }
            else
            {
                event.rejectDrop();
                return;
            }
        }
    }

    private class fileListTableModel extends javax.swing.table.AbstractTableModel
    {
        protected ArrayList data = null;

        final String[] columnNames = {"Files/Directories"};

        public fileListTableModel(ArrayList thedata )
        {
            data = thedata;
        }
        public int getColumnCount()
        {
            return 1;
        }
        public int getRowCount()
        {
            return data.size();
        }

        public String getColumnName(int col)
        {
            return columnNames[col];
        }
   
        public Object getValueAt(int row, int col)
        {
            try
            {
                File theFile = (File)data.get(row);
                return theFile.getName();
            }
            catch (Exception e)
            {
                System.out.println(" Exception "+ e );
            }
            return "";
        }
   
        public Class getColumnClass(int c)
        {
            return getValueAt(0, c).getClass();
        }
        public void broadcastTableChanged()
        {
            fireTableChanged(null);
        }
    }
}
   
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
carlpaddickAuthor Commented:
Thanks for your information both of you.  I've attached snippets of the code for your inspection.  What the code does is basically allow dropping of files from the desktop into a table in a dialog.

I'm using Metroworks Code Warrior to generate my dialog.  If you haven't used it before, it basically creates a special form file (.jfrm) which you create your gui in.  After you save it, it writes out the dialog controls etc to your .java file enclosing them in sections you can't edit but it can read for later form design.  You'll see that the bits you can't edit are enclosed between // GENERATED CODE lines.

You'll also see that I've used the dialog designer to add the JScrollPane variable - jFilesScrollPane.  I then call

       jFilesScrollPane.setViewportView(jFilesTable);

a little later on to associate the table with it.  I also found that the only way that I can get drag and drop to the table to work, is to give the table variable jFilesTable a size (dimension):

        jFilesTable = new FilesTable();
        jFilesTable.setSize(new java.awt.Dimension(180, 150));
        jFilesTable.setLocation(new java.awt.Point(20, 30));
        jFilesTable.setVisible(true);

It's as if it doesn't have a size, then there's no designated droppable area defined for it and nothing happens.  Also you HAVE to add the table to the Panel that the ScrollPane's included in, aswell as the ScrollPane itself:

       FilesPanel.add(jFilesTable);
 
I haven't a clue why this is so.

The rest of the code snippets are hopefully self explanatory, but I'll explain more if need be.  I've tried many variations to get this to work, for example

1) trying jFilesScrollPane = new javax.swing.JScrollPane(jFilesTable);
2) removing the FilesPanel.add(jFilesTable); call and just adding jFilesScrollPane to the Panel

I've commented out sections of code, re-introduced it a bit of a time and still I can only get drag and drop to work WITHOUT table headers if I add the line:

       FilesPanel.add(jFilesTable);

If I comment it out then table headers are displayed but drag and drop DOESN'T work:

//       FilesPanel.add(jFilesTable);

I hope the above helps and here's the code below:

Thanks,

public class MyClass extends JDialog implements ActionListener
{

// IMPORTANT: Source code between BEGIN/END comment pair will be regenerated
// every time the form is saved. All manual changes will be overwritten.
// BEGIN GENERATED CODE
    // member declarations
    //
    // ...more control declarations here....
    //
    javax.swing.JScrollPane jFilesScrollPane = new javax.swing.JScrollPane(); // Variable that represents the Scroll Pane
// END GENERATED CODE

    // Variable that represents my table
    private FilesTable jFilesTable;

    public MyClass()
    {
        initComponents();
    }

    public void initComponents()
    {
// IMPORTANT: Source code between BEGIN/END comment pair will be regenerated
// every time the form is saved. All manual changes will be overwritten.
// BEGIN GENERATED CODE
        // the following code sets the frame's initial state
        //
        // ...more control sizing here....
        //
        jFilesScrollPane.setSize(new java.awt.Dimension(180, 150));
        jFilesScrollPane.setLocation(new java.awt.Point(20, 30));
        jFilesScrollPane.setVisible(true);

        // FilesPanel is a JPanel and declared earlier
        FilesPanel.add(jFilesScrollPane);
        getContentPane().add(FilesPanel);

// END GENERATED CODE
        addTableInfo();
        pack();
        show();
    }

    private void addTableInfo()
    {
        jFilesTable = new FilesTable();
        jFilesTable.setSize(new java.awt.Dimension(180, 150));
        jFilesTable.setLocation(new java.awt.Point(20, 30));
        jFilesTable.setVisible(true);

        jFilesTable.setModel(new FileListTableModel( fileArrayList ) );
        jFilesTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
        jFilesTable.getModel().addTableModelListener(new FilesListTabelModelListener());

        jFilesTable.getTableHeader().setFont(new Font("Dialog", 0, nFontSize));
              
        jFilesScrollPane.setViewportView(jFilesTable);

        FilesPanel.add(jFilesTable);
    }

    private class FilesListTabelModelListener implements TableModelListener
    {
        public void tableChanged( TableModelEvent e)
        {
            // tableChanged code......
        }
    }

    private class FilesTable extends javax.swing.JTable implements DropTargetListener
    {
        Border originalBorder = null;
        DropTarget dropTarget = new DropTarget(this, this);

        public boolean isDragAcceptable( DropTargetDragEvent event )
        {
            return event.isDataFlavorSupported( DataFlavor.javaFileListFlavor );
        }
        public boolean isDropAcceptable( DropTargetDropEvent event )
        {
            return event.isDataFlavorSupported( DataFlavor.javaFileListFlavor );
        }
        public void dragEnter( DropTargetDragEvent event )
        {
            if( !isDragAcceptable( event ) )
            {
                event.rejectDrag();
                return;
            }

            originalBorder = getBorder();

            LineBorder      theLineBorder = new LineBorder( Color.black, 2 );
            setBorder(theLineBorder);
        }
        public void dragExit( DropTargetEvent event )
        {
            setBorder(originalBorder);
        }
        public void dragOver( DropTargetDragEvent event )
        {
        }
        public void dropActionChanged( DropTargetDragEvent event )
        {
            if( !isDragAcceptable( event ) )
            {
                event.rejectDrag();
                return;
            }
        }
        public void drop( DropTargetDropEvent event )
        {
            if( isDropAcceptable( event ) )
            {
                event.acceptDrop( DnDConstants.ACTION_MOVE );
                Transferable transferable = event.getTransferable();

                try
                {
                    java.util.List filesdropped = (java.util.List)transferable.getTransferData( DataFlavor.javaFileListFlavor );

                    Iterator iter = filesdropped.iterator();
                    while( iter.hasNext() )
                    {
                        java.io.File chosenFile = (java.io.File) iter.next();

                        if (fileArrayList.contains(chosenFile) != true)
                        {
                            fileArrayList.add(chosenFile); // fileArrayList is an ArrayList
                        }
                        else
                        {
                            Toolkit.getDefaultToolkit().beep();
                        }
                    }
                    jFilesTable.revalidate();
                    jFilesTable2.getModel().broadcastTableChanged();
                }
                catch( Exception e)
                {
                    System.out.println("Exception "+ e );
                }
            }
            else
            {
                event.rejectDrop();
                return;
            }
        }
    }

    private class fileListTableModel extends javax.swing.table.AbstractTableModel
    {
        protected ArrayList data = null;

        final String[] columnNames = {"Files/Directories"};

        public fileListTableModel(ArrayList thedata )
        {
            data = thedata;
        }
        public int getColumnCount()
        {
            return 1;
        }
        public int getRowCount()
        {
            return data.size();
        }

        public String getColumnName(int col)
        {
            return columnNames[col];
        }
   
        public Object getValueAt(int row, int col)
        {
            try
            {
                File theFile = (File)data.get(row);
                return theFile.getName();
            }
            catch (Exception e)
            {
                System.out.println(" Exception "+ e );
            }
            return "";
        }
   
        public Class getColumnClass(int c)
        {
            return getValueAt(0, c).getClass();
        }
        public void broadcastTableChanged()
        {
            fireTableChanged(null);
        }
    }
}
   
0
 
objectsCommented:
What you're doing is definitely wrong, you can't add a component to a panel AND have it as a viewport of a scrollpane. A component can only be in one place at the one time.

The table should be the viewport for the scrollpane, but you should remove line that adds the table to FilePanel. I know you've triedd this and it doesn't work but I'd say this is caused by a different reason, probably the crappy generated GUI code.
What is the layout manager used by FilePanel?  
I'd recomend using a BorderLayout and adding FilePanel to CENTER.
Also remove the code that explicitly resizes and positions the scroll pane and table, this is the responsibility of the layout manager.

public void initComponents()
   {
// IMPORTANT: Source code between BEGIN/END comment pair will be regenerated
// every time the form is saved. All manual changes will be overwritten.
// BEGIN GENERATED CODE
       // the following code sets the frame's initial state
       //
       // ...more control sizing here....
       //

       // FilesPanel is a JPanel and declared earlier
       FilesPanel.setLayout(new BorderLayout());
       FilesPanel.add(jFilesScrollPane, BorderLayout.CENTER);
       getContentPane().add(FilesPanel);

// END GENERATED CODE
       addTableInfo();
       pack();
       show();
   }

   private void addTableInfo()
   {
       jFilesTable = new FilesTable();
       jFilesTable.setModel(new FileListTableModel( fileArrayList ) );
       jFilesTable.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
       jFilesTable.getModel().addTableModelListener(new FilesListTabelModelListener());

       jFilesTable.getTableHeader().setFont(new Font("Dialog", 0, nFontSize));
           
       jFilesScrollPane.setViewportView(jFilesTable);
   }
0
 
carlpaddickAuthor Commented:
Thanks for your information 'objects'.  I'll look into doing this, and let you know how I get on.  If you can provide me with a quick working example.  I would appreciate it too.
0
 
objectsCommented:
Hopefully the above changes should fix your problems :)
0
 
carlpaddickAuthor Commented:
Hello objects - apologies for the delay!

Well using your advice and code snippets, I extracted my jtable out into a new jframe in a small test program, compiled and ran the program, and the drag and dropped worked!  However, here's the crazy thing - the drag and drop always worked but it would only work if the files were dragged OVER an existing row in the jtable.  If the drag was done under the last row, nothing would happen.  I guess this is due to the jtable not filling the entire jscrollpane.  Calling setPreferredSize() on the jtable to make it the same physical size as the jscrollpane allows the drag/drop operation to happen in a larger area, however the vertical scroll bar now doesn't automatically appear when there are more rows in the jtable that would naturally fit.  Also the last row can only be half seen.  I'm going to post this problem in another thread, because it's sort of a separate issue.

Thanks for clearing up the present one though and please have the points.
0
 
objectsCommented:
:-)

http://www.objects.com.au
Brainbench MVP for Java 1
http://www.brainbench.com

PS. What did I need to tell you to get an A :)
0
 
carlpaddickAuthor Commented:
You help me out with my other question my friend and I'll definitely give you an 'A'. :o)
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now