Matlab GUI使用GUIDE:想要动态更新图形

发布于 2024-12-25 10:34:25 字数 2009 浏览 2 评论 0原文

我编写了一个 Matlab 脚本,可以使用虚拟 COMM 端口实时读取数据。我在 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

I've written a Matlab script that reads in data using a virtual COMM port in real-time. I've done a significant amount of signal processing in an mfile.

Next, I felt the need to have a compact GUI that displays the information as summary.

I only recently started digging and reading more of Matlab's built-in GUI tool, GUIDE. I've followed a few tutorials and am successfully able to get my graphs to display on my GUI after a button-press.

However, I want the GUI to update in real-time. My data vector is constantly updating (reading in data from the COMM port). I want the GUI to keep updating the graphs with the newer data, as opposed to relying on a button press for an update. Can someone please point me in the right direction for background updating?

Here is the relevant code currently for the 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);

EDIT Changed code:

% --- 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);

The error that I get is:

??? 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

渡你暖光 2025-01-01 10:34:25

以下是使用带有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() 函数设置这些属性,例如,也许我想这样做。更改一些开始按钮的文本 您可能只想在代码

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

中的某个位置设置一个断点(也许是在按下按钮时),然后在各种对象上运行 get() 命令来学习。 现在,handles结构

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

前任。 “startButton”回调被自动传递handles。因此我可以通过handles.timer轻松访问计时器对象。

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

但是,要永久存储这些内容,您需要使用“guidata”功能。该函数基本上要么存储修改后的句柄结构,要么检索句柄的副本,具体取决于您如何调用它。因此,打开函数中的以下行将修改后的句柄结构(添加了 .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 的句柄。

Here is an example using a timer with a timerFcn callback. I made a simple GUI with 1 axes and 1 button.

In the opening function I initialize the plot and create the timer. In the start button callback I start the timer and start manipulating the data. The timer function callback the just updates the y-data of the line via its handle. Below are the relevant functions from the GUI's M-file (snipped init section and output 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);

You may want a Stop button to stop the timer depending on how your GUI is structured and were/how the data is updated.

Edit: Basic handles info some of this is pretty basic and you may already know it:

An individual handle to an object contains a bunch of properties that you can read with the get() function or set with the set() function. So for example maybe I wanted to change the text of the startButton for some reason in my GUI.

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

You may just want to set a break point in your code somewhere (maybe in a button press) and play around with the handles struct. Running get() commands on various objects to learn their properties.

Now the handles structure contains all of the ... umm... handles to your GUI's objects as well as any custom items that may be convenient for your to store there. Most GUI callbacks automatically get passed the handles struct so you have easy access to all parts of the GUI.

Ex. The 'startButton' callback was automatically passed handles. So I had easy access to the timer object via handles.timer.

Which brings me to sticking custom things into handles. In the opening function I added a new item to the handles structure handles.timer and handles.plot because I knew they would be useful in other callbacks (like button press and the timerFcn callback).

However, to store these things permanently you need to use the 'guidata' function. This function basically either stores the modified handles struct or retrieves a copy of handles depending on how you call it. So the following line in the opening function is storing the modified handles structure (added .timer and .plot) into the main GUI.

guidata(hObject,handles);

Basically any time you add something in handles you should have that line to make the change permanent.

Now the other method of calling it is:

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

This will retrieve the handles structure for the GUI.

And last handles.output = hObject is just the default output when you launch your GUI. IF you call your GUI via Matlab's command line like this h = myGUI; it should return the handle to your GUI.

季末如歌 2025-01-01 10:34:25

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

You need to use a timer object. Set the callback to be the function that updates the plots.

眼角的笑意。 2025-01-01 10:34:25

查看通过数据链接使图形响应
linkdata 命令。

如果同一变量出现在多个图中的图中,您可以
将任何图链接到变量。您可以使用链接图
与使用数据刷标记图形相协调,而且还关于它们
自己的。链接图可以让您

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

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

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

注 1:我必须在子例程中添加一个断点,它会修改全局 y 才能实际看到绘图自动更新。如果数据变化很快,您可能需要绘制、暂停或计时器的某种组合。

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

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

Take a look at Making Graphs Responsive with Data Linking
and the linkdata command.

If the same variable appears in plots in multiple figures, you can
link any of the plots to the variable. You can use linked plots in
concert with Marking Up Graphs with Data Brushing, but also on their
own. Linking plots lets you

  • Make graphs respond to changes in variables in the base workspace or within a function
  • Make graphs respond when you change variables in the Variable Editor and Command Line
  • Modify variables through data brushing that affect different graphical representations of them at once
  • Create graphical "watch windows" for debugging purposes

Watch windows are useful if you program in the MATLAB language. For
example, when refining a data processing algorithm to step through
your code, you can see graphs respond to changes in variables as a
function executes statements.

I made a quick and dirty test seen below and I am not sure how this will work in a GUI verses a function but may do the trick.

Note 1: I had to add a break point in my subroutine where it modifies the global y to actually see the plot auto-update. You may need some combination of drawnow, pause, or a timer if data is getting changed rapidly.

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

Edit: there may be ways around the use of globals depending on how your functions are structured ... but I don't have time to dig into it to much.

流绪微梦 2025-01-01 10:34:25

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

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

You can add a callback on the serial object that executes a plotting function. You must attach the callback to the 'BytesAvailableFcn' event on the object (see this for more details on the properties of the com object).

Essentially, when there are bytes available on the com port, you instruct matlab to run a specific function. In your case, it will be the function updating the GUI. If you need to process the incoming data first, then your callback function will first do the signal processing and then do the plotting commands.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文