1. 程式人生 > 實用技巧 >MATLAB GUI設計--數值分析輔助教學系統

MATLAB GUI設計--數值分析輔助教學系統

實現目標

數值分析實驗教學系統開發。要求包含實驗課中所有的實驗內容,具體系統總體設計、互動的友好性等,各小組組內討論決定;每個試驗模組包括以下子模組:

  1. 能手動填寫姓名、學號、班級等基本資訊
  2. 實驗目的,能手動填寫
  3. 實驗內容,包括視訊講解、演算法推導、程式實現、測試結果。
    3.1 視訊講解:視訊部分主要為了指導學生怎麼開展各個實驗,包括程式碼的講解,知識點講解及二者細節的對應關係等·(視訊講解要提前儲存在系統中,供學生學習),
    3.2 演算法推導:以自動滑動的圖片展示為主,能夠本地製作,拍照後通過系統上傳並展示
    3.3 程式實現:能在本地編寫函式,存入指定資料夾,然後系統在執行時能呼叫.3.4·測試結果:能實時顯示到系統介面上
  4. 總結及自評,能手動填寫
  5. 自動生成word 版實驗報告

參考資料

Matlab讀取並按幀顯示視訊程式碼 liaoqix
【MATLAB】簡單易學的GUI BILIBILI視訊

功能實現

主介面實現

包含主選單和三個區域,分別用於執行函式,顯示結果和繪圖;選單欄用於排程其他模組

全域性變數: global cur_row cmd pic cnt cur_cnt res
%定義兩個text標題框。用來標識下面的兩個靜態文字框.
text_s = uicontrol('Parent', gcf, ...
   'FontSize',6, ...
   'Style', 'text', ...
   'Units', 'Normalized', ...
   'Position', [0 0.98 0.123 0.02], ...
   'HorizontalAlignment', 'left', ...
   'Enable', 'on', ...
   'HandleVisibility', 'on', ...
   'String', 'Command', ...
   'Max', 2);
text_s_2 = uicontrol('Parent', gcf, ...
   'FontSize',6, ...
   'Style', 'text', ...
   'Units', 'Normalized', ...
   'Position', [0 0.48 0.123 0.02], ...
   'HorizontalAlignment', 'left', ...
   'Enable', 'on', ...
   'HandleVisibility', 'on', ...
   'String', 'Result', ...
   'Max', 2);

接下來定義兩個可以編寫的文字框(作為命令區和結果顯示區)。
edit_c = uicontrol('Parent', gcf, ... 
   'Style', 'edit', ...
   'Units', 'Normalized', ...
   'Position', [0 0.5 0.5 0.48], ...
   'HorizontalAlignment', 'left', ...
   'Enable', 'on', ...
   'HandleVisibility', 'on', ...
   'Max', 2);
text_c = uicontrol('Parent', gcf, ...
   'Style', 'edit', ...
   'Units', 'Normalized', ...
   'Position', [0 0 1 0.48], ...
   'HorizontalAlignment', 'left', ...
   'Enable', 'on', ... 
   'HandleVisibility', 'on', ...
   'Max', 2);
handles.edit_c = edit_c;
handles.text_c = text_c;

使用GUIDE編寫的選單欄

各區域如圖所示

函式編寫

函式、指令碼編寫功能實現

函式功能:在選單欄當中的函式編寫一欄添加回調函式當按下這一欄時候會彈出一個帶編輯框的視窗用於編寫函式及.m指令碼檔案。

function edit_fun_Callback(hObject, eventdata, handles)
fig_1 = figure('Name', 'Undefine.m', ...  %定義的figure視窗,
    'Numbertitle', 'off', ...			%每兩個為一組前者為屬性後
    'Units', 'Normalized', ...	%為屬性定義,具體可以再figure屬性中看。
    'Position', [0.15 0.1 0.7 0.7], ...%定義視窗的位置。
    'Menubar', 'none');	%不需要選單
edit_m = uicontrol('Parent', fig_1, ...	%在定義的figure 
   'Style', 'edit', ...			% fig_1的基礎上新增該eidt
   'Units', 'Normalized', ...%型別的文字框。用來編寫程式碼。
   'Position', [0 0 1 1], ...
   'HorizontalAlignment', 'left', ...
   'Enable', 'on', ...
   'HandleVisibility', 'on', ...
   'Max', 2);
menu_1 = uimenu(gcf, 'Label', '文字'); gcf為figure返回的控制代碼值
menu_s = uimenu(menu_1, 'Label', '另存為');在menu_1所建立的選單下新增一個新的選項另存為。
handles.fig_1 = fig_1;用控制代碼hanles.fig_1來記錄fig_1記錄的返回值
handles.edit_m = edit_m; 用控制代碼hanles.edit_m來記錄edit_m記錄的返回值
handles.menu_1 = menu_1; 用控制代碼hanles.menu_1來記錄menu_1記錄的返回值
handles.menu_s = menu_s; 用控制代碼hanles.menu_s來記錄menu_s記錄的返回值
guidata(hObject, handles);更新hObject儲存的handles結構體。
set( menu_s, 'Callback',  {@menu_s_Callback, handles}); 設定menu_s即儲存功能的回撥函式。

函式、指令碼儲存功能實現

函式功能:將在函式編寫介面編寫的函式(或指令碼)進行儲存(.m格式)

function menu_s_Callback(hObject, eventdata, handles)
% uiputfile用於儲存文字的函式。file儲存返回的檔名,path儲存儲存的路徑。
[file, path, ~] = uiputfile('*.m'); 
%如果取消則在變數定義中定義的eidt文字標題為result的文字框中輸出”User clicked Cancel.”,該文字框用來輸出結果。(如果使用者指定有效的檔名並點選儲存,MATLAB 將在 file 中返回該檔名。如果使用者取消該對話方塊,MATLAB 會將 0 返回給 file。)
%否則開啟該檔案,把在handles.edit_m中編寫的程式碼存入該檔案中。
if isequal(file,0) || isequal(path,0)    
set(handles.text_c, 'String', 'User clicked Cancel.');
else
    fp=fopen(file, 'w+');
    str = get(handles.edit_m, 'String')
    [row,col] = size(str);
    for i=1:row
        fprintf(fp, '%s\n', str(i,:));
    end
    fclose(fp);
end
close;

效果圖

觀看視訊功能實現

函式功能:開啟本地視訊(提前錄製好的教程);取消時將在結果框輸出使用者取消操作(下模組同)。

function watch_Callback(hObject, eventdata, handles)
%開啟一個視訊檔案
[file, path, c] = uigetfile('*.mp4'); 
if isequal(file, 0) || isequal(path, 0)
    set(handles.text_c, 'String', 'User clicked Cancel.');
else
h_1 = figure('Name', file, ...
    'Numbertitle', 'off', ...
    'Units', 'Normalized', ...
    'Position', [0.15 0.1 0.7 0.7], ...
    'color', 'w', ...
    'Menubar', 'none');

VidObj = VideoReader(file); %修改為需要讀取的視訊檔案 
nFrames = VidObj.NumberOfFrames; %獲取視訊總幀數
vidHeight = VidObj.Height; %獲取視訊高度
vidWidth = VidObj.Width; %獲取視訊寬度
for k = 1 : nFrames %遍歷每一幀
    I = read(VidObj, k); %讀出當前幀
    imshow(I); %顯示當前幀。
    pause(0.005); 暫停系統程式,是人眼可以分辨,這裡暫停0.005秒。
end
end
close;

逐幀播放視訊,無聲音

檢視圖片功能實現

函式功能:插入多張圖片並顯示,單擊圖片顯示下一張。

function pic_Callback(hObject, eventdata, handles)
%全域性變數 cnt,pic,cur,cnt,
% answer = questdlg(quest) 建立一個模態對話方塊,其中提出問題並返回使用者的回答 - 'Yes'、'No'、'Cancel' 或 ''。
預設情況下,該對話方塊有三個標準按鈕,其標籤分別為是、否和取消。
如果使用者點選其中一個按鈕,則 answer 值與按下的按鈕的標籤相同。
如果使用者點選對話方塊標題欄上的關閉按鈕 (X) 或按下 Esc 鍵,則 answer 值為空字元向量 (' ')。
如果使用者按下 Return 鍵,則 answer 值與預設所選按鈕的標籤相同。在本例中,為 'Yes'。
global cnt pic cur_cnt
answer = 'Yes';
file = 0;
path = 0;
answer = questdlg('是否要讀入圖片','讀入');
while( strcmp(answer,'Yes')==1 ) 
    cnt = cnt+1;
    [file, path, c] = uigetfile('*.jpg');
    pic_name(cnt, :) = file;
    answer = questdlg('是否要繼續讀人圖片','繼續');
end
if isequal(file,0) || isequal(path,0)
    set(handles.text_c, 'String', 'User clicked Cancel.');
else
	%建立一個figure把圖片通過它顯示。
pic = pic_name;
    h_p = figure('Name', '圖片瀏覽', ...
        'Numbertitle', 'off', ...
        'Units', 'Normalized', ...
        'Position', [0.15 0.1 0.7 0.7], ...
        'color', 'w', ...
        'Menubar', 'none');
    handles.h_p = h_p;
    guidata(hObject, handles);更新已有的handles資料結構。
set( h_p, 'WindowButtonDownFcn',{@h_p_WindowButtonDownFcn, handles});%新增滑鼠左鍵觸發,切換下一張圖片。
    cur_cnt = cur_cnt+1;
    imshow(pic(cur_cnt, :));展示圖片。自動展示第一張,之後的靠單擊滑鼠展示。
end

選擇圖片

![](https://img2020.cnblogs.com/blog/1752536/202101/1752536-20210111092921153-1093847614.png)

![](https://img2020.cnblogs.com/blog/1752536/202101/1752536-20210111092930598-1099165534.png)

  單擊顯示下一張圖片:
function h_p_WindowButtonDownFcn(hObject, eventdata, handles)
global cur_cnt pic cnt %全域性變數
if cur_cnt == cnt %如果當前是最後一張圖片則關閉。
    close;
else
    cur_cnt = cur_cnt+1;
    imshow(pic(cur_cnt, :));%顯示圖片
end

顯示介面:顯示圖片在介面內單擊滑鼠左鍵即可顯示下一張圖片。

命令文字框功能實現

函式功能:在command中輸入要執行的.m檔案的字首,執行該檔案並將結果顯示在Result區域,如果是函式繪圖,會將圖片在旁邊的座標區域顯示;輸入clc命令清空輸出框,輸入cla清空繪圖區。

%命令文字框的Callback實現
function edit_c_Callback(hObject, eventdata, handles)
global cur_row cmd res pstr
cur_row = cur_row+1;
cmd = get(handles.edit_c, 'String');%將輸入的檔案字首轉為字串
%set(handles.text_c, 'String', cmd(cur_row, :));
run(cmd(cur_row, :))%執行.m檔案
to_String;
set(handles.text_c, 'String', pstr);%將結果以字串的格式複製到輸出框
if strcmp(cmd(cur_row, 1:3),'clc') == 1
    set(handles.text_c, 'String', '');%輸入clc以空格覆蓋輸出區域
end

將數值型元胞陣列轉為字串陣列

function to_String()
global res pcnt pstr
[res_r, res_c] = size(res);
for i=1:res_c
    if strcmp(class(res{2,i}),'double') == 1
        double_1 = num2str(res{2,i});
        pstr(pcnt, 1:length(res{1,i})) = res{1,i};
        pcnt = pcnt+1;
        [c_r,c_c] = size(double_1);
        for j=1:c_r
            pstr(pcnt, 1:length(double_1(j, :))) = double_1(j, :)
            pcnt = pcnt+1;
        end
    end
end
res = {};

幫助(彈窗提示功能)實現

函式功能:顯示命令區使用指南。

f = msgbox(message) 建立一個訊息對話方塊,該對話方塊可將 message 自動換行,以適應合適大小的圖窗。如果您要在多個 App 視窗、MATLAB桌面或 Simulink 上顯示訊息對話方塊,並且在響應對話方塊之前仍能與它們進行互動,請使用此函式。	
msg = msgbox('輸入函式名稱後按下CTRL+ENTER執行 ', '幫助');

效果展示

生成Word版實驗功能實現

根據對話方塊輸入指定資訊,程式按指定的格式自動生成Word文件,並將演算法推導過程作為附錄引入

%此處刪去了部分重複性程式碼
function edit_doc_Callback(hObject, eventdata, handles)
%原包陣列,填寫基本資訊
handles.inf = inputdlg({'請輸入姓名', '請輸入學號', '請輸入班級'}, ...
    '基本資訊', 1);
%填寫實驗目的
handles.pro = inputdlg('實驗目的', '實驗目的', 2, ...
    {''}, 'on');
tmp = char;
tmp = handles.pro{1};
%總結及自評
handles.con = inputdlg('總結', '總結', 2, ...
    {''}, 'on');
tmp_2 = char;
tmp_2 = handles.con{1};
guidata(hObject, handles);


其中生成Word排版的程式碼含有大量重複部分,此處僅列舉一小部分(詳見程式碼)
%利用MATLAB生成Word文件
filespec_user = [pwd '\測試.doc'];% 設定測試Word檔名和路徑
% 判斷Word是否已經開啟,若已開啟,就在開啟的Word中進行操作,否則就開啟Word
try
% 若Word伺服器已經開啟,返回其控制代碼Word
Word = actxGetRunningServer('Word.Application');
catch
% 否則,建立一個Microsoft Word伺服器,返回控制代碼Word
Word = actxserver('Word.Application');
end;
 
Word.Visible = 1; % 或set(Word, 'Visible', 1);
% 若測試檔案存在,開啟該測試檔案,否則,新建一個檔案,並儲存,檔名為測試.doc
if exist(filespec_user,'file');
    Document = Word.Documents.Open(filespec_user);
    % Document = invoke(Word.Documents,'Open',filespec_user);
else
Document = Word.Documents.Add;
% Document = invoke(Word.Documents, 'Add');
Document.SaveAs2(filespec_user);
end
% 設定游標位置從頭開始
Content = Document.Content;
Selection = Word.Selection;
Paragraphformat = Selection.ParagraphFormat;
% 設定頁面大小
Document.PageSetup.TopMargin = 60; % 單位畫素
Document.PageSetup.BottomMargin = 45;
Document.PageSetup.LeftMargin = 45;
Document.PageSetup.RightMargin = 45;
% Content.InsertParagraphAfter;% 插入一段
% Content.Collapse=0; % 0為不覆蓋
Content.Start = 0;
title = '                   實驗 XXX(標題)';
Content.Text = title;           % 寫入標題
Content.Font.Size = 18 ;        % 字型大小
Content.Font.Bold = 4 ;         % 加粗
Content.Paragraphs.Alignment = 'wdAlignParagraphLeft';% 設定段落格式(居中操作)
Selection.Start = Content.end;% 定義開始的位置  (將游標移動到後面)
Selection.TypeParagraph;  % 相當於enter鍵

Selection.Text = '     學號:';% 寫入變數
Selection.Font.Size = 12;               % 字型大小
Selection.Font.Bold = 0;                % 取消加粗
Selection.MoveDown;
Selection.MoveRight;
Selection.Text = ['   ',handles.inf{2},'    '];% 寫入變數
Selection.Range.Underline = 1;
Selection.Font.Size = 12;               % 字型大小
Selection.Font.Bold = 0;                % 取消加粗
Selection.MoveDown;

……

Selection.InsertBreak(1);
%選擇演算法推導圖片
[file, path, c] = uigetfile(['*.jpg']);
H=figure();
imshow(file);
print(H,'-dbitmap');%將圖片發到剪下板
close;
Selection=Word.Selection;   
Selection.Range.Paste;%在當前游標的位置插入圖片
Selection.MoveDown;
Selection.TypeParagraph;

Document.Save; % 儲存文件
%Document.Close; % 關閉文件
%Word.Quit; % 退出word伺服器

效果展示


生成WORD如下

演算法推導作為附錄匯入

總結