如何用MATLAB实现拖拽控件

一般来说,MATLAB自身的GUI是不能够实现将文件夹或者文字拖拽进去进行读取的,就像用QQ邮箱上传文件一样:
在这里插入图片描述
然后我们用MATLAB实现的效果如下:
在这里插入图片描述
这个控件并不是用过MATLAB自带的函数实现的,而是通过调用Java来实现,先要定义好Java的对象,然后在MATLAB程序中进行调用,使用起来我们并不需要知道其中的原理,只需要当做黑匣子就可以了。


一定不要嫌麻烦,我会给出文件夹下载可以直接使用,你调整一下代码弄成自己的就好了,下面这个文件保存为dndcontrol.m


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

这个是一个调用的接口,我们直接将它保存下来,作者给我们提供了一个demo,直接在命令行里输入dndcontrol.demo()即可看到写好的一个例子。
同时,我们也需要保存下面的文件:

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;
    }
}    

你需要将这个.java文件编译成.class文件才能直接使用,所以我这里直接给出.class文件的下载,保存在.m文件的路径上就可以了,与上一个dndcontrol.m保持在同一路径。

close all
clear all
jLabel = javaObjectEDT('javax.swing.JLabel');
newIcon = javax.swing.ImageIcon('drop.png');
jLabel.setIcon(newIcon);
hFig = figure();
[~,hContainer] = javacomponent(jLabel,[],hFig);
set(hContainer,'Units','normalized','Position',[0.5 0 0.2 0.2]);
dndcontrol.initJava(); 
dndcontrol(jLabel,@getFile,@getString);

function getFile(~,evt)
disp('文件路径:')
celldisp(evt.Data)
end
function getString(~,evt) 
       disp('文字:') 
       disp(evt.Data)
end

上面这个是我写的一个例子,效果为上面的第二幅图,

jLabel = javaObjectEDT('javax.swing.JLabel');
这个是我们需要的控件类型,这里是一个label,
不同的类型你可以查看Java swing 控件基础,搜了之后可以直接看明白。

newIcon = javax.swing.ImageIcon('drop.png');
jLabel.setIcon(newIcon);
这个是用来换图标的,就是相当于label的背景图,
和我们平常使用GUI时的cdata设置控件不一样,但是和更改GUI的左上角图标方法类似。

[~,hContainer] = javacomponent(jLabel,[],hFig);
set(hContainer,'Units','normalized','Position',[0.5 0 0.2 0.2]);
这两句就是说把这个Java控件加到MATLAB指定的figure上去

dndcontrol(jLabel,@getFile,@getString);
我们需要注意的就是这个,第一个参数是上面的Java控件的handle,
后两个参数是分别拖拽文件和文本调用的函数

在这里插入图片描述
这个是拖入文件的图片
在这里插入图片描述
这个是拖入文本得到的效果。


下面是代码文件,可以直接使用
百度云链接
提取码:o2m1

发布了50 篇原创文章 · 获赞 66 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43157190/article/details/103645324