Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Java drag & drop

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 22 Aug, 2007 15:51:14

Message: 1 of 14

Here are two attempts to implement drop & drag. The second
method is successful in invoking the callback, but access
to hObj and EventData (e,g, through get) then cause
exceptions. Does anyone (are you there Yair) have any ideas?

function droptrial()
f=figure();
j=javacomponent('javax.swing.JComboBox',[],f);
j.setEditable(true);
e=get(j.Editor,'EditorComponent');

% METHOD 1
% This produces an exception and fails:
dnd=e.getDropTarget();
set(dnd, 'DropCallback', @MyCallback);

% METHOD 2
% This works but calls like get(hObj) produce exceptions in
the callback
dnd=java.awt.dnd.DropTarget();
set(dnd, 'DropCallback', @MyCallback);
e.setDropTarget(dnd);
return
end

function MyCallback(hObj, Ev)
get(hObj);
return
end

METHOD1 produces
java.lang.IllegalAccessException: Class
com.mathworks.jmi.bean.MatlabBeanInterface can not access a
member of class javax.swing.TransferHandler$SwingDropTarget
with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess
(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at
com.mathworks.jmi.bean.MatlabBeanInterface.addCallback
(MatlabBeanInterface.java:691)
at
com.mathworks.jmi.bean.MatlabCallbackInterface.addCallback
(MatlabCallbackInterface.java:128)


METHOD2, when get(hObj) is called from the callback after
making a drop (from a JTree) produces
K>> get(hObj)
Active = on
Class = [ (1 by 1) java.lang.Class array]
Component = [ (1 by 1)
javax.swing.plaf.metal.MetalComboBoxEditor$1 array]
DefaultActions = [3]
DropTargetContext = [ (1 by 1)
java.awt.dnd.DropTargetContext array]
FlavorMap = [ (1 by 1)
java.awt.datatransfer.SystemFlavorMap array]
DropCallback = [ (1 by 1) function_handle array]
DropCallbackDatajava.lang.reflect.InvocationTargetEx
ception
at sun.reflect.NativeMethodAccessorImpl.invoke0
(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.mathworks.jmi.bean.ClassInfo.getObjectField
(ClassInfo.java:323)
Caused by: java.awt.dnd.InvalidDnDOperationException: The
operation requested cannot be performed by the DnD system
since it is not in the appropriate state
at java.awt.dnd.DropTargetContext.getTransferable
(Unknown Source)
at java.awt.dnd.DropTargetDropEvent.getTransferable
(Unknown Source)
... 5 more

Subject: Java drag & drop

From: Yair Altman

Date: 22 Aug, 2007 21:01:45

Message: 2 of 14

I must admit I'm just as baffled. It appears that
e.setDropTarget() overrides the default call to the drop
target's TransferHandler() method (which is the default text
handler
javax.swing.plaf.basic.BasicTextUI$TextTransferHandler). You
might try to implement your own TransferHandler as explained
here:
http://java.sun.com/docs/books/tutorial/uiswing/dnd/intro.html
. I believe R2007b (Matlab 7.5) uses Java 1.6 and if so,
then you may be interested in the following article:
http://weblogs.java.net/blog/shan_man/archive/2006/02/choosing_the_dr.html

Yair Altman
http://ymasoftware.com

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 23 Aug, 2007 13:08:06

Message: 3 of 14

Dear Yair
Many thanks.
The R2007b pre-release produces identical exceptions but
thanks for the links. I think your suggestion is on the
right lines: the problems in the callback seem to arise
through calls to DropTargetDropEvent.getTransferable().
I'll follow the links and try TMW with a service request.
ML

Subject: Java drag & drop

From: Raphael Austin

Date: 11 Sep, 2007 14:20:57

Message: 4 of 14

I've posted a drag and drop example, but using Activex.

http://www.mathworks.com/matlabcentral/fileexchange/loadFile
.do?objectId=16312&objectType=file

<a
href="http://www.mathworks.com/matlabcentral/fileexchange/lo
adFile.do?objectId=16312&objectType=file">
http://www.mathworks.com/matlabcentral/fileexchange/loadFile
.do?objectId=16312&objectType=file </a>

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 12 Sep, 2007 15:45:49

Message: 5 of 14

Thanks Raphael. Unfortunately, I need a platform-
independent method.

For those interested TMW Support have just sent this to
Development as a bug notice.

I have found a workaround for my specific needs but not a
proper one. Might the drop event have been handled/rejected
in a listener before the callback is activated?

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 12 Sep, 2007 16:23:45

Message: 6 of 14

I should have added:

dnd=java.awt.dnd.DropTarget();
dnd=handle(dnd,'callbackProperties')

at least lets you get(hObject) in the callback as long as
you do not call hObject.getTransferable()

Subject: Java drag & drop

From: Travis Perry

Date: 18 Nov, 2008 21:54:02

Message: 7 of 14

"Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message <fc93qh$d7j$1@fred.mathworks.com>...
> I should have added:
>
> dnd=java.awt.dnd.DropTarget();
> dnd=handle(dnd,'callbackProperties')
>
> at least lets you get(hObject) in the callback as long as
> you do not call hObject.getTransferable()

Did this issue ever get resolved? I am having the same trouble calling getTransferable(). What was the workaround that you used? I need to access the file name and path of the file being dropped. Is there another way to do this?

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 19 Nov, 2008 15:35:02

Message: 8 of 14

There is no workaround that I know of. However, I have not tried this out on the most recent MATLAB versions so it is possible that it has been resolved.

Subject: Java drag & drop

From: Travis Perry

Date: 20 Nov, 2008 17:31:55

Message: 9 of 14

"Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message <gg1bn6$up$1@fred.mathworks.com>...
> There is no workaround that I know of. However, I have not tried this out on the most recent MATLAB versions so it is possible that it has been resolved.

Do you know if the source of the problem was ever determined? I don't have the latest version of Matlab, I have the R2007A which I believe is what you were using before. Do you see any other way of getting the file path and name from a file that has been dragged to a figure? I have been stumped on this for quite a while.

Subject: Java drag & drop

From: Malcolm Lidierth

Date: 24 Nov, 2008 17:19:02

Message: 10 of 14

Travis
I am afraid not - but its not my area.
Malcolm

Subject: Java drag & drop

From: Dirk Engel

Date: 3 Apr, 2009 14:13:01

Message: 11 of 14

"Travis Perry" <travisjperry@gmail.com> wrote in message <gg46ub$o63$1@fred.mathworks.com>...
> "Malcolm Lidierth" <ku.ca.lck@htreidil.mloclam> wrote in message <gg1bn6$up$1@fred.mathworks.com>...
> > There is no workaround that I know of. However, I have not tried this out on the most recent MATLAB versions so it is possible that it has been resolved.
>
> Do you know if the source of the problem was ever determined? I don't have the latest version of Matlab, I have the R2007A which I believe is what you were using before. Do you see any other way of getting the file path and name from a file that has been dragged to a figure? I have been stumped on this for quite a while.

I couldn't pinpoint the exact source of this problem either but do could locate it somewhere within Mathworks DropTargetListener which seems to pass the DropTargetDropEvent (dtde) to the Matlab callback function without accepting the drop before, so dtde.getTransferable() fails.
Since I wasn't able to solve that problem directly, I wrote a new DropTarget class "DropTargetList" which accepts the drop and stores transferable data as java.util.List in a new field. Matlab passes the DropTargetList object to the callback function as first argument:

% initialize new drop target
dnd=javaObjectEDT('DropTargetList')
dnd=handle(dnd,'callbackProperties');
set(dnd, 'DropCallback', @MyCallback);
e.setDropTarget(dnd);

function MyCallback(dropTargetList, dropTargetDropEvent)
data = dropTargetObject.getTransferData();
%...
end


Here's the java code of the DropTargetList class:

import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.util.List;
import java.io.IOException;

/* Modified DropTarget to be used for drag & drop in Matlab GUIs
 *
 * Dirk Engel
 * Process Systems Engineering
 * RWTH Aachen University
 */
public class DropTargetList extends DropTarget {
    
    private Transferable transferable;
    private DataFlavor acceptedDataFlavor = DataFlavor.javaFileListFlavor;
    private List<?> transferData;
    /*********************************************************************/

    public synchronized void drop(DropTargetDropEvent dtde) {
     dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
     super.drop(dtde);
    
     transferable = dtde.getTransferable();
     try {
     transferData = (List<?>)transferable.getTransferData(acceptedDataFlavor);
     } catch (UnsupportedFlavorException e) {
     return;
     } catch (IOException e) {
     return;
     }
    }
    
    public void setAcceptedDataFlavor(DataFlavor flavor) {
     acceptedDataFlavor = flavor; }
    public DataFlavor getAcceptedDataFlavor() {
     return acceptedDataFlavor; }
    public Transferable getTransferable() {
     return transferable; }
    public List<?> getTransferData() {
     return transferData; }
}

Note to Yair Altman's suggestion to override the default drop target's TransferHandler(): I tried it and this also works but is much more difficult because one has to use JMI to call Matlab from Java. Also you get an error when calling "figure" from within the callback after compiling the m-file to a standalone application (very strange)

Hope this solves the DND problem once and for all.

Subject: Java drag & drop

From: Yair Altman

Date: 4 Apr, 2009 19:22:01

Message: 12 of 14

> I couldn't pinpoint the exact source of this problem either but do could locate it somewhere within Mathworks DropTargetListener which seems to pass the DropTargetDropEvent (dtde) to the Matlab callback function without accepting the drop before, so dtde.getTransferable() fails.
> Since I wasn't able to solve that problem directly, I wrote a new DropTarget class "DropTargetList" which accepts the drop and stores transferable data as java.util.List in a new field. Matlab passes the DropTargetList object to the callback function as first argument: [snip...]

I'm afraid the acceptDrop() hunch is incorrect, since if you call dtde.acceptDrop() in the Matlab callback it still does not prevent an InvalidDnDOperationException being thrown from dtde.getTransferable().

I've tried to implement a Matlab-only approach that uses Java, but which does not require compiling a new Java class. I was successful to a point - perhaps others on this thread will have an idea how to proceed:

The basic idea is to use a list of plot command strings as drag source, and drop its items onto Matlab axes that will plot the requested command. Here's the setup:

% Set-up a figure with draggable list-box and 2 droppable axes
hFig = figure('name','DND example','numbertitle','off');
plotNames = {'surfc(peaks)','contour(peaks)','contourf(peaks)', ...
             'surf(membrane)','contour(membrane)','contourf(membrane)'};
jListbox = javax.swing.JList(plotNames);
[hjList,hcList] = javacomponent(jListbox,[10,10,100,200],hFig);
set(hcList,'units','norm','position',[.05,.05,.3,.6]);
hAx1 = axes('position',[.5,.1,.45,.35]);
hAx2 = axes('position',[.5,.55,.45,.35]);
jListbox.setDragEnabled(1);

% Enable drop on the figure axes
dnd = handle(java.awt.dnd.DropTarget(),'callbackProperties');
jFrame = get(hFig,'JavaFrame');
jAxis = jFrame.getAxisComponent;
jAxis.setDropTarget(dnd);
set(dnd,'DropCallback',{@dndCallbackFcn,hFig});
set(dnd,'DragOverCallback',@dndCallbackFcn);

Now the callback. I'm using a persistent transferable to overcome the intermittent behavior of the transferable object - sometime during the drag a valid transferable is available and them I'm grabbing it for reuse during the drop:

% The callback function
function dndCallbackFcn(varargin)
   persistent transferable
   eventData = varargin{2};
   if eventData.isa('java.awt.dnd.DropTargetDropEvent') %nargin>2
       hFig = get(0,'PointerWindow'); %varargin{3};
       hAxes = overobj('axes');
       if ~isempty(hAxes)
           try transferable = eventData.getTransferable; catch, end
           dataFlavorStr = 'text/plain; class=java.lang.String';
           dataFlavor = java.awt.datatransfer.DataFlavor(dataFlavorStr);
           dataStr = transferable.getTransferData(dataFlavor);
           eventData.acceptDrop(eventData.getDropAction);
           axes(hAxes(1));
           set(hFig,'pointer','watch');
           eval(dataStr);
           %obj.getComponent.repaint; % not really necessary
           eventData.dropComplete(true);
           set(hFig,'pointer','arrow');
       else
           eventData.rejectDrop();
       end
       eventData.dropComplete(true);
   elseif eventData.isa('java.awt.dnd.DropTargetDragEvent')
       try transferable = eventData.getTransferable; catch, end
       hAxes = overobj('axes');
       if isempty(hAxes)
           eventData.rejectDrag;
       else
           eventData.acceptDrag(eventData.getDropAction);
       end
   end

This works with 2 problems - Any ideas anyone?
1) after several drag-&-drops the figure stops accepting drags. It's not a source but a target problem, since DND from the list onto the editor still works.
2) the above does not work with a Matlab uicontrol('style','listbox') - setDragEnabled(1) on the underlying com.mathworks.hg.peer.ListboxPeer$UicontrolList is not enough to make the listbox draggable.

> Note to Yair Altman's suggestion to override the default drop target's TransferHandler(): I tried it and this also works but is much more difficult because one has to use JMI to call Matlab from Java. Also you get an error when calling "figure" from within the callback after compiling the m-file to a standalone application (very strange)

I would be grateful if you could post your code for us to learn.

Yair Altman
http://UndocumentedMatlab.com
 

Subject: Java drag & drop

From: Yair Altman

Date: 4 Apr, 2009 20:08:01

Message: 13 of 14

> I've tried to implement a Matlab-only approach that uses Java, but which does not require compiling a new Java class. I was successful to a point - perhaps others on this thread will have an idea how to proceed:

[snip]

> This works with 2 problems - Any ideas anyone?
> 1) after several drag-&-drops the figure stops accepting drags. It's not a source but a target problem, since DND from the list onto the editor still works.
> 2) the above does not work with a Matlab uicontrol('style','listbox') - setDragEnabled(1) on the underlying com.mathworks.hg.peer.ListboxPeer$UicontrolList is not enough to make the listbox draggable.

To clarify, these two problem exist even when using Dirk Engel's Java class. I could not detect any improvement over the Matlab-only approach. Ideas anyone?

Yair Altman
http://UndocumentedMatlab.com
 

Subject: Java drag & drop

From: Erik Koopmans

Date: 27 Jul, 2012 16:00:23

Message: 14 of 14

> This works with 2 problems - Any ideas anyone?
> 1) after several drag-&-drops the figure stops accepting drags. It's not a source but a target problem, since DND from the list onto the editor still works.
> 2) the above does not work with a Matlab uicontrol('style','listbox') - setDragEnabled(1) on the underlying com.mathworks.hg.peer.ListboxPeer$UicontrolList is not enough to make the listbox draggable.

Hello, here's a solution to problem #2:

The underlying JList in Matlab's listbox has an additional property, 'DragSelectionEnabled', which is enabled by default, and prevents drag-and-drop and MouseDraggedCallbacks on the listbox. Setting the property to false resolves the problem.

The following creates a drag-and-drop-enabled listbox (works in Matlab R2010a):

% Create a Matlab UIcontrol listbox
hListbox = uicontrol( 'style', 'listbox', 'string', {'Item 1' 'Item 2'} );

% Get the listbox's underlying Java control
jScrollPane = findjobj( hListbox );
jListbox = jScrollPane.getViewport.getComponent(0);

% Convert the listbox object to a reference handle
jListbox = handle( jListbox, 'CallbackProperties' );

% Configure drag-and-drop on the listbox
set( jListbox, 'DragSelectionEnabled', false, 'DragEnabled', true );


All the best!

Erik Koopmans

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us