[轉(zhuǎn)載]Matlab的GUI參數(shù)傳遞方式總結(jié)

轉(zhuǎn)自 http://blog.csdn.net/smf0504/article/details/51814375

其實(shí)Matlab提供了很多種直接或間接方法實(shí)現(xiàn)多fig中的數(shù)據(jù)共享,只是大家沒有注意罷了:

1鄙信、全局變量

2喷市、作為函數(shù)的參數(shù)傳遞

3描沟、利用控件的userdata數(shù)據(jù)

4囱嫩、為handles結(jié)構(gòu)體添加新字段

5、setappdata函數(shù)為句柄添加數(shù)據(jù)

6胚吁、跨空間計(jì)算evalin和賦值assignin

7、將數(shù)據(jù)保存到文件恋脚,需要時(shí)讀取

8、帶參數(shù)調(diào)用GUI的M文件

9焰手、嵌套函數(shù)(不適用于GUIDE中糟描,只適用純命令是的GUI)

一、全局變量

運(yùn)用global定義全局變量傳遞參數(shù)书妻,適用于gui內(nèi)控件間以及不同gui間船响。這種方式恐怕是最簡單的方式,是很省心躲履!但是见间,簡單的問題就在于有時(shí)你會很頭疼!因?yàn)樵诿恳粋€(gè)要到該全局變量的地方工猜,你都要添一句gloalx米诉,還有就是如果你在一個(gè)地方修改了 x的值,那么所有x的值就都變了篷帅!有的時(shí)候恐怕會出現(xiàn)紊亂史侣。另一個(gè)更重要的問題在于,套用C++的一句話魏身,全局變量破壞了程序的封裝性惊橱!所以,全局變量是能少用盡量少用箭昵。

以下創(chuàng)造一個(gè)簡單的GUI給大家說明一下税朴,建一個(gè)GUI, 包含兩個(gè)按鈕家制,一個(gè)坐標(biāo)系正林,一個(gè)用來畫y=sin(x),一個(gè)用來畫y=cos(x);

eg:在GUI的OpeningFcn函數(shù)中寫:

globalx y1 y2

x=0:.1:2*pi;y1=sin(x);y2=cos(x);

在pushbutton1_Callback函數(shù)中寫

Globalx y1

Plot(x,y1)

在pushbutton1_Callback函數(shù)中寫

Globalx y2

Plot(x,y2)

全局變量是比較方便的,但全局變量會破壞封閉性颤殴,如果不是有大量數(shù)據(jù)要傳遞卓囚,建議不要使用。

二诅病、運(yùn)用gui本身的varain{}哪亿、varaout{}傳遞參數(shù)

這種方式僅適用于gui間傳遞數(shù)據(jù),且只適合與主子結(jié)構(gòu)贤笆,及從主gui調(diào)用子gui蝇棉,然后關(guān)掉子gui,而不適合遞進(jìn)結(jié)構(gòu)芥永,即一步一步實(shí)現(xiàn)的方式篡殷。

輸入?yún)?shù)傳遞(主要在子gui中設(shè)置):

比如子GUI的名稱為subGUI,設(shè)想的參數(shù)輸入輸出為:[out1,out2] = subGUI(in1, in2)

在subGUI的m文件中(由GUIDE自動產(chǎn)生):

1.第一行的形式為:function varargout = subGUI(varargin)

該行不用做任何修改;varargin 和varargout 分別是一個(gè)可變長度的cell型數(shù)組埋涧。輸入?yún)?shù)in1和in2保存在varargin中板辽,輸出參數(shù)out1奇瘦,out2包含在varargout中;

2.在subGUI的OpeningFcn中劲弦,讀入?yún)?shù)耳标,并用guidata保存,即:

handles.in1= varargin{1};

handles.in2= varargin{2};

guidata(hObject,handles);

返回參數(shù)的設(shè)置:

1.在主GUI的OpeningFcn函數(shù)中加上[out1, out2] = subGUI(in1, in2)邑跪,用于調(diào)用子gui次坡,并在結(jié)尾加上uiwait(handles.figure1);figure1是subGUI的Tag,主要是等待調(diào)用子gui的過程画畅,從而獲得子gui的輸出參數(shù)out1砸琅、out2;

2.subGUI中控制程序結(jié)束(如"OK”和"Cancel"按鈕)的callback末尾加上uiresume(handles.figure1)轴踱,注意是主gui的窗口handles.figure1,不要將delete命令放在這些callback中症脂;

3.在子GUI的OutputFcn中設(shè)置要傳遞出去的參數(shù),如varargout{1} = handles.out1淫僻;varargout{2}= handles.out2;末尾添加delete(handles.figure1); 結(jié)束程序诱篷。

在GUI的OpenFcn中,如果不加uiwait嘁傀, 程序會直接運(yùn)行到下面,執(zhí)行OutputFcn视粮。也就是說程序一運(yùn)行细办,返回值就確定了,再在其它部分對handles.output作更改也沒有效果了蕾殴。

加上uiwait后笑撞,只有執(zhí)行了uiresume后,才會繼續(xù)執(zhí)行到OutputFcn钓觉,在此之前用戶有充分的時(shí)間設(shè)置返回值茴肥。

通過以上設(shè)置以后,就可以通過 [out1, out2] = subGUI(in1, in2) 的形式調(diào)用該子程序荡灾。

在一個(gè)GUI中調(diào)用另一個(gè)GUI時(shí)瓤狐,主GUI不需要特別的設(shè)置,同調(diào)用普通的函數(shù)一樣批幌。在打開子GUI界面的同時(shí)础锐,主程序還可以響應(yīng)其它的控件。不需要擔(dān)心子GUI的返回值被傳錯(cuò)了地方荧缘。

三皆警、userdata數(shù)據(jù)

直接通過對象的userdata屬性進(jìn)行各個(gè)callback之間的數(shù)據(jù)存取操作,主要適用于gui內(nèi)截粗。首先必須將數(shù)據(jù)存儲到一個(gè)特定的對象中信姓,假設(shè)對象的句柄值為ui_handle,需要存儲的值為value,則輸入以下程序即可:

set('ui_handle','UserData',Value);

此時(shí)鸵隧,value數(shù)據(jù)就存在句柄值為ui_handle的對象內(nèi),在執(zhí)行的過程中若要取回變量可以通過以下方式在任意callback中獲取該數(shù)據(jù)值 :

value=get(''ui_handle,'UserData');

雖然使用這種方法簡單 意推,但是每個(gè)對象僅能存取一個(gè)變量值豆瘫,因此當(dāng)同一對象存儲兩次變量時(shí) ,先前的變量值就會被覆蓋掉左痢,因此都用UserData存儲簡單與單一的數(shù)據(jù)靡羡。如下面有兩個(gè)gui函數(shù), myloadfn加載mydata.mat文件俊性,該文件內(nèi)存儲XYData變量略步,其值為m*2的繪圖矩陣,加載后將該變量值存儲到 當(dāng)前的窗口的UserData屬性中定页。另一個(gè)myplotfcn函數(shù)則是用以獲取該UserData屬性中存取的繪圖數(shù)據(jù)趟薄,然后繪圖。代碼如下:

function myloadfcn

load mydata;

set(gcbf,'UserData',XYdata)

function myplotfcn

XYdata=get(gcbf,'UserData');

x=XYData(:,1);

y=XYData(:,2);

plot(x,y);

userdata的缺點(diǎn)就是一個(gè)句柄只能放一個(gè)Userdata典徊。

四杭煎、GUI數(shù)據(jù)(handles)

結(jié)合handles和guidata函數(shù),適用于gui內(nèi)卒落,如果你在pushbutton1中得到一個(gè)變量X羡铲,相傳出去,那么在pushbutton1的callback中儡毕,在得到X后添加如下代碼:

 handles.X=X;

 guidata(hObject,handles)(注意也切,一定是兩行連寫)

在pushbutton2中要用到X是,在其callback先添加 X=handles.X腰湾; 即可得到X的值雷恃。

注:

  1. guidata(object_handle,data);如果object_handle不是figure型句柄,那么會將data保存在object_handle的父figure對象中费坊。這樣不必?fù)?dān)心在一個(gè)pushbutton的callback中存儲的變量在其他對象中無法提取倒槐。

  2. data = guidata(object_handle);獲取當(dāng)前object_handle的handles數(shù)據(jù),最后一次guidata(object_handle,data)保存的數(shù)據(jù)附井。

一個(gè)簡單的GUI給大家說明一下讨越,建一個(gè)GUI, 包含兩個(gè)按鈕永毅,一個(gè)坐標(biāo)系谎痢,一個(gè)用來畫y=sin(x),一個(gè)用來畫y=cos(x);

eg:在GUI的OpeningFcn函數(shù)中寫:

x=0:.1:2*pi;

y1=sin(x);

y2=cos(x);

handles.x=x;

handles.y1=y1;

handles.y2=y2;

guidata(hObject,handles);%注意,在OpeningFcn函數(shù)中這句是本身存在的卷雕,若在其它函數(shù)中节猿,務(wù)必加上這句

在pushbutton1_Callback函數(shù)中寫

x=handles.x;

y1=handles.y1;

plot(x,y1)

在pushbutton2_Callback函數(shù)中寫

x=handles.x;

y2=handles.y2;

plot(x,y2)

五、Application數(shù)據(jù)

應(yīng)用setappdata\getappdata與rmappdata函數(shù),適用于gui間和gui內(nèi)滨嘱。使用上面三個(gè)函數(shù)最有彈性處理數(shù)據(jù)的傳送問題峰鄙,與UserData的方式相類似,但是克服UserData的缺點(diǎn)太雨,使一個(gè)對象能存取多個(gè)變量值吟榴。

(1)getappdata函數(shù)

value=getappdata(h,name)

(2)setappdata函數(shù)

setappdata(h,name,value)

(3)rmappdata函數(shù)

rmappdata(h,name)

首先在matlab命令窗口輸入magic(3)數(shù)據(jù),因此當(dāng)前的工作空間就存儲了magic(3)這組數(shù)據(jù)了囊扳,然后建立一個(gè)按鈕來獲取并顯示magic(3)數(shù)據(jù)吩翻。

A=magic(3);

setappdata(gcf,'A',A);%save

uicontrol('String','顯示矩陣

A','callback','A=getappdata(gcf,''A'')');

A=

 8    1     6

 3    5     7

 4    9     2

當(dāng)在主、子gui內(nèi)調(diào)用時(shí)锥咸,可以如下設(shè)置

fig1調(diào)用fig2時(shí)狭瞎,使用fig2指令來打開fig2,

在fig2的m文件中,在回調(diào)函數(shù)中用setappdata(fig1,'A',A);實(shí)現(xiàn)返回fig1搏予,并將參數(shù)A傳遞給fig1

然后在fig1的使用A的地方添加A=getappdata(fig1熊锭,‘A’)。

但這種方式的一個(gè)問題就是每調(diào)用一次雪侥,fig1的數(shù)據(jù)就得初始化一次碗殷,這是因?yàn)閟etappdata(fig1,'A',A)中出現(xiàn)了fig1,調(diào)用一次setappdata就得運(yùn)行一次fig1的緣故速缨,解決方案就是把setappdata(fig1,'A',A)改為setappdata(0,'A',A)锌妻,這樣把A讀入matlabworkspace,相當(dāng)于一個(gè)全局變量了旬牲,但當(dāng)然比直接用global定義全局變量好仿粹!

同樣的例子:

eg:在GUI的OpeningFcn函數(shù)中寫:

x=0:.1:2*pi;

y1=sin(x);

y2=cos(x);

setappdata(handles.figure1,'x',x)%在figure1下創(chuàng)建’x’,包含數(shù)據(jù)x,也可以放在其它句柄下,如setappdata(handles.pushbutton1,'x',x)引谜,不過一般放在figure1下牍陌,記起來方便……

setappdata(handles.figure1,'y1',y1)

setappdata(handles.figure1,'y2',y2)

在pushbutton1_Callback函數(shù)中寫

x=getappdata(handles.figure1,'x');%提取擎浴,當(dāng)然用get了……

y1=getappdata(handles.figure1,'y1');

plot(x,y1)

在pushbutton1_Callback函數(shù)中寫

x=getappdata(handles.figure1,'x');

y2=getappdata(handles.figure1,'y2');

plot(x,y2)

六员咽、跨空間計(jì)算evalin和賦值assignin

適用于gui間和gui內(nèi)

Assignin函數(shù)基本語法

assignin(ws, 'var',val)

其中'base' or 'caller',分別表示基本工作空間和調(diào)用函數(shù)(callerfunction)工作空間贮预,

Assinin函數(shù)將值val指定給工作空間ws中的變量var贝室,若變量var不存在,則創(chuàng)建一個(gè)變量var仿吞。

從一個(gè)函數(shù)function向MATLAB工作空間中輸入數(shù)據(jù)滑频;

在一個(gè)函數(shù)function內(nèi)部,需要改變一個(gè)在callerfunction函數(shù)工作空間中定義的變量唤冈,例如函數(shù)形參列表中的變量峡迷。

例子:

%向基本工作空間中傳輸數(shù)據(jù)變量

Functionassignin_test1

prompt = {'Enterimage name:','Enter colormap name:'};

title = 'Imagedisplay - assignin example';

lines = 1;

def ={'my_image','hsv'};

answer =inputdlg(prompt,title,lines,def);

assignin('base','imfile',answer{1});

assignin('base','cmap',answer{2});

evalin函數(shù)基本語法

evalin(ws,expression)
[a1, a2, a3, ...] = evalin(ws, expression)

在特定的工作空間執(zhí)行MATLAB語句,expression的形式如

expression =[string1, int2str(var), string2,...]

[a1, a2, a3, ...] =evalin(ws, expression),將返回值賦予變量a1绘搞,a2彤避,a3,...evalin(ws,'[a1, a2, a3, ...] = function(var)')

注:

evalin('caller',expression),只能指定callerfunction函數(shù)中的變量為expression的語句夯辖,而不能是subfunction

該函數(shù)不可嵌套使用琉预,evalin('caller','evalin(''caller'', ''x'')')是錯(cuò)誤的

例子:

如果在figure1中有個(gè)變量a1
則傳入時(shí)assignin('base','a1',data) %data是workplace中的變量
在figure2傳出時(shí)a2=evalin('base','data'); %a2是figure2中的變量

七、將數(shù)據(jù)保存到文件蒿褂,需要時(shí)讀取

運(yùn)用save和load(importdata)傳遞參數(shù)圆米,適用于gui間和gui內(nèi)。將某變量x的值先存到磁盤啄栓,用的時(shí)候在調(diào)用娄帖。格式如下:save('.mat','x');用的時(shí)候就用load('.mat'),但這樣只是把x讀到了matlabworkspace谴供,不會用顯示块茁,你還要再去查看這個(gè)變量名,然后才能用,建議使用p=importdata('*.mat'),p是一個(gè)結(jié)構(gòu)體桂肌,可以隨意使用了数焊。當(dāng)然,這種方式涉及到磁盤讀寫崎场,速度當(dāng)然會有影響的佩耳,一般情況不用,通常用在保存以及導(dǎo)入某個(gè)變量時(shí)谭跨!

八干厚、帶參數(shù)調(diào)用GUI的M文件

這個(gè)相信大家都很熟悉了,適用于gui間和gui內(nèi)螃宙。

總結(jié)幾點(diǎn):

① 如果變量數(shù)據(jù)量很大蛮瞄,需要占用大量內(nèi)存,不要將變量存儲為handles的變量谆扎,因?yàn)槊總€(gè)控件每次調(diào)用callback function都會使用handles挂捅,增加不必要的內(nèi)存開銷。若改變量存取不頻繁堂湖,可以考慮UserData數(shù)據(jù)或者Application數(shù)據(jù)闲先;若存取比較頻繁,建議使用Global變量和Application結(jié)構(gòu)體无蜂,這里的Application要定義為setappdata(0,'var',val)以及getappdata(0,'var',val)伺糠。

② 對于GUI界面之間的數(shù)據(jù)傳遞,可以考慮以下幾種方法:

方法1:采用global函數(shù)斥季。

可以采用這種方法共享數(shù)據(jù)训桶;

方法2:采用findobj和findall函數(shù)查找對象句柄

findall(0, 'Type','figure', 'Tag', 'figure1')

查找標(biāo)簽為figure1的窗口,無論該窗口是否隱藏。

方法3:采用handles結(jié)構(gòu)舵揭。

假設(shè)我們在窗口1的Opening函數(shù)中慰照,采用函數(shù)創(chuàng)建了一個(gè)子窗口2:

h_fig =figure('Visible', 'off', ...);

h_btn1 =uicontrol('Parent', h_fig, ‘Tag', 'btn1', ...);

h_btn2 =uicontrol('Parent', h_fig, ‘Tag', 'btn2', ...);

h_btn3 =uicontrol('Parent', h_fig, ‘Tag', 'btn3', ...);

如果我們要在窗口1的任何回調(diào)函數(shù)中,直接訪問子窗口2的任意控件琉朽,可以在上述語句后緊跟著寫下如下語句:

handles.btn1 =h_btn1;

handles.btn2 =h_btn2;

handles.btn3 =h_btn3;

最后毒租,需要一個(gè)guidata語句。當(dāng)然箱叁,Opening函數(shù)最后有g(shù)uidata語句墅垮,所以不用自己添加。

方法4:將要共享的數(shù)據(jù)使用save函數(shù)存入mat文件耕漱;或者使用文件I/O函數(shù)算色,存入文本文件中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末螟够,一起剝皮案震驚了整個(gè)濱河市灾梦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妓笙,老刑警劉巖若河,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異寞宫,居然都是意外死亡萧福,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門辈赋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲫忍,“玉大人,你說我怎么就攤上這事钥屈∥蛎瘢” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵篷就,是天一觀的道長射亏。 經(jīng)常有香客問我,道長腻脏,這世上最難降的妖魔是什么鸦泳? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任银锻,我火速辦了婚禮永品,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘击纬。我一直安慰自己鼎姐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著炕桨,像睡著了一般饭尝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上献宫,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天钥平,我揣著相機(jī)與錄音,去河邊找鬼姊途。 笑死涉瘾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捷兰。 我是一名探鬼主播立叛,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼贡茅!你這毒婦竟也來了秘蛇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤顶考,失蹤者是張志新(化名)和其女友劉穎赁还,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驹沿,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秽浇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了甚负。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柬焕。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梭域,靈堂內(nèi)的尸體忽然破棺而出斑举,到底是詐尸還是另有隱情,我是刑警寧澤病涨,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布富玷,位于F島的核電站,受9級特大地震影響既穆,放射性物質(zhì)發(fā)生泄漏赎懦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一幻工、第九天 我趴在偏房一處隱蔽的房頂上張望励两。 院中可真熱鬧,春花似錦囊颅、人聲如沸当悔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盲憎。三九已至嗅骄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饼疙,已是汗流浹背溺森。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窑眯,地道東北人儿惫。 一個(gè)月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像伸但,于是被迫代替她去往敵國和親肾请。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容