我有一个外部函数说“external_func”(单独的.m文件)
在此函数内部调用while循环,此while循环更新名为“update_prog”的变量
现在我将使用
将此值传递给GUIDEassignin('base', 'update_prog', update_prog); % passing to workspace
我正在制作
“update_prog”作为全局变量并将其调用到GUIDE .m文件
function pb1_Callback(hObject, eventdata, handles)
global update_prog
% hObject handle to pb1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% else
% set(handles.pb1,'enable','on');
% end
% update_prog first value prints, but it wont updates as the loop in external_func goes on.
drawnow;
set(handles.slider1,'Value',update_prog)
external_func;
所以在GUIDE .m文件中我可以得到值
“update_prog”但它不会跟上while循环。我使用“drawow”但它没用。
如何在“external_func”中的while循环经历多次迭代时,如何优化此值“update_prog”。 [注意:更新的值存在于GUIDE的回调函数中,但除非有回调函数,否则回调函数不会更新“update_prog”],那么如何在call_back函数内实现这种实时更新。
[注意:在我的情况下,通过函数输入传递变量是不可能的,所以我正在寻找替代方案]
Edit1:请考虑此链接,其中有一个示例Which may clarify you what I am trying to acheive
我在这里做的是
有什么问题?
1. GUI回调中的变量(Consdier I将按下按钮,然后它将使用while循环调用该函数)将更新的值放入set(handles.slider,'Value',variable)
通过这样做,我无法移动滑块。
为什么?
答案 0 :(得分:1)
我不建议使用中间工作区(外部 - >基础工作区 - > GUI)以3个步骤传递变量。我宁愿建议直接传递你的变量(external-> GUI)。
每个Matlab图提供了一个存储任何类型变量(应用程序数据)的空间。我建议阅读文章Share Data Among Callbacks并阅读3个函数的文档:
通过这种方式,您可以更好地控制变量的范围,并且您不需要任何global
声明。
下面是一个简单gui的例子。 gui在其用户空间(使用setappdata
)中声明变量,然后使用计时器定期读取此变量(使用getappdata
)。
外部函数执行您想要的任何操作(在示例中只是一个随机数),然后更新您使用相同setappdata
的变量。你唯一需要的是主GUI图形的句柄,所以在这个例子中我把它作为外部函数的输入。
GUI还有两个按钮来启动和停止更新。
主要示例GUI的代码' theGui.m'是:
function h = theGui
%// basic GUI with 2 buttons and 1 slider
h.fig = figure('Position',[433 434 500 100],'Menubar','none','CloseRequestFcn',@my_closefcn) ;
h.sld = uicontrol('Style','Slider','Position',[20 20 460 20]) ;
h.btnStart = uicontrol('Style','pushbutton','String','Start updating','Callback',@btnStart_callback,'Position',[20 50 200 30]);
h.btnStop = uicontrol('Style','pushbutton','String','Stop updating','Callback',@btnStop_callback,'Position',[280 50 200 30],'Max',1,'Min',0);
%// Define the timer
h.t = timer ;
h.t.Period = 0.1 ; %// 0.1s refresh interval
h.t.TimerFcn = {@timer_callback,h.fig} ;
h.t.ExecutionMode = 'fixedSpacing' ;
%// initialise the variable to update in the GUI appdata
update_prog = 0 ;
setappdata( h.fig , 'update_prog' , update_prog ) ;
%// save handles
guidata( h.fig , h );
function btnStart_callback(hobj,~)
h = guidata( hobj ) ; %// retrieve handles
if strcmp('off',h.t.Running) %// Start timer (only if not already running)
start(h.t)
end
function btnStop_callback(hobj,~)
h = guidata( hobj ) ; %// retrieve handles
stop(h.t) %// Stop timer
function timer_callback(~,~,hfig)
update_prog = getappdata( hfig , 'update_prog' ) ; %// retrieve the 'update_prog' variable value
h = guidata( hfig ) ; %// retrieve handles
set(h.sld , 'Value' , update_prog) ; %// update the slider object with the retrieved value
function my_closefcn(hobj,~)
%// this function is only to clean up when the GUI will be closed.
%// It is recommended to delete the timer manually
h = guidata( hobj ) ; %// retrieve handles
stop(h.t) %// Stop timer (in case it is still running)
delete(h.t) ; %// delete the timer
delete(h.fig) ; %// destroy the figure
external_func.m
function external_func( guiMainFigureHandle )
%// This function will only generate random numbers and push them into the
%// variable 'update_prog' contained in the GUI appdata.
%// This is why this function NEEDS the handle of the gui to be able to
%// access the Application Data space of the gui.
for k = 1:100
randomValue = rand(1) ; %// generate a random value
hfig = ancestor( guiMainFigureHandle , 'figure' ) ; %// make sure the handle provided is the top level figure
setappdata( hfig , 'update_prog' , randomValue) ; %// update the variable value
pause(0.1) ;
end
编辑:
我将其置于编辑中而不是更改上面的代码,因为如果您不需要,我建议您不要使用root
对象。但在你的情况下,它可以解决你的问题。
如果您的外部功能无法访问GUI,它可以随时更新可用于所有在给定Matlab会话中运行的程序的内存部分,即{ {1}}对象。它的句柄是保留的,对于任何程序都是相同的:root
(虽然从v2014b开始有另一种方法可以调用它:groot,它仍然是所有Matlab的相同句柄。)< / p>
因此,在上面的示例中,在0
中,请改为使用:
theGui.m
在主程序中,然后在子功能setappdata( 0 , 'update_prog' , update_prog ) ;
中,使用:
function timer_callback(~,~,hfig)
你的函数update_prog = getappdata( 0 , 'update_prog' ) ; %// retrieve the 'update_prog' variable
不需要任何额外的参数,更新只需要一行:
external_func()
答案 1 :(得分:0)
我“怀疑”基础工作区中的update_prog
变量不是全局变量(您必须在要使用它的每个工作空间中将其定义为全局变量)。
由于您使用全局变量(有很多更好的方法可以做到这一点 - 但这不是您的问题) - 为什么不简单地将update_prog
变量定义为external_func
函数中的全局变量(替换分配呼叫。)
编辑在您的external_func
功能中添加一个drawow。这样当你点击按钮时它会更新。
编辑3
我想我知道你想做什么,尝试这个例子,看看它是否符合你的要求 - 更新以显示如何在代码中找到滑块对象并在循环内更新:
function mygui
% create a figure
f = figure;
% create a uicontrol slider - note that I give it a tag.
uicontrol ( 'style', 'slider', 'Position', [0 200 200 40], 'tag', 'MYSLIDER', 'backgroundcolor', 'white', 'parent', f );
% create a push button which we can press to update
uicontrol ( 'string', 'Press 2 start', 'callback', @(a,b)myLoop(), 'Position', [0 0 200 50] )
end
% This replicates your "external_func" function.
function myLoop()
% since you cant pass in any var -> you need to find the slider object
% you can do this by using findobj and search for the tag of the item
uic = findobj ( 0, 'tag', 'MYSLIDER' );
% find the figure handle (only needed for this demo)
f = ancestor ( uic, 'figure' );
% initialise the value which will be used to update the slider
count = 0;
% create your loop
while ishandle(f)
% incrememt the count variable -> this will end up on the slider value
count = count + 1e-5;
% reset count if > 1 -> so the slider cant go out of range.
if count >= 1
count = 0;
end
set ( uic, 'Value', count );
% initiate a drawnow -> this allows matlab to process GUI events
drawnow();
end
end
这样做的缺点是你在循环中插入一个drawow - &gt;这可能会减慢它的速度。
如果这不能解决您的问题,您需要更好地解释您想要做的事情......(在我看来)