Matlab图形用户界面中的拖放文件

7
我正在寻找一种在我的Matlab GUI中使用拖放的方法。我找到的最接近的是这个(链接)
然而,我希望结果看起来像这样: 图片描述 当文件被放置后,我只需要文件的路径和对我的加载函数进行调用即可。
欢迎提出所有建议!

1
我正在使用Matlab 2012,所以不知道更新的版本是否已经实现了拖放事件。无论如何,您可以使用以下方法:(http://de.mathworks.com/matlabcentral/answers/94681-how-do-i-implement-drag-and-drop-functionality-in-matlab) - Lati
在您提供的链接示例中,您只能在图形内拖动项目。我想从资源管理器(或Mac上的Finder)中拖动文件到GUI中,然后调用一个函数来读取文件。 - jkazan
@JZKaz,您仍然可以使用相同的方法,唯一需要添加的是比较鼠标位置和您想要放置的元素的位置(我猜这在您的情况下是一个面板)。 - Lati
@Lati,Matlab 是如何知道以下信息的:a)当我将某物拖到图形之外(例如从桌面拖到图形中)时;b)该对象的信息(例如文件路径)? - jkazan
提供一下信息,我修改了Maarten van der Seijs的类,并提供更好的控制DragEnter / DragExist / DragActionChanged / Drop事件的功能,例如拒绝某些文件类型的拖放和更改拖动图标等... 请参见此处那里获取更多信息。 - CitizenInsane
1个回答

1

这篇文章由Maarten van der Seijs在文件交换中解决了它。

它创建了一个回调函数,可以与Java Swing GUI组件配对,如附带演示所示。

它使用了一个Java类,该类是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;
    }
}

然后由MATLAB类进行初始化和调用:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接