簡體   English   中英

回調函數內部值的實時更新[這些值來自(另一個.m文件的)外部函數]

[英]Real-time update of values inside a call_back function[the values are from external function(of another .m file)]

我有一個外部函數說“ external_func”(單獨的.m文件)

在此函數中,調用了while循環,該while循環更新了一個名為“ update_prog”的變量

現在,我將使用

assignin('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循環。 我用過“ drawedow”,但是沒有用。

當“ external_func”中的while循環經歷多次迭代時,如何優化該值“ update_prog”。 [注意:更新的值在GUIDE的回調函數中,但是除非有回調,否則回調函數將不會更新“ update_prog”],因此如何在call_back函數中實現此實時更新。

[注意:在我的情況下,無法通過函數輸入傳遞變量,因此我正在尋找替代方法]

Edit1:請考慮此鏈接,其中包含一個示例,該示例可以闡明您我要達到的目標

我在這里做的是

  1. 將變量(在外部函數的while循環中正在更新的變量)傳遞到GUI中。
  2. 我將使用此變量在進度條(滑塊)上顯示進度。

問題是什么? 1. GUI回調中的變量(考慮到我將按下一個按鈕,然后使用while循環調用該函數)會將更新后的值放入set(handles.slider,'Value',variable)

通過這樣做,我無法移動滑塊。

為什么?

  1. 僅當我按下按鈕時,回調才會更新變量,接下來將不更新對變量的所有更新,因此進度條/滑塊不會移動。

我不建議您通過一個中間工作區(外部->基礎工作區-> GUI)分三步傳遞變量。 我寧願建議直接傳遞變量(external-> GUI)。

每個Matlab圖形都有一個空間來存儲任何類型的變量(應用程序數據)。 我建議閱讀文章“ 在回調之間共享數據”,並閱讀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會話中運行的所有程序,即root對象。 它的句柄是保留的,並且對於任何程序都是相同的: 0 (盡管自v2014b以來,還有另一種調用它的方法: groot ,但對於所有Matlab來說,它始終是相同的句柄)。

因此,在上面的示例中,在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()不需要任何額外的參數,更新只需要一行:

setappdata( 0 , 'update_prog' , update_prog) ;    %// update the variable value

我“懷疑”基本工作空間中的update_prog變量不是全局變量(必須將其定義為在要使用它的每個工作空間中都是全局變量)。

由於您使用的是全局變量(有許多更好的方法可以執行此操作-但這不是您的問題)-為什么不簡單地將update_prog變量定義為external_func函數中的全局變量(替換assign調用)。

編輯在您的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,這可能會使它變慢。

如果這不能解決您的問題,則需要更好地解釋您想做什么...(我認為)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM