Solved

Drag and Drop into a JTable

Posted on 2002-05-08
14
1,209 Views
Last Modified: 2013-12-14
This is sort of part 2 of my first question about being able to Drag and Drop into a JTable (see http://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=java&qid=20295898).

The situation I'm now presented with is this:

I have a jscrollpane variable who's client is a jtable.  I'm using the file chooser dialog to manually add and/or drag files from it to the jtable and display the filenames in the rows.  There's no problem adding the files manually - this works fine.  However on a drag and drop operation, if there are no rows contained in the jtable, the drop operation doesn't work because the jtable at this point isn't large enough.  After adding a few rows manually, the jtable increases in size and the drop operation suddenly works IF you drop the file onto an existing row in the jtable - if it's below the last row, then it doesn't work again, I guess this is because the location is outside the size of the jtable?

Now I've tried calling setPreferredSize on the jtable to make it bigger than it's default peferred size, and the drag works if there are no rows, but suddenly other things happen, such as no vertical scroll bar appears in the jscrollpane if there are more rows that fit, the and the last visible row is chopped off at the bottom of the jtable and isn't displayed clearly.  The following article:

http://www.jguru.com/faq/view.jsp?EID=237070

confirms the symptoms and says you shouldn't use setPreferredSize at anytime anyway.

I've also tried calling setPreferredSize on the jscrollpane and it's container a panel and nothing changes the default table size.

So my question is how do you work around this problem?  There's got to be people dragging and dropping values into a jtable that isn't full by default, surely?!!  If anyone has the solution to this problem, I would be appreciate your help.  Thanks.  Here's my code:


import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.table.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;


public class NewJobWindow extends JFrame
{
    javax.swing.JPanel PayloadPanel = new javax.swing.JPanel();
    javax.swing.JScrollPane jFilesScrollPane2 = new javax.swing.JScrollPane();

    java.util.ArrayList fileArrayList;
   
    private FilesTable jFilesTable2;

    public NewJobWindow()
    {
        super("Drag n' Drop & Table Headers Working");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fileArrayList = new ArrayList();

//      Drag and Drop works if you drag a file OVER one of these rows
//      If you comment them all out, it ceases to work
        fileArrayList.add("Dummy1");
        fileArrayList.add("Dummy2");
        fileArrayList.add("Dummy3");
        fileArrayList.add("Dummy4");
        fileArrayList.add("Dummy5");
        fileArrayList.add("Dummy6");
       
//      I'm not using a LayoutManager because I'm using CodeWarrior but
//      even if you do (see the 2 lines below) the result is just the same

//        PayloadPanel.setLayout(new BorderLayout());
//        PayloadPanel.add(jFilesScrollPane2, BorderLayout.CENTER);

        PayloadPanel.setSize(new java.awt.Dimension(270, 210));
        PayloadPanel.setLocation(new java.awt.Point(2,2));
        PayloadPanel.setLayout(null);

        getContentPane().add(PayloadPanel);

        jFilesScrollPane2.setSize(new java.awt.Dimension(200, 180));
        jFilesScrollPane2.setLocation(new java.awt.Point(4,4));
       
        PayloadPanel.add(jFilesScrollPane2);

        jFilesTable2 = new FilesTable();

        jFilesTable2.setModel(new fileListTableModel( fileArrayList ) );
        jFilesTable2.setSelectionMode( ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );

        jFilesTable2.getTableHeader().setFont(new Font("Dialog", 0, 12));
              
        jFilesScrollPane2.setViewportView(jFilesTable2);

        pack();

        setSize(new java.awt.Dimension(222, 214));
        show();
    }
 
    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();

                        fileArrayList.add(chosenFile.getName());
                    }

                    jFilesTable2.revalidate();
                }
                catch( Exception e)
                {
                    System.out.println("Exception "+ e );
                }
            }
            else
                event.rejectDrop();
      }
    }

    public static void main(String[] arguments)
    {
        NewJobWindow frame = new NewJobWindow();
    }
}

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
        {
            String val = (String ) data.get(row);
            return val;
        }
        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
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
  • 8
  • 6
14 Comments
 
LVL 92

Expert Comment

by:objects
ID: 6997753
Have you tried making your viewport also a drop target?
0
 

Author Comment

by:carlpaddick
ID: 7007973
Hello again objects :o) - apologies for the delay in the reply.

To answer your question, yes I have tried making my viewport also a drop target, and it receives the drop messages ok, but only when the file is dragged onto the JScrollPane border.  As soon as you drag the file (that wish to put into the table) inside (past) the JScrollPane, the drop event stops and we're in that space where the table isn't large enough (yet) to pick up any drop events.
0
 
LVL 92

Accepted Solution

by:
objects earned 100 total points
ID: 7007988
Are you sure you are adding the viewport as a drop target, and not the scroll pane?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:carlpaddick
ID: 7008004
Ah, no I'm adding the JScrollPane as a drop target not the viewport.  How do I make the viewport a drop target objects?  Could you show me please?  Thanks.
0
 
LVL 92

Expert Comment

by:objects
ID: 7008013
You can get the viewport component from the scrollpane using it's getViewport() method. Then simply use that component as the drop target instead of the scroll pane.
0
 

Author Comment

by:carlpaddick
ID: 7008015
Ah, no I'm adding the JScrollPane as a drop target not the viewport.  How do I make the viewport a drop target objects?  Could you show me please?  Thanks.
0
 

Author Comment

by:carlpaddick
ID: 7008028
Ah, no I'm adding the JScrollPane as a drop target not the viewport.  How do I make the viewport a drop target objects?  Could you show me please?  Thanks.
0
 

Author Comment

by:carlpaddick
ID: 7008062
Ok, I'll give that a go.  I don't know what EE is doing with my comments today.  It's adding them more than once!
0
 
LVL 92

Expert Comment

by:objects
ID: 7008077
I think if you hit the browser refersh it reposts your comment. Instead use the ee reload button.
0
 

Author Comment

by:carlpaddick
ID: 7008086
Ok, I'll give that a go.  I don't know what EE is doing with my comments today.  It's adding them more than once!
0
 

Author Comment

by:carlpaddick
ID: 7008121
Damn, that's what I've been doing!  Ok I'll do that from now on!  Right then objects I've just changed my code now to be the following:

    public NewJobWindow()
    {
        // .......
        // statements as before so I'm not bothering to include them again objects
           
        jFilesScrollPane2.setViewportView(jFilesTable2);

        new DropTarget(jFilesScrollPane2.getViewport(), new ScrollPaneListener());

        // ......
    }

    private class ScrollPaneListener implements DropTargetListener
    {
        Border originalBorder = null;

        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 = jFilesScrollPane2.getBorder();

            LineBorder theLineBorder = new LineBorder( Color.black, 2 );
            jFilesScrollPane2.setBorder(theLineBorder);
        }
        public void dragExit( DropTargetEvent event )
        {
            jFilesScrollPane2.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();

                        fileArrayList.add(chosenFile.getName());
                    }

                    jFilesTable2.revalidate();
                }
                catch( Exception e)
                {
                    System.out.println("Exception "+ e );
                }
            }
            else
                event.rejectDrop();
      }
    }

and now it works perfectly!!  But every now and then I get a null pointer exception sometimes when I drag onto the table:

java.lang.NullPointerException
        at sun.awt.windows.WDataTransferer.getFlavorsForFormats(WDataTransferer.java:196)
        at sun.awt.DataTransferer.getFlavorsForFormatsAsArray(DataTransferer.java:200)
        at sun.awt.windows.WDropTargetContextPeer.getTransferDataFlavors(WDropTargetContextPeer.java:93)
        at java.awt.dnd.DropTargetContext.getCurrentDataFlavors(DropTargetContext.java:192)
        at java.awt.dnd.DropTargetContext.getCurrentDataFlavorsAsList(DropTargetContext.java:205)
        at java.awt.dnd.DropTargetContext.isDataFlavorSupported(DropTargetContext.java:219)
        at java.awt.dnd.DropTargetDragEvent.isDataFlavorSupported(DropTargetDragEvent.java:117)
        at NewJobWindow$FilesTable.isDragAcceptable(NewJobWindow.java:79)
        at NewJobWindow$FilesTable.dragEnter(NewJobWindow.java:87)
        at java.awt.dnd.DropTarget.dragEnter(DropTarget.java:310)
        at sun.awt.dnd.SunDropTargetContextPeer.processMotionMessage(SunDropTargetContextPeer.java:624)
        at sun.awt.dnd.SunDropTargetContextPeer.run(SunDropTargetContextPeer.java:239)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:154)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:337)
        at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:131)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:98)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:85)

The 2 methods in question seem to be:

        public boolean isDragAcceptable( DropTargetDragEvent event )
        {
            return event.isDataFlavorSupported( DataFlavor.javaFileListFlavor );
        }
 
and

        public void dragEnter( DropTargetDragEvent event )
        {
            if( !isDragAcceptable( event ) )
            {
                event.rejectDrag();
                return;
            }
           originalBorder = jFilesScrollPane2.getBorder();

            LineBorder theLineBorder = new LineBorder( Color.black, 2 );
            jFilesScrollPane2.setBorder(theLineBorder);
        }

Do you have any idea why this is doing this objects?
0
 
LVL 92

Expert Comment

by:objects
ID: 7008150
No idea sorry.
0
 

Author Comment

by:carlpaddick
ID: 7008168
Don't worry objects, I've worked out why it's doing this and sorted out the problem.

Anyway objects, in the first instance you've answered my question above perfectly and solved a huge headache of a problem that I've been trying to work through for quite a while now.

Therefore I'm delighted to give you the points with my thanks and an 'A' grade for your quick response and answer.

Thanks.
0
 
LVL 92

Expert Comment

by:objects
ID: 7008177
Happy to help :-)

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

Featured Post

SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

Question has a verified solution.

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

Suggested Solutions

Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
In this post we will learn how to make Android Gesture Tutorial and give different functionality whenever a user Touch or Scroll android screen.
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

733 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