Solved

Drag and Drop into a JTable

Posted on 2002-05-08
14
1,188 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
  • 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
 

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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

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

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.

Join & Write a Comment

Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

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

12 Experts available now in Live!

Get 1:1 Help Now