Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and drop files in Matlab GUI

I am trying to find a way to use drag and drop in my matlab GUI. The closest I've found is this.

However, I would like the result to look like this:

enter image description here

When a file has been dropped, all I need is the path of the file and a call to my load function.

All suggestions are much appreciated!

like image 775
jkazan Avatar asked Apr 25 '16 06:04

jkazan


People also ask

Is Matlab good for GUI?

Matlab provides a good environment for creating the GUI. This is because it automatically generates the code for the design of the GUI. The generated code also contain comments that make it easy for the programmer to understand what the code entails and to better organize the callback functions.

How do I open a GUI file in Matlab?

Type guide in command window. A new GUI dialog box will appear. In the dialog box you will select the existing GUI project. To to the tab and you will find the gui file which you want to edit.

What does \t mean in Matlab?

The ability to use the "\t" format in a listbox in MATLAB to place a tab in a string expression is not available. As a workaround, you can use spaces along with a fixed-width font to align the columns.


1 Answers

This submission by Maarten van der Seijs on the file exchange seems to solve it.

It creates a callback function which can be coupled to java swing GUI components, as shown in the attached demo.

It uses a java class, which is a thin wrapper around java.awt.dnd.DropTarget:

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

public class MLDropTarget extends DropTarget
{
    /**
     * Modified DropTarget to be used for drag & drop in MATLAB UI control.
     */
    private static final long serialVersionUID = 1L;
    private int droptype;
    private Transferable t;
    private String[] transferData;

    public static final int DROPERROR = 0;
    public static final int DROPTEXTTYPE = 1;
    public static final int DROPFILETYPE = 2;

    @SuppressWarnings("unchecked")
    @Override
    public synchronized void drop(DropTargetDropEvent evt) {

        // Make sure drop is accepted
        evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);

        // Set droptype to zero
        droptype = DROPERROR;        

        // Get transferable and analyze
        t = evt.getTransferable();

        try {
            if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                // Interpret as list of files
                List<File> fileList = (ArrayList<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
                transferData = new String[fileList.size()];
                for (int i = 0; i < fileList.size(); i++) 
                    transferData[i] = fileList.get(i).getAbsolutePath();
                droptype = DROPFILETYPE;
            } 
            else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
                // Interpret as string              
                transferData[0] = (String) t.getTransferData(DataFlavor.stringFlavor);
                droptype = DROPTEXTTYPE;
            }

        } catch (UnsupportedFlavorException e) {
            droptype = DROPERROR;
            super.drop(evt);            
            return;
        } catch (IOException e) {
            droptype = DROPERROR;
            super.drop(evt);
            return;
        }

        // Call built-in drop method (fire MATLAB Callback)       
        super.drop(evt);
    }

    public int getDropType() {
        return droptype;
    }   
    public Transferable getTransferable() {
        return t;
    }
    public String[] getTransferData() {
        return transferData;
    }
}

which is then initialized and called by a MATLAB class:

classdef (CaseInsensitiveProperties) dndcontrol < handle
%DNDCONTROL Class for Drag & Drop functionality.
%   obj = DNDCONTROL(javaobj) creates a dndcontrol object for the specified
%   Java object, such as 'javax.swing.JTextArea' or 'javax.swing.JList'. Two
%   callback functions are available: obj.DropFileFcn and obj.DropStringFcn, 
%   that listen to drop actions of respectively system files or plain text.
%
%   The Drag & Drop control class relies on a Java class that need to be
%   visible on the Java classpath. To initialize, call the static method
%   dndcontrol.initJava(). The Java class can be adjusted and recompiled if
%   desired.
%
%   DNDCONTROL Properties:
%       Parent            - The associated Java object.
%       DropFileFcn       - Callback function for system files.
%       DropStringFcn     - Callback function for plain text.
%
%   DNDCONTROL Methods:
%       dndcontrol        - Constructs the DNDCONTROL object.
%
%   DNDCONTROL Static Methods:
%       defaultDropFcn    - Default callback function for drop events.
%       demo              - Runs the demonstration script.
%       initJava          - Initializes the Java class.
%       isInitialized     - Checks if the Java class is visible.
%
%   A demonstration is available from the static method dndcontrol.demo().
%
%   Example:
%       dndcontrol.initJava();
%       dndcontrol.demo();
%
%   See also:
%       uicontrol, javaObjectEDT.    
%
%   Written by: Maarten van der Seijs, 2015.
%   Version: 1.0, 13 October 2015.


    properties (Hidden)
        dropTarget;                
    end

    properties (Dependent)
        %PARENT The associated Java object.
        Parent;
    end

    properties
        %DROPFILEFCN Callback function executed upon dropping of system files.
        DropFileFcn;        
        %DROPSTRINGFCN Callback function executed upon dropping of plain text.
        DropStringFcn;        
    end

    methods (Static)
        function initJava()
        %INITJAVA Initializes the required Java class.

            %Add java folder to javaclasspath if necessary
            if ~dndcontrol.isInitialized();
                classpath = fileparts(mfilename('fullpath'));                
                javaclasspath(classpath);                
            end 
        end

        function TF = isInitialized()            
        %ISINITIALIZED Returns true if the Java class is initialized.

            TF = (exist('MLDropTarget','class') == 8);
        end                           
    end

    methods
        function obj = dndcontrol(Parent,DropFileFcn,DropStringFcn)
        %DNDCONTROL Drag & Drop control constructor.
        %   obj = DNDCONTROL(javaobj) contstructs a DNDCONTROL object for 
        %   the given parent control javaobj. The parent control should be a 
        %   subclass of java.awt.Component, such as most Java Swing widgets.
        %
        %   obj = DNDCONTROL(javaobj,DropFileFcn,DropStringFcn) sets the
        %   callback functions for dropping of files and text.

            % Check for Java class
            assert(dndcontrol.isInitialized(),'Javaclass MLDropTarget not found. Call dndcontrol.initJava() for initialization.')

            % Construct DropTarget            
            obj.dropTarget = handle(javaObjectEDT('MLDropTarget'),'CallbackProperties');
            set(obj.dropTarget,'DropCallback',{@dndcontrol.DndCallback,obj});
            set(obj.dropTarget,'DragEnterCallback',{@dndcontrol.DndCallback,obj});

            % Set DropTarget to Parent
            if nargin >=1, Parent.setDropTarget(obj.dropTarget); end

            % Set callback functions
            if nargin >=2, obj.DropFileFcn = DropFileFcn; end 
            if nargin >=3, obj.DropStringFcn = DropStringFcn; end
        end

        function set.Parent(obj, Parent)
            if isempty(Parent)
                obj.dropTarget.setComponent([]);
                return
            end
            if isa(Parent,'handle') && ismethod(Parent,'java')
                Parent = Parent.java;
            end
            assert(isa(Parent,'java.awt.Component'),'Parent is not a subclass of java.awt.Component.')
            assert(ismethod(Parent,'setDropTarget'),'DropTarget cannot be set on this object.')

            obj.dropTarget.setComponent(Parent);
        end

        function Parent = get.Parent(obj)
            Parent = obj.dropTarget.getComponent();
        end
    end

    methods (Static, Hidden = true)
        %% Callback functions
        function DndCallback(jSource,jEvent,obj)

            if jEvent.isa('java.awt.dnd.DropTargetDropEvent')
                % Drop event     
                try
                    switch jSource.getDropType()
                        case 0
                            % No success.
                        case 1
                            % String dropped.
                            string = char(jSource.getTransferData());
                            if ~isempty(obj.DropStringFcn)
                                evt = struct();
                                evt.DropType = 'string';
                                evt.Data = string;                                
                                feval(obj.DropStringFcn,obj,evt);
                            end
                        case 2
                            % File dropped.
                            files = cell(jSource.getTransferData());                            
                            if ~isempty(obj.DropFileFcn)
                                evt = struct();
                                evt.DropType = 'file';
                                evt.Data = files;                                
                                feval(obj.DropFileFcn,obj,evt);
                            end
                    end

                    % Set dropComplete
                    jEvent.dropComplete(true);  
                catch ME
                    % Set dropComplete
                    jEvent.dropComplete(true);  
                    rethrow(ME)
                end                              

            elseif jEvent.isa('java.awt.dnd.DropTargetDragEvent')
                 % Drag event                               
                 action = java.awt.dnd.DnDConstants.ACTION_COPY;
                 jEvent.acceptDrag(action);
            end            
        end
    end

    methods (Static)
        function defaultDropFcn(src,evt)
        %DEFAULTDROPFCN Default drop callback.
        %   DEFAULTDROPFCN(src,evt) accepts the following arguments:
        %       src   - The dndcontrol object.
        %       evt   - A structure with fields 'DropType' and 'Data'.

            fprintf('Drop event from %s component:\n',char(src.Parent.class()));
            switch evt.DropType
                case 'file'
                    fprintf('Dropped files:\n');
                    for n = 1:numel(evt.Data)
                        fprintf('%d %s\n',n,evt.Data{n});
                    end
                case 'string'
                    fprintf('Dropped text:\n%s\n',evt.Data);
            end
        end            

        function [dndobj,hFig] = demo()
        %DEMO Demonstration of the dndcontrol class functionality.
        %   dndcontrol.demo() runs the demonstration. Make sure that the
        %   Java class is visible in the Java classpath.

            % Initialize Java class
            dndcontrol.initJava();

            % Create figure
            hFig = figure();

            % Create Java Swing JTextArea
            jTextArea = javaObjectEDT('javax.swing.JTextArea', ...
                sprintf('Drop some files or text content here.\n\n'));

            % Create Java Swing JScrollPane
            jScrollPane = javaObjectEDT('javax.swing.JScrollPane', jTextArea);
            jScrollPane.setVerticalScrollBarPolicy(jScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

            % Add Scrollpane to figure
            [~,hContainer] = javacomponent(jScrollPane,[],hFig);
            set(hContainer,'Units','normalized','Position',[0 0 1 1]);

            % Create dndcontrol for the JTextArea object
            dndobj = dndcontrol(jTextArea);

            % Set Drop callback functions
            dndobj.DropFileFcn = @demoDropFcn;
            dndobj.DropStringFcn = @demoDropFcn;

            % Callback function
            function demoDropFcn(~,evt)
                switch evt.DropType
                    case 'file'
                        jTextArea.append(sprintf('Dropped files:\n'));
                        for n = 1:numel(evt.Data)
                            jTextArea.append(sprintf('%d %s\n',n,evt.Data{n}));
                        end
                    case 'string'
                        jTextArea.append(sprintf('Dropped text:\n%s\n',evt.Data));
                end
                jTextArea.append(sprintf('\n'));
            end
        end
    end    
end
like image 85
Rody Oldenhuis Avatar answered Sep 20 '22 21:09

Rody Oldenhuis