MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

Приложения с GUI и дескрипторная графика

Приложение c использованием ActiveX-компоненты sgrid.ocx

В этом разделе мы рассмотрим использование ActiveX-компоненты sgrid.ocx версии 1.1, которая вместе с документацией sgrid.hlp может быть скачана с http://adfsoft.hypermart.net/sgrid/. Данная свободно распространяемая компонента предназначена для создания таблиц. Мы используем ее для написания приложения с графическим интерфейсом пользователя sgrid_demo, окно которого приведено ниже.

Figure 1

Таблица в окне приложения sgrid_demo создана при помощи ActiveX-компоненты sgrid.ocx. В таблицу можно занести данные или вручную, или нажав кнопку Load… и выбрав нужный файл с текстовыми данными (в нем должен быть прямоугольный массив чисел, разделенных пробелами). Кнопки Bar и Bar3 предназначены для отображения данных на осях при помощи обычной или трехмерной столбцевой диаграммы, причем прямоугольную область, содержащую отображаемые данные,  можно предварительно выделить при помощи мыши в таблице. Кнопка Clear служит для очистки осей.

Описываемое в этом разделе демонстрационное приложение является несколько измененным примером приложения actx_grid.m, которое находится в <КаталогMATLAB>\help\techdoc\matlab_external\examples\, комментарии к нему приведены в справочной системе MATLAB в разделе External Interfaces: COM and DDE Support (Windows Only): Using MATLAB as an ActiveX Client: Example — Grid ActiveX Control in a Figure.

Регистрация ActiveX-компоненты

Перед использованием ActiveX-компоненты sgrid.ocx в приложениях MATLAB ее следует зарегистрировать (большинство стандартных компонент этого не требуют). Для регистрации компоненты в Windows следует выполнить команду regsvr32, указав имя файла с ActiveX-компонентой в качестве ее параметра

regsvr32 sgrid.ocx

Эту команду можно выполнить или в окне Запуск программы, которое появляется после Пуск > Выполнить в Windows (но тогда вместо sgrid.ocx следует набрать полное имя файла, содержащего ActiveX-компоненту), или прямо в командной строке MATLAB. Для регистрации компоненты из командной строки MATLAB следует:

  1. сделать в MATLAB каталог с sgrid.ocx текущим;
  2. в командной строке выполнить системную команду regsvr32 (в MATLAB это делается при помощи восклицательного знака)
    >> !regsvr32 sgrid.ocx
    

Для просмотра всех ActiveX-компонент в MATLAB существует функция actxcontrollist, которая возвращает массив ячеек с информацией о всех установленных ActiveX-компонентах

  >> C = actxcontrollist 
  C =  
  '2D  Axum Graph'                    [1x21  char]    [1x42 char] 
  '3-D  Plot'                  'MathSoft.Plot3D.1'    [1x36  char] 
  ........................... 

Каждая строка массива C соответствует своей компоненте, в частности для компоненты sgrid.ocx выводится следующая информация, которую лучше смотреть в Array Editor, поскольку в командном окне длинные строки, содержащиеся в ячейках, не отображаются, а вместо них выводится тип и размер содержимого ячейки:

  • 'Simple Grid Control' — имя AxctiveX-компоненты;
  • 'SGRID.SgCtrl.1' — идентификатор (ProgID), который понадобится нам для внедрения ActiveX-компоненты с целью создания таблицы в окне приложения;
  • 'C:\MATLAB71\work\ActiveX\sgrid.ocx' — полное имя файла, содержащего AxctiveX-компоненту.

Разберем теперь, как создать таблицу при помощи AxctiveX-компоненты, ее основные свойства и методы.

Создание окна с ActiveX-компонентой, ее свойства и методы

Размещение ActiveX-компоненты

Для помещения ActiveX-компоненты в графическое окно служит функция actxcontrol, ее входными аргументами являются

  • идентификатор ActiveX-компоненты (ProgID);
  • положение компоненты в графическом окне, задаваемое вектором [x y  width  height], где x, y — координаты левого нижнего угла компоненты относительно левого нижнего угла графического окна, а  width  и height, соответственно, ширина и высота компоненты в пикселях;
  • указатель на графическое окно.

Выходной аргумент функции actxcontrol служит для установления интерфейса к созданному объекту, обращения к его свойствам и методам.

Последовательность команд (функция figure возвращает указатель на созданное ею графическое окно)

  hF = figure; 
  pos = [10 300 40 0 100]; 
  hgrid = actxcontrol('SGRID.SgCtrl.1', pos, hF);

приводит к окну, содержащему таблицу:

Figure 2
Графическое окно с добавленной компонентой sgrid.ocx

Свойства ActiveX-компоненты

По умолчанию, у создаваемой таблицы 256 столбиков и 16383 строк, в чем можно убедиться, выводя значения свойств NRows и NColumns созданного объекта-таблицы

  num_rows = hgrid.NRows 
  num_rows = 
    16383 
  num_cols = hgrid.NColumns 
  num_cols = 
    256

Число строк и столбцов в таблице может быть изменено при помощи этих же свойств NRows и NColumns. Например

  hgrid.NRows = 3; 
  hgrid.NColumns = 4;

приводит к следующей таблице:

Figure 3
Изменение числа строк и столбцов (свойства NRows и NColumns)

Для получения всех свойств AxtiveX-компоненты используется метод get

  hgrid.get 
  Row: 0 
  Col: 0 
  BackColor: 16777215 
  ..........

Рассмотрим использование некоторых из свойств sgrid.ocx. Значения свойств Row и Col определяют текущую строку и столбец, т.е. текущую ячейку, стоящую на их пересечении. Нумерация строк и столбцов начинается с нуля. Свойство Number позволяет получить или задать число в текущей ячейке. Например

  hgrid.Row = 1; 
  hgrid.Col = 2; 
  hgrid.Number = 344;

приводит к занесению числа 344 в ячейку C2:

Figure 4
Добавление в ячейку текста (свойства Row, Col и Number)

Присваивание

  B = hgrid.Number

приводит к занесению в переменную B числа 344. В пустых ячейках по умолчанию содержится нулевое значение

  hgrid.Row = 2; 
  hgrid.Col = 1; 
  C = hgrid.Number 
  C = 
  0

Для добавления текста в ячейку таблицы служит ее свойство Text (предварительно ячейку надо сделать текущей), например

  hgrid.Row = 1; 
  hgrid.Col = 1; 
  hgrid.Text = 'TEXT';

добавит текст в ячейку B2:

Figure 5
Добавление в ячейку текста (свойства Row, Col и Text)

Среди свойств sgrid есть, в частности, три свойства, отвечающие за цветовое оформление таблицы:

  • BackColor — цвет фона ячеек;
  • ForeColor — цвет шрифта;
  • SeparatorColor — цвет разделительных линий.

Цвет задается целым числом в формате RGB, тип — OLE_COLOR, являющийся двойным словом (сокращение OLE значит Objects Linked and Embedded, т.е. присоединенные и встроенные объекты). В младшие восемь разрядов числа записывается количество красного цвета (от 0 до 255), в следующий байт —  количество зеленого цвета, затем количество синего цвета. Для получения, например, таких зеленых ячеек с красным текстом и синими разделительными линиями:

Figure 6
Изменение цвета (свойства BackColor, ForeColor и SeparatorColor)

достаточно выполнить операторы

  % задание цвета  шрифта 
  red = 255; 
  green = 0; 
  blue = 0; 
  fore_color = red + bitshift(green, 8) + bitshift(blue, 16); 
  hgrid.ForeColor = fore_color; 
  % задание цвета  фона 
  red = 0; 
  green = 255; 
  blue = 0; 
  back_color = red + bitshift(green, 8) + bitshift(blue, 16); 
  hgrid.BackColor = back_color; 
  % задание цвета  разделителя 
  red = 0; 
  green = 0; 
  blue = 255; 
  separator_color = red + bitshift(green, 8) + bitshift(blue, 16); 
  hgrid.SeparatorColor = separator_color;

Здесь использована функция bitshift, которая осуществляет побитовый сдвиг на указанное число бит влево, например

  a = 121 
  a = 
  121 
  dec2bin(a) 
  ans = 
  1111001 
  as = bitshift(121, 8) 
  as = 
  30976 
  dec2bin(as) 
  ans = 
  111100100000000 — сдвиг 1111001 на восемь бит влево.

Количество каждого из цветов в цвете, заданном одним числом, можно получить при помощи обратных операций

  red = bitand(color, hex2dec('ff')) 
  green = bitand(color, hex2dec('ff00')) / 255 
  blue = bitand(color, hex2dec('ff0000')) / 65536

Здесь color — заданный цвет, функция bitand осуществляет побитовое «И», а hex2dec — преобразование шестнадцатеричного числа в десятичное.

Завершим обзор свойств компоненты sgrid.ocx ее свойством Font. Получим значение этого свойства

  hgrid.Font 
  ans = 
  Interface.Standard_OLE_Types.Font

Оно должно быть OLE-шрифтом. Текущее значение свойства Font может быть получено при помощи метода get, который возвращает структуру MATLAB с полями, соответствующими текущим параметрам шрифта

  F = hgrid.Font.get  
  F = 
  Name: 'MS Shell Dlg' 
  Size: 8.2500 
  Bold: 0 
  Italic: 0 
  Underline: 0 
  Strikethrough: 0 
  Weight: 400 
  Charset: 204

Для изменения свойства Font компоненты sgrid средствами MATLAB используется метод set, свойства и их значения задаются парами, например.

  hgrid.Font.set('Name', 'Arial', 'Size', 12, 'Bold', 1, 'Italic', 1, 'Underline', 1)

приводит к таблице со следующим шрифтом:

Figure 7
Изменение шрифта (свойство Font)

Методы ActiveX-компоненты

Разберем кратко методы ActiveX-компоненты. Их список можно получить при помощи

  hgrid.methods 
  Methods for class  COM.SGRID_SgCtrl_1: 
  AboutBox        EditCut         GetTypeRC        addproperty       interfaces       release          
  ClearAll        EditDelete      Refresh          delete            invoke           save             
  ClearRange      EditPaste       Scale            deleteproperty    load             send             
  EditClear       Format          SetColWidth      events            move             set              
  EditCopy        GetSelection    SetSelection     get               propedit

С прописной буквы начинаются методы ActiveX-компоненты, а со строчной — функции MATLAB, реализующие методы работы с ActiveX-компонентами.

Для задания свойств ActiveX-компоненты при помощи ее диалогового окна предназначен метод propedit, его вызов

  hgrid.propedit

приводит к появлению диалогового окна, работа в котором достаточно очевидна.

Figure 8 Диалоговое окно со свойствами ActiveX-компоненты

Метод move предназначен для получения текущей позиции компоненты в графическом окне или для ее задания. Например,

  pos = move(hgrid)

возвращает ровно тот вектор, который был указан при создании компоненты функцией actxcontrol (см. Размещение ActiveX-компоненты)

  pos = 
  10  300  400  100

Операция

  move(hgrid, [120 300 400 100])

приводит к перемещению таблицы к правому краю окна.

Figure 9
Перемещение ActiveX-компоненты (метод move)

Метод move можно было вызывать и так:

  hgrid.move( [120  300 400 100])

Методы save и load предназначены для сохранения свойств ActiveX-компоненты в файле и их последующего восстановления. Сохраним таблицу в файле data

  save(hgrid, 'data') 
  затем изменим цвет ячеек на желтый: 
  red = 255; 
  green = 255; 
  blue = 0; 
  back_color = red + bitshift(green, 8) + bitshift(blue, 16); 
  hgrid.BackColor = back_color;

и затем восстановим таблицу, считав сохраненные свойства из файла

  load(hgrid, 'data')

Figure 10

Figure 11

Figure 12

Сохранение свойств save(hgrid, 'data')

Изменение цвета hgrid.BackColor = back_color;

Чтение свойств из файла load(hgrid, 'data')

Все методы и функции MATLAB для работы с ActiveX-компонентами приведены в справочной системе MATLAB в разделе External Interfaces Reference: Component Object Model and ActiveX: COM Client.

События ActiveX-компоненты

Для получения свойств ActiveX-компоненты служит метод events

  hgrid.events

  Error = void Error(int16 Number, string Description, int32 Scode,
          string Source, string HelpFile, int32 HelpContext, bool CancelDisplay)
  Сlick = void Click() 
  DblClick = void DblClick() 
  MouseDown = void MouseDown(int16 Button, int16  Shift, Variant x, Variant y) 
  MouseUp = void MouseUp(int16 Button, int16  Shift, Variant x, Variant y) 
  EndEdit = void EndEdit(string EditString,  int16 Cancel) 
  Modified = void Modified() 
  ReadyStateChange = void ReadyStateChange() 
  TopLeftChanged = void TopLeftChanged()

Для программирования событий в приложениях MATLAB с графическим интерфейсом используется метод registerevent, который предназначен для связывания события ActiveX-компоненты  с соответствующей функцией обработки, написанное на языке MATLAB. В следующих разделах мы рассмотрим программирование событий на примере создания приложения с компонентой sgrid как без среды визуального программирования GUIDE, так и при помощи GUIDE.

Создание sgrid_demo без среды GUIDE

Приложение sgrid_demo состоит из основной функции sgrid_demo с перечисленными ниже вложенными функциями (программирование приложений с графическими интерфейсом пользователя  с использованием вложенных функций описано в разделе Использование вложенных функций в приложениях GUI. Файл-функция для окна, возвращающая введенные в него параметры.):

  • MouseUp_fun — обработка отпускания кнопки мыши в таблице;
  • btnLoad_Callback — обработка нажатия на кнопку Load...;
  • btnBar_Callback — обработка нажатия на кнопку Bar;
  • btnBar3_Callback — обработка нажатия на кнопку Bar3;
  • btnClear_Callback — обработка нажатия на кнопку Clear;
  • delete_fun — обработка закрытия окна приложения.

В функции sgrid_demo создается графическое окно, причем с его событием DeleteFcn, которое возникает при удалении окна, связывается функция delete_fun. В ней удаляется компонента sgrid при помощи функции delete. Далее в sgrid_demo создаются оси и четыре кнопки Load…, Bar, Bar3 и Clear, с событием Callback каждой из которых связывается своя функция. Затем при помощи actxcontrol создается объект hgrid — ActiveX-компонента sgrid заданных размеров, указывается число ее строк и столбцов и задается ширина столбцов. Когда пользователь выделяет область в таблице и отпускает кнопку мыши возникает событие MouseUp компоненты sgrid. С этим событием связывается функция MouseUp_fun при помощи метода registerevent. После внедрения компоненты создается пустой массив данных DATA, который будет содержать выделенные в таблице данные и использоваться в других функциях обработки событий. Указатель на графическое окно делается видимым только для функций обработки событий (свойство HandleVisibility  устанавливается в 'callback') с целью предотвращения случайного изменения окна пользователем вводимыми командами.

В функции MouseUp_fun обработки отпускания клавиши мыши в таблице входной аргумент называется varargin. Это зарезервированное слово MATLAB для списка входных аргументов функции, число которых может быть произвольным. Список входных аргументов varargin является массивом ячеек.

В документации к sgrid описан интерфейс MouseUp следующим образом:

  MouseUp (Button, Shift, x, y)

где

  • аргумент Button предназначен  для определения отпущенной кнопки мыши (левая или правая кнопка);
  • аргумент Shift предназначен для определения нажатой клавиши Shift, Alt или Ctrl при отпускании кнопки мыши;
  • аргументы x и y предназначены для получения координат текущего положения курсора мыши в таблице.  

В функцию MouseUp_fun передаются следующие аргументы (ячейки входного аргумента массива varargin):

  • varargin(1) — имя объекта (ActiveX-компоненты);
  • varargin(2) — идентификатор объекта;
  • varargin(3 : end-2) — аргументы MouseUp;
  • varargin(end-1) — структура с полями:
    • Type — тип события =  'MouseUp';
    • Source — источник, принимающий значение имени ActiveX-компоненты;
    • EventID — идентификатор события;
    • Button — отпущенная кнопка мыши (1 — левая, 2 — правая);
    • Shift — одновременно удерживаемая клавиша (1 — Shift, 2 — Ctrl, 4 — Alt);
    • x и y — координаты текущего положения курсора мыши в таблице;
  • varargin(end) — имя события.

Про написание функций для обработки событий ActiveX-компонент написано в справочной системе MATLAB в разделе External Interfaces: COM and DDE Support (Windows Only): MATLAB COM Client Support: Writing Event Handlers.

В функции MouseUp_fun происходит обращение к свойству GetSelection компоненты sgrid

  [row_start, col_start, row_end, col_end] = hgrid.GetSelection(1, 1, 1, 1, 1); 

В MATLAB нет передачи аргументов по ссылке, поэтому используется список выходных аргументов (входные могут быть любыми). Далее в функции MouseUp_fun инициализируется нулями массив DATA, его размеры совпадают с размерами выделенной в таблице прямоугольной области, и в цикле в элементы массива DATA записываются числа из ячеек (нумерация строк и столбцов в sgrid начинается с нуля). Для получения числового значения ячейка делается текущей (при помощи свойств Col и Row) и числовое значение извлекается с применением свойства Number. Для проверки типа содержимого ячейки можно использовать метод GetTypeRC.

  t = hgrid.GetTypeRC(i, j)

где

  • t == 0 для пустой ячейки;
  • t == 1 для ячейки с текстом;
  • t == 2 для ячейки с числом;
  • t == 3 для ячейки с формулой.

В функции btnLoad_Callback, обрабатывающей событие Callback кнопки Load..., открывается диалоговое  окно выбора файла с фильтром на расширение dat и если пользователь выбрал файл (FName равно 0, если пользователь нажал в окне Cancel, иначе FName содержит имя выбранного файла, а PName — путь к нему) происходит формирование полного имени файла сцеплением строк, считывание из него данных в массив DATA при помощи функции load (предполагается, что в файл записана матрица в текстовом виде), удаление всех данных из таблицы при помощи метода ClearAll компоненты sgrid  и запись считанных данных в таблицу обходом ячеек в циклах  (с использованием свойств Col, Row и Number).

В функциях btnBar_Callback и btnBar3_Callback обработки события Callback кнопок Bar и Bar3 делается проверка массива DATA и если он не пустой, то строится диаграмма при помощи функции bar, или, соответственно, bar3.

В функции btnClear_Callback происходит очистка осей (функцией cla) и возвращение их параметров к принятым по умолчанию (функцией reset).

Текст функции sgrid_demo со вложенными функциями приведен ниже

function sgrid_demo
  % создание окна приложения  
  hF =  figure('Position', [200   150  500    400],... 
    'DeleteFcn', @delete_fun, ...     
    'MenuBar', 'none', 'NumberTitle', 'off',... 
    'Name', 'sgrid demo'); 
  % создание осей  
  hA =  axes('Units', 'pixels',... 
    'Position', [30 200 460 180]); 
  % создание кнопок Load..., Bar, Bar3 и Clear 
  hLoad =  uicontrol('Style', 'pushbutton', ... 
    'String', 'Load...',... 
    'Position', [420 145 70 25 ],... 
    'Callback', @btnLoad_Callback); 
  hBar =  uicontrol('Style', 'pushbutton', ... 
    'String', 'Bar',... 
    'Position', [420 115 70 25 ],... 
    'Callback', @btnBar_Callback); 
  hBar3 =  uicontrol('Style', 'pushbutton', ... 
    'String', 'Bar3',... 
    'Position', [420 85 70 25 ],... 
    'Callback', @btnBar3_Callback); 
  hClear =  uicontrol('Style', 'pushbutton', ... 
    'String', 'Clear',... 
    'Position', [420 55 70 25 ],... 
    'Callback', @btnClear_Callback); 
  % размещение ActiveX-компоненты sgrid 
  pos = [10  10 400 160]; 
  hgrid =  actxcontrol('SGRID.SgCtrl.1', pos, hF); 
  % задание числа ее строк и столбцов 
  hgrid.NRows = 100; 
  hgrid.NColumns = 100; 
  % задание ширины столбцов 
  hgrid.SetColWidth(0, 99, 4000, 1) 
  % связывание функции MouseUp_fun с событием MouseUp 
  hgrid.registerevent({'MouseUp',  @MouseUp_fun}); 
  % инициализируем массив DATA 
  DATA = []; 
  % делаем указатель на окно доступным только для функций  обработки событий 
  set(hF,  'HandleVisibility', 'callback');
  
function  MouseUp_fun (varargin) 
  % функция обработки отпускания кнопки мыши  
    % получаем выделенный диапазон  
    [row_start, col_start, row_end,  col_end] = hgrid.GetSelection(1, 1, 1, 1, 1); 
    % инициализируем массив DATA 
    DATA = zeros(row_end - row_start + 1,  col_end - col_start + 1); 
    % в циклах делаем каждую ячейку  выделенного диапазона текущей 
    % и заносим ее  содержимое в соответствующий элемент массива DATA 
    for j = col_start : col_end 
      hgrid.Col = j; 
      for i = row_start : row_end 
        hgrid.Row = i; 
        DATA(i+1, j+1) = hgrid.Number; 
      end 
    end 
  end  % of function MouseUp_fun

function btnLoad_Callback (src, evt) % функция обработки нажатия на кнопку Load % открываем диалоговое окно для выбора файла с данными [FName, PName] = uigetfile('*.dat'); if ~isequal(FName, 0) % если файл выбран, то конструируем его полное имя FullName = [PName, FName]; % считываем данные DATA = load(FullName); % узнаем их размеры [nRows, nCols] = size(DATA); % удаляем все данные из таблицы hgrid.ClearAll % в циклах делаем ячейки таблицы текущими и заносим в них % данные из DATA for j = 1 : nCols hgrid.Col = j - 1; for i = 1 : nRows hgrid.Row = i - 1; hgrid.Number = DATA(i, j); end end            end end % of function btnLoad_Callback

function btnBar_Callback (src, evt) % функция обработки нажатия на кнопку Bar if ~isempty(DATA) % если массив данных DATA не пуст, строим обычную диаграмму bar(DATA) end        end  % of function btnBar_Callback

function btnBar3_Callback (src, evt) % функция обработки нажатия на кнопку Bar3 if ~isempty(DATA) % если массив данных DATA не пуст, строим объемную диаграмму bar3(DATA) end end   % of function btnBar3_Callback

function btnClear_Callback (src, evt) % функция обработки нажатия на кнопку Clear % очищаем оси axes(hA), cla, reset(hA) end   % of function btnClear_Callback

function delete_fun (src, evt) % функция обработки закрытия окна приложения % удаляем компоненту sgrid delete(hgrid) end   % of function delete_fun end % of main function sgrid_demo

Создание sgrid_demo в среде GUIDE

Работа в среде визуального программирования GUIDE описана в разделе Приложения с GUI и дескрипторная графика. Здесь приводятся только необходимые сведения.

Для запуска среды GUIDE следует выполнить

  >> guide

При этом появляется окно среды и в нем заготовка окна приложения. На заготовку следует нанести оси, четыре кнопки и ActiveX-компоненту при помощи кнопок на вертикальной панели инструментов среды GUIDE (см. рисунок ниже).

Figure 13
Создание окна приложения в среде GUIDE

При размещении ActiveX-компоненты появится окно, приведенное ниже, в списке ActiveX Control List которого следует выбрать Simple Grid Control и нажать OK (ActiveX-компонента Simple Grid Control будет видна в списке, если выполнена ее регистрация, как написано в разделе Регистрация ActiveX-компоненты), после чего на заготовке окна приложения задать размеры добавленной компоненты мышью.

Figure 14
Окно для выбора ActiveX-компоненты

Далее требуется задать теги кнопок и надписи на них. Для этого делаем двойной щелчок по каждой кнопке и в появившемся окне инспектора свойств (Property Inspector) задаем ее свойства Tag и String

Figure 15
Задание свойств объектов приложения в инспекторе свойств

Дадим следующие теги кнопкам:

  • кнопка Load... — тег btnLoad;
  • кнопка Bar — тег btnBar;
  • кнопка Bar3 — тег btnBar3;
  • кнопка Clear — тег btnClear.

При сохранении приложения, например с именем sgrid_demo_guide, автоматически создается файл sgrid_demo_guide.m, в котором сгенерировались некоторые функции. Этот файл понадобится при программировании событий элементов управления.

Для того, чтобы окно приложения выглядело как на рисунке в начале этого раздела, следует установить размеры окна и всех его элементов. Для каждого элемента в окне инспектора свойств (Property Inspector) задаем:

  для окна 
  Units = pixels 
  Position: x = 200,  y = 150,  width = 500,  height = 400 
  
  для осей 
  Units = pixels 
  Position: x = 30,  y = 200,  width = 460,  height = 180 
  
  для кнопки Load... 
  Units = pixels 
  Position: x = 420,  y = 145,  width = 70,  height = 25 
  
  для кнопки Bar 
  Units = pixels 
  Position: x = 420,  y = 115,  width = 70,  height = 25 
  
  для кнопки Bar3 
  Units = pixels 
  Position: x = 420,  y = 85,  width = 70,  height = 25 
  
  для кнопки Clear 
  Units = pixels 
  Position: x = 420,  y = 55,  width = 70,  height = 25 

В инспекторе свойств нет положения ActiveX-компоненты (отображаются только ее свойства), а ее размер определяется при создании окна приложения. Про то, как программно задать размеры ActiveX-компоненты и что нужно изменить в функции sgrid_demo_guide, сказано ниже. Пока можно задать ее размеры примерно при помощи мыши.

Теперь самое время приступить к программированию событий Callback, возникающих при нажатии кнопок Load, Bar, Bar3 и Clear и отпускании кнопки мыши в таблице. Для этого в редакторе GUIDE в контекстном меню кнопки Load… следует в пункте View Callbacks выбрать подпункт Callback. При этом в файле sgrid_demo_guide.m создастся заголовок функции btnLoad_Callback (он состоит из тега кнопки btnLoad и названия события Callback)

  function  btnLoad_Callback(hObject, eventdata, handles)

После заголовка функции надо разместить операторы, которые должны выполнятся при нажатии пользователем на кнопку Load… Далее они приведены с комментариями. В этом коде есть три важных момента.

  1. Есть структура handles (входной аргумент функции btnLoad_Callback). Названия ее полей совпадают с тегами объектов окна приложения. В частности, в handles.activex1 содержится объект — ActiveX-компонента (при ее создании она автоматически получила тег activex1).
  2. Для хранения данных мы будем использовать поле DATA структуры handles. Для сохранения структуры handles после выхода из функции обработки события (все переменные функции являются локальными) мы воспользуемся функцией guidata. В качестве первого ее входного аргумента задается указатель на любой объект приложения, мы используем входной аргумент hObject функции обработки события (это указатель на объект, событие которого обрабатывается в функции). Вторым входным аргументом функции  guidata является структура данных приложения handles.
  3. После считывания данных из файла функцией load (в файле числовые данные представлены в текстовом виде) они заносятся в ячейки таблицы. Для этого предварительно содержимое таблицы удаляется с применением метода ClearAll ActiveX-компоненты. Затем в цикле ячейка таблицы делается текущей (при помощи свойств Row и Col ActiveX-компоненты) и в нее заносятся данные (с использованием свойства Number ActiveX-компоненты). Нумерация строк и столбцов таблицы начинается с нуля.
  guidata(hObject, handles); 
  % открываем диалоговое окно для выбора файла с данными 
  [FName, PName] = uigetfile('*.dat'); 
  if ~isequal(FName, 0) 
    % если файл  выбран, то конструируем его полное имя 
    FullName = [PName, FName]; 
    % считываем данные  и сохраняем в поле DATA  структуры handles 
    handles.DATA = load(FullName); 
    % сохраняем структуру handles 
    guidata(hObject, handles);     
    % узнаем размеры  данных 
    [nRows, nCols] = size(handles.DATA); 
    hgrid = handles.activex1; 
    % удаляем все  данные из таблицы 
    hgrid.ClearAll 
    % в циклах делаем  ячейки таблицы текущими и заносим в них 
    % данные из DATA 
    for j = 1 : nCols 
      hgrid.Col = j - 1; 
      for i = 1 : nRows 
        hgrid.Row = i - 1; 
        hgrid.Number = handles.DATA(i, j); 
      end 
    end 
  end

Далее запрограммируем обработку событий Callback кнопок Bar, Bar3 и Clear, предварительно создав заголовки функций так же, как и для кнопки Load…. Код функций приведен ниже. В функциях btnBar_Callback и btnBar3_Callback проверяется, не пусто ли поле DATA структуры handles. Если нет, то вызывается соответствующая функция (bar или bar3) для построения диаграммы.

function  btnBar_Callback(hObject, eventdata, handles) 
if ~isempty(handles.DATA)  
  % если массив  данных  не пуст, строим обычную диаграмму 
  bar(handles.DATA) 
end

function  btnBar3_Callback(hObject, eventdata, handles) 
if ~isempty(handles.DATA)  
  % если массив  данных  не пуст, строим обычную диаграмму 
  bar3(handles.DATA) 
end

В функции btnClear_Callback происходит очистка осей (функцией clear) и установка принятых по умолчанию параметров осей (функция reset)

function  btnClear_Callback(hObject, eventdata, handles) 
cla, reset(handles.axes1)

При запуске приложения поле DATA структуры handles должно существовать и содержать пустой массив. Для этого в функции sgrid_demo_guide_OpeningFcn (которая выполняется непосредственно перед тем, как окно приложения станет видимым) перед сохранением структуры handles функцией guidata добавим поле DATA, присвоив ему пустой массив

function  sgrid_demo_guide_OpeningFcn(hObject, eventdata, handles, varargin) 
handles.output = hObject; 
handles.DATA = []; 
guidata(hObject, handles);

При закрытии окна пользователем следует удалить ActiveX-компоненту. Когда окно приложения закрывается, возникает событие DeleteFcn, в функции обработки которого включим удаление компоненты при помощи функции delete. Для этого сгенерируем заголовок функции, выбрав в контекстном меню на свободном месте окна приложения в редакторе GUIDE в пункте View Callbacks подпункт DeleteFcn. При этом создастся заголовок функции, после которого добавим удаление ActiveX-компоненты (см приведенный ниже код функции figure1_DeleteFcn)

function  figure1_DeleteFcn(hObject, eventdata, handles) 
% удаление  ActiveX-компоненты 
delete(handles.activex1)

Осталось запрограммировать событие MouseUp ActiveX-компоненты. Для этого в ее контекстном меню в GUIDE в пункте View Callbacks выбираем подпункт MouseUp. При этом создается заголовок функции activex1_MouseUp. Код обработки события MouseUp приведен ниже. В нем совершаются следующие действия

  1. при помощи структуры handles в hgrid заносится объект — ActiveX-компонента;
  2. применяется метод GetSelection для получения выделенной прямоугольной области в таблице;
  3. в поле DATA структуры handles записываются данные из выделенной области таблицы проходом в циклах по ячейкам (с использованием свойств Row и Col и свойства Number)
  4. обновленная структура handles сохраняется при помощи функции guidata

  function  activex1_MouseUp(hObject, eventdata, handles) 
  % функция обработки отпускания кнопки мыши 
  hgrid = handles.activex1; 
  % получаем  выделенный диапазон  
  [row_start, col_start, row_end, col_end] = hgrid.GetSelection(1,1,1,1,1); 
  %  инициализируем массив DATA 
  handles.DATA = zeros(row_end - row_start + 1, col_end - col_start + 1); 
  % в циклах делаем каждую ячейку выделенного диапазона  текущей 
  % и заносим ее содержимое в соответствующий элемент массива DATA 
  for j = col_start : col_end 
    hgrid.Col = j; 
    for i = row_start : row_end 
      hgrid.Row = i; 
      handles.DATA(i+1, j+1) = hgrid.Number; 
    end 
  end 
  % сохраняем  структуру handles 
  guidata(handles.figure1, handles);

Приложение создано, его работу можно проверить, нажав на кнопку Run  Figure 16 на горизонтальной панели редактора GUIDE, или выполнив в командной строке

  >> sgrid_demo_guide

(приложение надо предварительно сохранить)

Разберем теперь, как программно задать размеры ActiveX-компоненты. В основной функции приложения есть оператор if

if nargout 
  [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 
else 
  gui_mainfcn(gui_State, varargin{:}); 
end

в котором вызывается функция gui_mainfcn, которая определяет стандартный порядок инициализации приложения, созданного в среде GUIDE. При запуске нашего приложения

  >> sgrid_demo_guide

сначала входной аргумент varargin функции sgrid_demo_guide является пустым массивом, затем в gui_mainfcn снова вызывается sgrid_demo_guide, но уже массив ячеек varargin не пустой, в его ячейках находятся следующие данные:

  • varargin{1} содержит имя функции  'figure1_CreateFcn', вызываемой при создании окна приложения; 
  • varargin{2} содержит указатель на окно.

Далее происходит возврат в точку вызова gui_mainfcn и массив varargin опять пуст. Задача — запомнить указатель на окно и после возвращения в точку вызова gui_mainfcn получить объект — ActiveX-компоненту и задать ей нужные размеры. Для этого внесем небольшое дополнение в основную функцию sgrid_demo_guide нашего приложения, добавив в ней следующие операторы.

  1. Проверку на не пустоту массива varargin и равенства содержимого первой ячейки  varargin строке ‘figure1_CreateFcn’. Если эти условия верны, то запомним в переменной hF содержимое второй ячейки массива varargin, содержащей указатель на графическое окно приложения. Переменная hF должна быть доступна после возвращения в точку вызова, поэтому мы объявим ее как persistent (значения этих переменных остаются в памяти и при первом вызове функции ее значение — пустой массив). Осталось выйти из функции sgrid_demo_guide при помощи оператора return.
  2. Проверку на не пустоту hF (т.е., что в нее был записан указатель на окно приложения) и проверку на пустоту массива varargin (он должен быть пустой при возвращении в точку вызова gui_mainfcn). При выполнении этих условий мы выведем окно командой drawnow и получим структуру данных приложения handles (содержащую указатели на объекты окна) при помощи функции guidata. В поле activex1 структуры handles содержится объект — AxtiveX-компонента. Изменим ее положение при помощи метода move, указав желаемую позицию (координаты левого нижнего угла объекта относительно левого нижнего угла окна, ширину и высоту). Код функции sgrid_demo_guide приведен ниже.
function  varargout = sgrid_demo_guide(varargin) 
persistent  hF 
gui_Singleton  = 1; 
gui_State =  struct('gui_Name',    mfilename, ... 
    'gui_Singleton', gui_Singleton, ... 
    'gui_OpeningFcn', @sgrid_demo_guide_OpeningFcn, ... 
    'gui_OutputFcn', @sgrid_demo_guide_OutputFcn, ... 
    'gui_LayoutFcn', [], ... 
    'gui_Callback', []); 
if nargin  && ischar(varargin{1}) 
  gui_State.gui_Callback = str2func(varargin{1}); 
end 
if nargout 
  [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); 
else 
  gui_mainfcn(gui_State, varargin{:}); 
end 
if  ~isempty(varargin) & isequal(varargin{1}, 'figure1_CreateFcn') 
  hF = varargin{2}; 
  return 
end 
if  ~isempty(hF)&isempty(varargin) 
  drawnow 
  handles = guidata(hF); 
  hgrid = handles.activex1; 
  pos = [10 10 400 160]; 
  move(hgrid, pos); 
end


Поиск по сайту:

Система Orphus

Яндекс.Метрика