如何以比官方记录更多的方式自定义 App Designer 图形?

How to customize App Designer figures in more ways than officially documented?

最近发表的 article in UndocumentedMatlab, mentions that App Designer figures are actually web pages using the Dojo Toolkit。这意味着我们 可以 理论上直接操纵 HTML DOM 以实现某些 UI 自定义,否则这些自定义是不可用的。

下面是 App Designer 图窗定义的示例,出现在 App Designer 生成的 .m 文件中(在 MATLAB R2016a 上):

classdef domDemo < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure     matlab.ui.Figure          % UI Figure
        LabelListBox matlab.ui.control.Label   % List Box
        ListBox      matlab.ui.control.ListBox % Item 1, Item 2, Item 3, It...
    end

    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)

        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 260 147];
            app.UIFigure.Name = 'UI Figure';
            setAutoResize(app, app.UIFigure, true)

            % Create LabelListBox
            app.LabelListBox = uilabel(app.UIFigure);
            app.LabelListBox.HorizontalAlignment = 'right';
            app.LabelListBox.Position = [50 93 44 15];
            app.LabelListBox.Text = 'List Box';

            % Create ListBox
            app.ListBox = uilistbox(app.UIFigure);
            app.ListBox.Position = [109 36 100 74];

        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

...看起来像这样:

根据 uilistbox (which redirects us to the page on Check Box Properties 的完整 属性 列表的文档),没有办法操纵例如列表项的文本对齐方式。如果是,

Question: How do we manipulate the ListBox in the example app such that its contents become center-aligned, even though such a setting is not available to us?

为了成功完成这项任务,我们需要做几件事:

  • 找到 HTML/CSS 所在的位置(这样我们就可以操纵它们)。
  • 找到我们要编辑的 DOM 的哪个元素。
  • 找出我们需要做出的改变。
  • 找到使用 MATLAB 操作元素的方法。

逐步工作:

1。找出图形的 HTML/CSS 在哪里 stored/located

win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
URL = win.URL; % Needed only for testing in browser

2。找到我们需要编辑DOM的哪个元素

data_tag = char(struct(app.ListBox).Controller.ProxyView.PeerNode.getId);

使用浏览器验证:

3。找出我们需要做出的改变是什么

由于我们要操纵文本对齐方式,我们 google 一些相关关键字并找到 CSS text-align property。那我们手动试试看是否真的有效:

4。找到一种使用 MATLAB

操作元素的方法

使用dojo.style and dojo.query:

win.executeJS(['dojo.style(dojo.query("[data-tag^=''' data_tag ''']")[0],"textAlign","center")']);


此答案的完整代码:

classdef domDemo < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure     matlab.ui.Figure          % UI Figure
        LabelListBox matlab.ui.control.Label   % List Box
        ListBox      matlab.ui.control.ListBox % Item 1, Item 2, Item 3, It...
    end

    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
          % Customizations (aka "MAGIC GOES HERE"):
          drawnow; rez = [];
          warning off MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame
          warning off MATLAB:structOnObject            
          while ~strcmp(rez,'"center"')
            try                
              % 1. Get a handle to the webwindow:
              win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
              % 2. Find which element of the DOM we want to edit (as before):
              data_tag = char(struct(app.ListBox).Controller.ProxyView.PeerNode.getId);    
              % 3. Manipulate the DOM via a JS command
              rez = win.executeJS(['dojo.style(dojo.query("[data-tag^=''' ...
                data_tag ''']")[0],"textAlign","center")']);
            catch
              pause(1); % 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 260 147];
            app.UIFigure.Name = 'UI Figure';
            setAutoResize(app, app.UIFigure, true)

            % Create LabelListBox
            app.LabelListBox = uilabel(app.UIFigure);
            app.LabelListBox.HorizontalAlignment = 'right';
            app.LabelListBox.Position = [50 93 44 15];
            app.LabelListBox.Text = 'List Box';

            % Create ListBox
            app.ListBox = uilistbox(app.UIFigure);
            app.ListBox.Position = [109 36 100 74];

        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