java - Matlab arrastra y suelta el archivo desde el explorador de Windows hasta la figura(gui)
user-interface drag-and-drop (2)
Hay una publicación en Matlab Central que utiliza una clase java compilada. Una respuesta stackoverflow incluyó el código. Con esa solución, su demostración puede verse así:
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
Me gustaría saber que hay una forma de arrastrar un archivo desde el explorador de Windows y soltarlo en mi GUI.
El objetivo debe ser obtener la ruta del archivo (o la ruta de la carpeta) y poder cargarla con mi propia función de carga.
Preciso que estoy usando Matlab 2015b en Windows 10 64bits.
Edito mi publicación para dar un ejemplo de código de lo que estoy tratando de hacer (basado en la solución de Yair Altman y otros encontrados en 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
Siempre me sale un error en la línea:
fileList = transferable.getTransferData(dataFlavorList);
El error es el siguiente:
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)
Traté de implementar la misma funcionalidad que la tuya y caí en las mismas excepciones cuando trato de obtener datos transferibles.
No está claro si getTransferable
falla debido a FlavorMap
predeterminado instanciado en %matlabroot%/sys/java/jre/.../lib/flavormap.properties
(como se señala en el libro de Yair Altman en la sección de arrastrar y soltar) o por algún otro extraño razón. De todos modos, encontré este objeto dndcontrol en el intercambio de archivos, que funciona como un encanto para nuestro propósito al administrar los datos transferibles en el lado de Java directamente.
Me inspiro para escribir mi propio proxy matlab encima de java.awt.dnd.DropTarget que es más genérico y más cercano a su par de implementación java (es decir, funciona exactamente de la misma manera que el objeto DropTarget
java excepto que todos los tipos de datos tienen convertido a tipos de matlab más estándar y convenientes).
Puede descargar mi implementación desde aquí:
- GitHub: DropListener
- FileExchange: DropListener
Y aquí hay algunos ejemplos de uso para hacer lo que necesita (colocar en el eje de matlab desde el explorador de archivos):
%
% 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
El objeto también es compatible con la captura de DragOver
, DragOver
, DropActionChanged
, DragExit
evento para que pueda ajustar todos los aspectos de la operación de arrastre. Con poco esfuerzo, también se puede ampliar para admitir el arrastre de imágenes u otros tipos de datos al arrastrar.
Espero que te guste y lo encuentres lo suficientemente genérico como para pensar en otros usos.