Reputation: 389
MATLAB possesses all features I need in my application, except for one - a 21st century look to the applications it builds. The old UI controls with the skin from the 90s just don't cut it anymore. Are there ways to customize the GUI of the compiled window itself? I know of App Designer for MATLAB (which is an alternative for GUIDE as I understood) but that's not close enough. For example, I want a complete flat design look with sprites/buttons/etc drawn in Photoshop for my built application.
Would an external C library/framework be able to build a custom GUI when compiling an application?
I've tried to google this question and it seems like nobody cares about design in the scientific community. I'm not quite sure how to phrase my question, apologies. I hope some of you have a bit of experience with this.
P.S.: Below is the look I'd like to achieve:
Upvotes: 5
Views: 1946
Reputation: 4855
As described in my previous comment, and starting from R2019b, you can use uihtml components in new web-based uifigure (introduced in R2016a) to customize style of elements appearing on screen via css
+ javascript
Here below is a very simple example for a css-styled button:
First the matlab code (TestUiHtml.m
):
function [] = TestUiHtml()
%[
% Create the figure and layout
fig = uifigure('Name', 'Test uihtml', 'Color', [1 1 1]);
grid = uigridlayout('Parent', fig, 'ColumnWidth', { '1x', '1x' }, 'RowHeight', {200, '1x' }, 'BackgroundColor', fig.Color);
% Add a uihtml element (that will act like a button using html+css+javascript)
button = uihtml('Parent', grid, 'HTMLSource', 'myway.html', 'DataChangedFcn', @(s,e)onBtnClicked(fig));
% Button layout
button.Layout.Row = 1; button.Layout.Column = [1 2];
%]
end
function [] = onBtnClicked(fig)
%[
uialert(fig, 'World!', 'Clicked', 'Icon', 'info');
%]
end
NB: Above code simply adds in the figure a uihtml
component whose property HTMLSource
points to the html content you want to have.
Here is the html code to describe the custom uihtml
component content (myway.html
):
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="myway.css">
<script type="text/javascript" src="myway.js"></script>
</head>
<html>
<body>
<div class="container">
<button class="skewBtn blue" id="btn">Hello!</button>
</div>
</body>
</html>
NB: It is not mandatory to have a fully well-formed html code (i.e. just a <button style="...">Hello</button>
would do).
The linked css code to style the html content (myway.css
):
body {
background-color: transparent;
}
.container {
display: flex;
justify-content: space-evenly;
align-items: center;
flex-wrap: wrap;
height: 97vh;
}
.container .skewBtn {
width: 180px;
height: 80px;
outline: none;
cursor: pointer;
background: none;
transition: 0.5s;
font-size: 24px;
border-radius: 5px;
font-family: "Lato", sans-serif;
}
.container .skewBtn:hover {
border: none;
color: white;
font-size: 28px;
transform: scale(1.1);
}
.blue {
border: 2px solid #1976D2;
color: #1976D2;
}
.blue:hover {
background-color: #1976D2;
transition: all 0.3s ease-in-out;
}
And finally the javascript code for event/data marshalling between matlab and the html-based component ... or for more advanced programming logic, if any, for the html-content (myway.js
):
function setup(htmlComponent)
{
document.getElementById("btn").addEventListener("click", function(event)
{
htmlComponent.Data = 1234; // dummy value to fire event on matlab side
});
}
Marshalling is ensure via the data
property of a htmlComponent
object which both sides (i.e. matlab/javascript) are listening to for changes. Matlab automatically uses jsonencode/jsondecode in the background so you can pass back and forth almost any structure/values you need directly.
And voilà ... a nice-and-responsive css-styled button in matlab's figure:
It would be of course better to refactor above code as a uibuttonex
class modeled on existing uibutton property name/value pairs.
Sarting from R2021a it is eventually possible to add it to app designer library of components as described here (I personally don't use the designer and prefer to code interfaces programmatically).
Some remarks
It is not possible to directly style exiting uibutton
, uipanel
, uitab
, etc... elements => Mathwork does not allow to access uifigure's html nor to inject css/javascript in it easily (see following undocumented-matlab thread and mlapptools project to try to cheat things). For instance a uibutton
does not translate to directly <button>
markup in uifigure's source but a lot of imbricated <div>
, so it is very difficult to style (and will probably change from one release to another).
I would not recommend to create a single uihtml
element in the figure and code everything in html+css+javascript, but I would rather recommend to create small and simple custom uibuttonex
, etc elements ... else you'll have to deal with a single data
blob to connect you interface with the matlab code which can be tricky and difficult to reuse.
Unfortunately it is yet not possible to create custom html-containers in which you can add other child ui-elements (custom or non-custom) ... say bye-bye to create containers similar to uix.GridFlex, uix.CardPanel from the wonderful GUI Layout toolbox or to creating nicely styled uitabex
, etc... This is really a missing part !
Looking at source code of uifigure
pages, custom ui-elements are also embedded in <iframe></iframe>
markups, so it is not possible to inject some global css/javascript code (i.e. you'll have to repeat this for each uihtml
element you create). It is not possible (or difficult) then to have multiple uihtml elements to interact with each-other (unless coding everything in a single page or passing through matlab code/events only).
Addendum : Here is a solution to get css-style from parent, unfortunately this does not solve one need to inject this css in the main uifigure source (well this can be done in javascript ... something like if !exist(parent.elements where id="mycss") => parent.document.inject(lalala)
)
Mathworks is going the good direction with uifigure
and html
in the background, but it's still a bit too locked for now and missing important containers from the GUI Layout toolbox.
NB: I tried the GUI Layout toolbox elements in uifigure
... some are working (with lot of resizing bugs), other are not working at all (GridFlex). Maybe a new version of the toolbox will come.
Charting
For modern charting you can use javascript libraries like D3js, SciChart, LightningChart, or others!!.
There is some example using D3 on fileexchange
Upvotes: 9