Solved

Drag and Drop into a JTable

Posted on 2002-05-08
14
1,214 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
MS Dynamics Made Instantly Simpler

Make Your Microsoft Dynamics Investment Count  & Drastically Decrease Training Time by Providing Intuitive Step-By-Step WalkThru Tutorials.

 

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

[Webinar] How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

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…
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.
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

690 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