MATLAB uicontrol 回调返回矩阵

Posted

技术标签:

【中文标题】MATLAB uicontrol 回调返回矩阵【英文标题】:MATLAB uicontrol callback return matrix 【发布时间】:2017-11-13 20:02:04 【问题描述】:

原帖:MATLAB scrolling plot

我的问题现在有了第二部分。 和以前一样,我正在绘制一个 19*1000*134 矩阵,这要归功于 Aero Engy 在上一篇文章中的出色回答。

我想在我的工作区中创建一个名为 clean 的向量,其长度为 134。

默认情况下,clean(i) 的值(i 介于 1 和 134 之间)将为 1 -- 但是,如果我按下 UI 界面上的按钮,该值必须变为 0。

我的代码如下,只是不要给我任何输出。该按钮似乎可以工作,但是当我关闭该图时,我没有得到干净的矢量。

function cleanData(data);
% data = rand(19,1000,134);
global clean
clean = ones(1,size(data,3));
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',@sliderChange,a);
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',@changeChannel,a,s,data);
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',@notClean,clean,s);

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.Stringl.Value);
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
viewI = round(s.Value);
disp(['Current Epoch: ' num2str(viewI)]) %console print
xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])

function notClean(c,evtData,clean,s)
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print

我做错了什么?

奖励:如果

当我按下“不干净”按钮时,滑块会改变值并增加(目前,我必须按下按钮,然后按下滑块的右箭头才能转到接下来 2 秒的数据)。李> 一旦我为一个通道(矩阵的 19 行之一)检查了“干净”或“不干净”,对于下一个通道,它将跳过“不干净”数据(即干净中的 0对应于纪元数的矩阵)。

感谢您的帮助,我是 MATLAB 的新手,即使我进步很快,我也远没有完全理解这段代码。

【问题讨论】:

【参考方案1】:

在 notClean 回调中,我将clean 作为全局对象调用。我还把它作为输入删除了……因为它是一个全局的,所以没有必要传入它。

我还添加了代码以在您每次按下按钮时推进滑块 1。

关闭 GUI 后,在您的工作区中查看您标记的内容,您只需在命令行中执行以下操作即可访问您的 clean 数组。 (数字是我标记为不干净的随机事物。

我现在必须离开,所以我无法解决关于更改频道和跳过 ~clean elementr 的第二个项目符号......但这应该不会很难。我会在几个小时后回到这里。

>> global clean
>> find(~clean)
ans =
  3  4  11 19

修改代码: 编辑:在边缘添加代码保护以跳过频道。

function cleanData(data)
% data = rand(19,1000,134);
global clean
clean = ones(1,size(data,3));
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',@sliderChange,a);
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',@changeChannel,a,s,data);
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',@notClean,s,a);

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.Stringl.Value);
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
global clean
persistent prevI

if isempty(prevI)
    prevI = 1;
end

viewI = round(s.Value);
sDir = sign(viewI - prevI);  %-1 if going backwards +1 if going forward
prevI = viewI;

if clean(viewI) == 0
    newPos = viewI + sDir;
    if newPos < 1 || newPos > s.Max
        return
    end
    s.Value = newPos; 
    sliderChange(s,[],a)
else
    disp(['Current Epoch: ' num2str(viewI)]) %console print
    xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])  
end


function notClean(c,evtData,s,a)
global clean %Call the global
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print
%Advance to the next slider position.
if num+1 < s.Max
    s.Value = num+1;
    sliderChange(s,[],a)
end

【讨论】:

谢谢,我了解了全局变量的工作原理,并且我也找到了第二部分的方法,我将其作为新答案发布。 嘿!你能看看我为第二部分所做的改变吗?它产生了 2 个我无法解决的问题。 1,如果我在轴的末端按“清洁”(即没有更多的步骤可移动),它会崩溃 // 2. 如果我之前在幻灯片上按清洁,滑块上的左箭头将不再起作用. @Mathieu 我会看看今晚晚些时候我能做些什么。 @Mathieu Try mode modified code out in this answer。我想我在第一个和最后一个时期标记不干净并尝试使用箭头时涵盖了各种错误情况。【参考方案2】:

修改后的代码也适用于第二部分:

function cleanData(data);
% data = rand(19,1000,134);
f = figure('Units','Normalized','Position',[0.25 0.25 0.5 0.5]);
a =   axes('Units','Normalized','Position',[0.05 0.15, 0.75 0.75]);
s =   uicontrol(f, 'Style','Slider', 'Units','Normalized','Position',[0.05 0.025, 0.75 0.05],...
                   'Min',1,'Max',size(data,3),'Value',1, 'Callback',@sliderChange,a);
l =   uicontrol(f, 'Style','listbox','Units','Normalized','Position',[0.85 0.15, 0.1, 0.75],...
                   'String',cellstr(num2str([1:size(data,1)]')),'Callback',@changeChannel,a,s,data);
c = uicontrol(f, 'Style','pushbutton','Units','Normalized','String','Not clean',...
                   'Position',[0.85 0.025 0.1 0.05],'Callback',@notClean,s,a);

stepSize = 1/(s.Max - s.Min);
s.SliderStep = [stepSize 2*stepSize];               
changeChannel(l,[],a,s,data)

function changeChannel(l,evtData,a,s,data)
cla(a);
chanNum = str2double(l.Stringl.Value);
sR = 500;  %500Hz
tempData = reshape(data(chanNum,:,:),[],size(data,3)); %Reshape each epoch into a column
tempTime = [0:1/sR:(size(data,2)-1)/sR]' + (0:1:size(data,3)-1)*2; %Build time array
plot(a,tempTime,tempData) %plot all the lines
s.Value = 1; %Rest Slider Position

function sliderChange(s,evtData,a)
global clean
viewI = round(s.Value);
if clean(viewI) == 0
    s.Value = s.Value+1;
    sliderChange(s,[],a)
else
    disp(['Current Epoch: ' num2str(viewI)]) %console print
    xlim(a,[(viewI-1)*2 viewI*2] + [-.1 .1])  
end


function notClean(c,evtData,s,a)
global clean %Call the global
num = round(s.Value);
clean(num) = 0;
disp(['Epoch ' num2str(num) ' not clean']) %console print
%Advance to the next slider position.
s.Value = num+1;
sliderChange(s,[],a)

【讨论】:

不错。这也是我打算为第二部分做的事情。 完美!谢谢!

以上是关于MATLAB uicontrol 回调返回矩阵的主要内容,如果未能解决你的问题,请参考以下文章

matlab中无法调用uicontrol按钮的回调

uicontrol 回调函数输入参数过多

用户更新后从 Matlab 编辑 uicontrol 中删除光标?

Matlab UI控制单元

Matlab uicontrol 列表框在关闭时返回而不是立即返回

UIcontrol 按钮以在 matlab 中绘制工作区中的数据