8

我编写了一个使用虚拟 COMM 端口实时读取数据的 Matlab 脚本。我在 mfile 中完成了大量的信号处理。

接下来,我觉得需要一个紧凑的 GUI,将信息显示为摘要。

我最近才开始挖掘和阅读更多 Matlab 的内置 GUI 工具 GUIDE。我已经学习了一些教程,并且在按下按钮后成功地让我的图表显示在我的 GUI 上。

但是,我希望GUI 实时更新。我的数据向量不断更新(从 COMM 端口读取数据)。我希望 GUI 使用较新的数据不断更新图表,而不是依靠按下按钮进行更新。有人可以为我指出正确的背景更新方向吗?

这是当前用于 GUI 的相关代码:

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global data
global time

% Time domain plot
axes(handles.timeDomainPlot);
cla;
plot (time, data);

编辑更改的代码:

% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%Setting it to display something when it ends
% t = timer('TimerFcn', 'timerOn=false; disp(''Updating GUI!'')',... 
t = timer(... 
            'TasksToExecute', 10, ... % Number of times to run the timer object
            'Period', 3, ...                
            'TimerFcn', GUIUpdate()); 

%Starting the timer
start(t)

function GUIUpdate()
global data
global time
%Parameters below axes
    global min
    global max 
      % Time domain plot
    axes(handles.timeDomainPlot);
    cla;
    plot (time, data);
    %Other parameters:
    set(handles.mean, 'String', mean);
    set(handles.max, 'String', max);

我得到的错误是:

??? Error using ==> GUI_Learning>GUIUpdate
Too many output arguments.

Error in ==>
@(hObject,eventdata)GUI_Learning('pushbutton1_Callback',hObject,eventdata,guidata(hObject))


??? Error while evaluating uicontrol Callback
4

4 回答 4

10

这是一个使用带有 timerFcn 回调的计时器的示例。我用 1 个轴和 1 个按钮制作了一个简单的 GUI。

在打开函数中,我初始化绘图并创建计时器。在开始按钮回调中,我启动计时器并开始操作数据。计时器函数回调只是通过其句柄更新该行的 y 数据。以下是 GUI 的 M 文件中的相关函数(截断 init 部分和输出 fcn.

function testTimer_OpeningFcn(hObject, eventdata, handles, varargin)
global y x
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);
handles.plot = plot(handles.axes1,x,y);
handles.timer = timer('ExecutionMode','fixedRate',...
                    'Period', 0.5,...
                    'TimerFcn', {@GUIUpdate,handles});
handles.output = hObject;
guidata(hObject, handles);

% --- Executes on button press in startButton.
function startButton_Callback(hObject, eventdata, handles)
global y x
start(handles.timer)
for i =1:30
   y = sin(x+i/10); 
   pause(1) 
end

function GUIUpdate(obj,event,handles)
global y 
set(handles.plot,'ydata',y);

您可能需要一个停止按钮来停止计时器,具体取决于您的 GUI 的结构以及数据的更新方式/更新方式。

编辑:基本处理信息其中一些非常基本,您可能已经知道:

对象的单个句柄包含一堆属性,您可以使用 get() 函数读取或使用 set() 函数设置这些属性。例如,也许我想在我的 GUI 中出于某种原因更改 startButton 的文本。

set(handles.startButton,'String','Something Other Than Start');

您可能只想在代码中的某处设置断点(可能在按下按钮时)并使用handles 结构。在各种对象上运行get()命令以了解它们的属性。

现在,handles 结构包含所有...嗯...您的 GUI 对象的句柄以及任何可能方便您存储在那里的自定义项目。大多数 GUI 回调会自动传递给 handles 结构体,因此您可以轻松访问 GUI 的所有部分。

前任。'startButton' 回调被自动传递handles。所以我可以很容易地通过handles.timer.

这让我不得不将自定义的东西放入handles. 在打开的函数中,我向句柄结构添加了一个新项目handles.timerhandles.plot因为我知道它们在其他回调(如按钮按下和 timerFcn 回调)中会很有用。

但是,要永久存储这些内容,您需要使用“guidata”功能。这个函数基本上要么存储修改后的handles结构体,要么检索一个副本,handles具体取决于你如何调用它。因此,打开函数中的以下行将修改后的句柄结构(添加 .timer 和 .plot)存储到主 GUI 中。

guidata(hObject,handles);

基本上,任何时候你添加一些东西,handles你都应该有那条线来使更改永久化。

现在调用它的另一种方法是:

handles = guidata(hObject); %hObject can be any handle who is a child of the main GUI.

这将检索 GUI 的句柄结构。

最后一个handles.output = hObject只是启动 GUI 时的默认输出。如果您像这样通过 Matlab 的命令行调用您的 GUI,h = myGUI; 它应该将句柄返回给您的 GUI。

于 2012-01-08T19:32:38.230 回答
1

您需要使用计时器对象。将回调设置为更新绘图的函数。

于 2012-01-06T00:01:14.743 回答
1

查看使用数据链接和linkdata命令制作响应式图形 。

如果同一变量出现在多个图中的图中,您可以将任何图链接到该变量。您可以将链接图与通过数据刷亮标记图形一起使用,也可以单独使用。链接图可以让您

  • 使图形响应基础工作区或函数内的变量变化
  • 当您在变量编辑器和命令行中更改变量时,使图形响应
  • 通过一次影响变量的不同图形表示的数据刷来修改变量
  • 为调试目的创建图形“监视窗口”

如果您使用 MATLAB 语言进行编程,观察窗口非常有用。例如,在改进数据处理算法以逐步执行代码时,您可以看到图形响应函数执行语句时变量的变化。

我做了一个快速而肮脏的测试,如下所示,我不确定这将如何在 GUI 和函数中工作,但可能会奏效。

注意 1:我必须在我的子程序中添加一个断点,它会修改全局y以实际看到绘图自动更新。如果数据快速更改,您可能需要drawow、pause 或计时器的某种组合。

function testLinking()
global x y
%Links failed if the global did not also exist in the base workspace
evalin('base','global x y');
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);

h = plot(x,y,'ydatasource','y','xdatasource','x');
linkdata on
testSub

function testSub()
%Test to see if a sub can make a linked global refresh
global x y
for i = 1:10
    %This should automatically update the plot.
    y = sin(x+i/10); 
end

编辑:可能有一些方法可以使用全局变量,具体取决于您的函数的结构......但我没有时间深入研究它。

于 2012-01-06T15:37:29.617 回答
0

您可以在执行绘图功能的串行对象上添加回调。您必须将回调附加到对象上的“BytesAvailableFcn”事件(有关 com 对象属性的更多详细信息,请参阅此内容)。

本质上,当 com 端口上有可用字节时,您可以指示 matlab 运行特定函数。在您的情况下,它将是更新 GUI 的功能。如果您需要先处理传入的数据,那么您的回调函数将首先进行信号处理,然后执行绘图命令。

于 2012-01-06T16:57:30.670 回答