MATLAB 混合Java进行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加载?
2807

被折叠的 条评论
为什么被折叠?



