Reputation: 340
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
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
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