Romain
Romain

Reputation: 340

Matlab drag and drop file from windows explorer to figure (gui)

I would like to know it there is a way to drag a file from Windows explorer and drop it in my GUI.

The goal should be to get the file path (or folder path) and be able to load it with my own loading function.

I precise that I am using Matlab 2015b in Windows 10 64bits.

I edit my post to give an code example of what I am trying to do (based on Yair Altman solution and other found in Internet) :

function demo

    % Set-up a figure droppable axis
    hFig = figure('name','DND example','numbertitle','off');
    hAx1 = axes('position',[.1,.1,.8,.8]);

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

end

function dndCallbackFcn(varargin)

   persistent transferable
   eventData = varargin{2};
   if eventData.isa('java.awt.dnd.DropTargetDropEvent') %nargin>2
       hFig = varargin{3}; % my figure is passed as the third argument

       try 
           eventData.acceptDrop(eventData.getDropAction);
           transferable = eventData.getTransferable; 
       catch
       end


       dataFlavorList = java.awt.datatransfer.DataFlavor.javaFileListFlavor;
       fileList = transferable.getTransferData(dataFlavorList);

       %{
          I want here to get back the file path and then call my loading function
       %}
    end
end

I always get an error in the line :

fileList = transferable.getTransferData(dataFlavorList); 

The error is the following :

Java exception occurred:
java.awt.dnd.InvalidDnDOperationException: No drop current

at sun.awt.dnd.SunDropTargetContextPeer.getTransferData(Unknown Source)

at sun.awt.datatransfer.TransferableProxy.getTransferData(Unknown Source)

at java.awt.dnd.DropTargetContext$TransferableProxy.getTransferData(Unknown Source)

Upvotes: 2

Views: 2085

Answers (2)

CitizenInsane
CitizenInsane

Reputation: 4855

I tried to implement same functionality as yours and fall into the same exceptions when trying to get transferable data.

It is rather unclear if getTransferable fails because of default FlavorMap instantiated in %matlabroot%\sys\java\jre\...\lib\flavormap.properties (as pointed in Yair Altman's book in drag and drop section) or for some other strange reason. Anyway I came accross this dndcontrol object on file exchange which works like a charm for our purpose by managing transferable data on java side directly.

I get inspired from this to wrote my own matlab proxy on top of java.awt.dnd.DropTarget that is more generic and closer to its java implementation peer (i.e. it works exactly the same way as java DropTarget object except that all data types have been converted to more standard and convenient matlab types).

You can download my implementation from here:

And here is some usage example for doing what you need (drop in matlab axis from file explorer):

%
% PURPOSE:
%
%   Show how to add drop support from file explorer to some matlab axis
%
% SYNTAX:
%
%   [] = DropListenerDemo();
%
% USAGE:
%
%   Simply drop files from file explorer into displayed axis.
%

%%
function [] = DropListenerDemo()
%[
    % Create a figure with some axis inside
    fig = figure(666); clf;
    axes('Parent', fig);

    % Get back the java component associated to the axis
    % NB1: See §3.7.2 of Undocumented Secrets of Matlab Java Programming
    % NB2: or use findjobj, or javaObjectEDT for drop support onto other component types
    jFrame = get(handle(fig), 'JavaFrame');
    jAxis = jFrame.getAxisComponent();

    % Add listener for drop operations
    DropListener(jAxis, ... % The component to be observed
                 'DropFcn', @(s, e)onDrop(fig, s, e)); % Function to call on drop operation    
%]
end
function [] = onDrop(fig, listener, evtArg) %#ok<INUSL>
%[
    % Get back the dropped data
    data = evtArg.GetTransferableData();

    % Is it transferable as a list of files
    if (data.IsTransferableAsFileList)       

        % Do whatever you need with this list of files
        msg = sprintf('%s\n', data.TransferAsFileList{:});
        msg = sprintf('Do whatever you need with:\n\n%s', msg);
        uiwait(msgbox(msg));

        % Indicate to the source that drop has completed 
        evtArg.DropComplete(true);

    elseif (data.IsTransferableAsString)

        % Not interested
        evtArg.DropComplete(false);

    else

        % Not interested
        evtArg.DropComplete(false);

    end
%]
end

The object also support for catching DragEnter, DragOver, DropActionChanged, DragExit event so you can tune every aspects of dragging operation. With little effort, it can also be extended to support for image dragging or other data types dragging.

Hope you'll like it and you'll find it generic enough to think of other usages.

Upvotes: 2

Xiangrui Li
Xiangrui Li

Reputation: 2426

There is a post at Matlab Central which uses a compiled java class. A stackoverflow answer included the code. With that solution, your demo may look like this:

function demo
    % Set-up a figure droppable axis
    hFig = figure('name','DND example','numbertitle','off');
    warning('off', 'MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
    jFrame = get(hFig,'JavaFrame');
    jAxis = jFrame.getAxisComponent;

    % dnccontrol class from above link
    dndcontrol.initJava();
    dndcontrol(jAxis, @dropCallbackFcn);
end

function dropCallbackFcn(~, evt)
    fileparts(evt.Data{1}) % show dropped file's path
end

Upvotes: -1

Related Questions