MATLAB 调用Java的Jar进行UI设计(个人记录向)

记录一下使用matlab编写UI的过程

在使用MATLAB的guide和app designer做一个绘图UI后,需要将其打包为exe文件。数据处理和计算我放在了后台线程池中执行,组件加载和更新放在主进程。
经过各种尝试,我发现:

  • app designer虽然组件和功能更多,但是它在启动时,窗口组件需要加载很久,性能比guide慢很多;
  • 由于我需要使用table组件,但是guide的table组件只有一个显示功能,其它的功能(如:设置选中行、设置单元格颜色等)基本没有提供。

因此,决定混合Java的swing来优化组件。

findjobj函数

创建好组件后,使用findjobj函数可以找到找到该组件隐藏的Java句柄,但是,在该函数寻找组件句柄时,由于pause的影响,有时反而花费了大量的时间在查找上,我试过将pause注释掉或暂停时间改小,可是之后返回的句柄一直是空,没理解原因。这里放其中一段的代码。

while isempty(jControl) && counter>0
        counter = counter - 1;
        pause(0.005);
        jControl = findTooltipIn(jContainer, specialTooltipStr);
end

后续做法

之后,我就尝试使用Java的swing来写组件,然后打包为JAR文件供matlab调用,其中:

  • JAR中Swing组件需要定义好MATLAB调用的接口,基本是组件更新和数据获取的函数;
  • 此外,Java组件中不定义任何监视器或回调函数,该部分放在Matlab进行实现;
  • 即使在matlab中修改了JDK版本,这个环境也无法打包进去,因此只能使用matlab默认的同版本Java。
    在这里插入图片描述

MATLAB调用JAR文件

1,读取jar文件

javaaddpath可以将jar文件添加到动态路径中,每次添加且程序执行完成后,都需要将其卸载,否则下次执行时将会报错。
在调用javacomponent函数中,会弹出警告,这里将对应警告关闭。

javaPath = "SetJTable.jar";
clear(javaPath)
javaaddpath(javaPath);
warning('off', 'MATLAB:ui:javacomponent:FunctionToBeRemoved')

2,接口调用

这里在matlab中居于自己的需要,编写并调用对应的接口功能。
由于matlab和java之间可以自动装载转换,但依旧需要一些装载转换问题,尤其是混合状态和empty下的装载。
注意:我这里需要:

import com.example.GetUITable.*

有些版本可能这样即可:

import GetUITable.*
classdef UiTable < handle
    % 构建包含表头的复杂JTable
    properties (Access=private)
        GetJavaClass
    end

    methods (Access=public)
        function tableBuild(obj, varargin)
            if nargin == 1
                varargin = {};
            end

            p = inputParser;

            data = javaArray('java.lang.Object', 1, 1);            % Object[][]
            colNames = ["Col1", "Col2"];   % Object[](String 数组)
            % Object[][](空数组)
            % matlab的cell会自动转为Object[], 但 {}会转为null
            groupHeader = javaArray('java.lang.Object', 0, 0);   
            
            % 定义默认值
            addParameter(p, 'data', data);
            addParameter(p, "coluName", colNames);
            addParameter(p, "groupHeader", groupHeader);
            addParameter(p, "multiselect", false);
            addParameter(p, "width", 300);
            parse(p, varargin{:});

            % 对输入数据进行检验
            getData = p.Results.data;
            getColumn = p.Results.coluName;
            dataSize = size(getData);
            if dataSize(2) < length(getColumn)
                getData = [getData, javaArray('java.lang.Object', dataSize(1), length(getColumn) - dataSize(2))];
            end

            obj.GetJavaClass = GetUITable(getData, getColumn, p.Results.groupHeader, p.Results.multiselect, p.Results.width);
        end

        %% 设置类
        % 设置选中行数,需要在嵌入figure之后使用才有效'
        function selectRow(obj, row)
            table = obj.GetJavaClass.getTable();
            if nargin == 1
                table.selectAll();
            else
                % java下标从0开始
                table.setRowSelectionInterval(row-1, row-1);
            end
        end

        % 设置行选中回调
        function setRowSelectedFCN(obj, fun)
            table1 = obj.GetJavaClass.getTable;
            jh = handle(table1, 'CallbackProperties');
            set(jh, 'MouseReleasedCallback', fun);
        end

        % 修改表格全部数据
        function setTableData(obj, data)
            obj.GetJavaClass.changeData(data);
        end

        function setBackColor(obj, col, colors)
            obj.GetJavaClass.setHighlight(col-1, single(colors));
        end
        
        % Input:
        %   data: 维度为[m, n]的cell,m表示需要添加的列数
        %   colNames: 维度为[m]的cell
        %   groupHeader: [m, 3]列的cell,第2-3列需要int32类型
        function addTableColumn(obj, data, colNames, groupHeader)
            if nargin == 3
                obj.GetJavaClass.addColumn(data, colNames);
            else
                obj.GetJavaClass.addColumn(data, groupHeader, colNames);
            end
        end

        function removeTableColumn(obj, colNames)
            obj.GetJavaClass.removeColumn(colNames);
        end

  
        %% 获取类
        % 获取jTable组件       
        function jTable = getScrollPane(obj)
            jTable = obj.GetJavaClass.getScrollPane;
        end

        % 获取选中行
        function rows = getSelectedRow(obj)
            rows = obj.GetJavaClass.getTable().getSelectedRows() + 1;
        end
        
        function data = getData(obj)
            data = obj.GetJavaClass.Data();
        end

    end

    methods (Access = public)
        function obj = UiTable(varargin)
            import com.example.GetUITable.*; 
            % obj.addJarPth;
        end

    end
end

更好做法?

感觉可以在Java中写好UI和回调,并在Java回调中调用matlab的function进行计算。deepseek说只要在首次调用matlab的function时,才会加载MCR,考虑能否在启动时,新建一个进程来专门启动MCR? 这样就不用在首次启动exe时等待十多秒钟来等待MCR加载?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值