Solved

Drag & Drop functionality for JTable removes JTable column headers

Posted on 2002-05-01
10
907 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
  • 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
 

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
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
THe viewer will learn how to use NetBeans IDE 8.0 for Windows to perform CRUD operations on a MySql database.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

746 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now