Solved

Drag & Drop functionality for JTable removes JTable column headers

Posted on 2002-05-01
10
926 Views
Last Modified: 2013-12-14
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
Comment
Question by:carlpaddick
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 92

Expert Comment

by:objects
ID: 6984468
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
 
LVL 9

Expert Comment

by:Ovi
ID: 6985175
"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
 

Author Comment

by:carlpaddick
ID: 6985769
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:carlpaddick
ID: 6986121
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
 
LVL 92

Accepted Solution

by:
objects earned 200 total points
ID: 6987460
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
 

Author Comment

by:carlpaddick
ID: 6988791
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
 
LVL 92

Expert Comment

by:objects
ID: 6992472
Hopefully the above changes should fix your problems :)
0
 

Author Comment

by:carlpaddick
ID: 6996433
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
 
LVL 92

Expert Comment

by:objects
ID: 6997734
:-)

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
 

Author Comment

by:carlpaddick
ID: 7005535
You help me out with my other question my friend and I'll definitely give you an 'A'. :o)
0

Featured Post

Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
This video teaches viewers about errors in exception handling.
Suggested Courses

621 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question