Open thiblab opened 6 years ago
Regarding the first issue, as the error says - more time needs to pass between the creation of the UIFigure and running mlapptools
. Here's what you can try:
mlapptools.setTimeout(hUIFig, 10);
(try 15
, 20
etc. if 10
doesn't work for you).pause
before calling mlapptools
(so for example: pause(5); mlapptools.getWebElements(...)
).Regarding the 2nd issue - when exactly does it happen? When you run the code, or after you close a uifigure
? Please provide exact steps to reproduce. If you need to upload a .mlapp
file, please do so. I have R2018a and R2018b so I can test it locally.
Thank you for your answer @Dev-iL . To answer your remarks :
Set a longer timeout: mlapptools.setTimeout(hUIFig, 10); (try 15, 20 etc. if 10 doesn't work for you). Add a pause before calling mlapptools (so for example: pause(5); mlapptools.getWebElements(...)).
I tested what you say but the issue n°2 is now showing 100% of the time...
Regarding the 2nd issue - when exactly does it happen? When you run the code, or after you close a uifigure? Please provide exact steps to reproduce. If you need to upload a .mlapp file, please do so. I have R2018a and R2018b so I can test it locally.
It happens just after starting the interface (3 -4 seconds of delay). Actually, the [win, widgetID] = mlapptools.getWebElements(app.TabGroup)
function is in the startUpFcn
.
I give you my code (I would prefer in private) but you will have many parts missing...
Thanks
@thiblab Please try to create a new App with just the minimum code required to reproduce the issue, then post the code of the App here.
Did you try saving the code of the App in a regular .m
file and running it? I suspect that this issue happens because you run the code from within the App Designer.
The issue 2 seems indeed appear only with App Designer. So in which conditions I have to use mlappTools ? When using the code of App Designer but not using App Designer itself ?
Yes, I would say that this is a sound course of action (at least that's how I always use it, because I used to have various problem running App Designer, so I ended up creating UIFigures completely programmatically)...
You see, the App Designer itself is a uifigure (and hence, a "browser window"), so there must be some issues when we try making MATLAB have two browser windows communicating with each other.
Sorry, I replied too fast. Below is a simple code that I am running as.m
file. And unfortunately, the issue 2 is still showing...
The behavior is actually strange : Sometimes it works, and when it works both [win, widgetID]
are returned. When it crashes the widgetID
isn't return so it seems that the issue come from this parameter.
classdef app2 < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
TabGroup matlab.ui.container.TabGroup
Tab matlab.ui.container.Tab
Tab2 matlab.ui.container.Tab
end
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
[win, widgetID] = mlapptools.getWebElements(app.TabGroup)
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'UI Figure';
% Create TabGroup
app.TabGroup = uitabgroup(app.UIFigure);
app.TabGroup.Position = [100 82 325 280];
% Create Tab
app.Tab = uitab(app.TabGroup);
app.Tab.Title = 'Tab';
% Create Tab2
app.Tab2 = uitab(app.TabGroup);
app.Tab2.Title = 'Tab2';
end
end
methods (Access = public)
% Construct app
function app = app2
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end
I can reproduce your problem.
If your use-case permits it, I suggest you only take the code that creates components (and callbacks if there are any), then apply your customizations at the end.
%% Create UIFigure and add components:
app = struct(); % < This is just to keep the same structure for the rest of the code.
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 640 480];
app.UIFigure.Name = 'UI Figure';
% Create TabGroup
app.TabGroup = uitabgroup(app.UIFigure);
app.TabGroup.Position = [100 82 325 280];
% Create Tab
app.Tab = uitab(app.TabGroup);
app.Tab.Title = 'Tab';
% Create Tab2
app.Tab2 = uitab(app.TabGroup);
app.Tab2.Title = 'Tab2';
%% Customize using mlapptools:
pause(5); % might need to be longer, depending on your computer.
[win, widgetID] = mlapptools.getWebElements(app.TabGroup);
...
In conclusion - until we find a way to better way to avoid these crashes, you should only use mlapptools
after your uifigure was fully created (just like in the examples).
Thanks for your answer, but actually it has fixed the issue. I can put pause(30)
or more, sometimes it's still crashing. I don't get why it does this, in both cases the component are already created right ? So what would be the inherent problem ?
Actually, I want to be able to personalize the Tab Group (cf screenshot) (Size of click panel, Selected / Unselected Color, Font, Font Size, Underlying...). Am I able to do this with mlappTools ?
I didn't try doing anything like that myself, but I expect that it is possible, yes. I would also advise you to use the documented ways to edit components as much as possible, and only when you reach their limit, switch to mlapptools
.
Actually, the documented way doesn't offer any possibility to customize the TabGroup
object. This is Why I wanted to try mlapptools
.
Today I tried the 'manual' way to retrieve tags and ID and the issue is the same, and appear only with the TabGroup
object but works fine with other objects. Here is the code if you want to reproduce it. The URL is found, but the script crashes when retrieving the tag
of the associated TabGroup
.
classdef DOMdemo < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure % UI Figure
LabelTextArea matlab.ui.control.Label % Text Area
TextArea matlab.ui.control.TextArea % This is some text.
TabGroup matlab.ui.container.TabGroup
Tab matlab.ui.container.Tab
Tab2 matlab.ui.container.Tab
end
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
% Customizations (aka "MAGIC GOES HERE"):
warning off Matlab:HandleGraphics:ObsoletedProperty:JavaFrame
warning off Matlab:structOnObject
while true
try
win = struct(struct(struct(app.UIFigure).Controller).PlatformHost).CEF;
disp(win.URL)
data_tag = char(struct(app.TabGroup).Controller.ProxyView.PeerNode.getId)
widgetId = win.executeJS(['dojo.getAttr(dojo.query("[data-tag^=''' data_tag '''] > div")[0],"widgetid")']);
break
catch
disp('Not ready yet!');
pause(0.5); % Give the figure (webpage) some more time to load
end
end
end
end
% App initialization and construction
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure
app.UIFigure = uifigure;
app.UIFigure.Position = [100 100 500 500];
app.UIFigure.Name = 'UI Figure';
setAutoResize(app, app.UIFigure, true)
% Create LabelTextArea
app.LabelTextArea = uilabel(app.UIFigure);
app.LabelTextArea.HorizontalAlignment = 'right';
app.LabelTextArea.Position = [16 73 62 15];
app.LabelTextArea.Text = 'Text Area';
% Create TextArea
app.TextArea = uitextarea(app.UIFigure);
app.TextArea.Position = [116 14 151 60];
app.TextArea.Value = {'This is some text.'};
% Create TabGroup
app.TabGroup = uitabgroup(app.UIFigure);
app.TabGroup.Position = [100 82 325 280]
% Create Tab
app.Tab = uitab(app.TabGroup);
app.Tab.Title = 'Tab';
% Create Tab2
app.Tab2 = uitab(app.TabGroup);
app.Tab2.Title = 'Tab2';
end
end
methods (Access = public)
% Construct app
function app = DOMdemo()
% Create and configure components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end
If you have to use mlapptools
in startupFcn
, you can do so using a timer
(the timer runs on a different thread, which allows the App to properly finish initializing):
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
start(timer('TimerFcn', @(x,y)app.customizeElements(), 'StartDelay', 10));
end
function customizeElements(app)
[hWin, widgetID] = mlapptools.getWebElements(app.TabGroup);
[childIDs] = mlapptools.getChildNodeIDs(hWin, widgetID);
mlapptools.setStyle(hWin, 'background', 'transparent', childIDs(2));
[childIDs] = mlapptools.getChildNodeIDs(hWin, childIDs(2));
mlapptools.setStyle(hWin, 'background', 'black', childIDs(4));
end
end
Note that it will only crash if the timer delay is too short.
Summary
I am having troubles when using the following function :
[win, widgetID] = mlapptools.getWebElements(app.TabGroup);
The issue is quite random. I can have issue 1 or issue 2, you can find below. I don't understand any of them. About issue 2 I looked what has been said about it on Matlab forum, like upgrade driver etc.. But I did it, tried the function on several computer and I still have it.
Problem Description
Issue 1 :
Issue 2 :
Specifications
mlapptools
version 2018