后台:我在GUI中有几个部分来处理不同的任务。在1部分(部分1)我有文本输入和发送按钮。所以一旦我点击发送它就会发送一个数据到我的串口。另一部分(部分2)将从串行端口接收已从其他设备接收的信号。这两个部分都使用两个按钮;一个开始特定部分的工作,一个停止工作。我使用了全局变量和while循环(使用boolean)来退出无限循环,因为我需要连续发送数据或接收数据。
我的问题:问题是当我使用全局变量和上面提到的使用无限循环的方法时,如果我单击part1,则section1将开始迭代。现在,如果我点击part2,那么将停止part1。但我需要同时使用它们,并且它们都会不断发送和接收数据,直到我点击其他按钮退出无限循环。
我的示例代码澄清:
function send_Callback(hObject, eventdata, handles)
global firstFlag;
firstFlag = true;
while firstFlag
%Required codes
end
function haltSend_Callback(hObject, eventdata, handles)
global firstFlag;
firstFlag = false;
function receive_Callback(hObject, eventdata, handles)
global secondFlag;
secondFlag = true;
while true
%Required codes
end
function stopReceive_Callback(hObject, eventdata, handles)
global secondFlag;
secondFlag=false;
我试图找到一个引用互联网的解决方案,但大多数解决方案都使用全局变量。如果我能在没有全局变量的情况下工作会更好。但即使我的要求得到满足(根据我的问题)也行不通。
答案 0 :(得分:2)
全球与否不是这里的问题。
Matlab中的回调都在同一个线程上运行。
因此,当callback1正在运行并触发callback2时,callback2将中断callback1。
callback1将仅在callback2完成后继续。
您只能使用BusyAction
属性
http://www.mathworks.de/de/help/matlab/ref/uicontrol_props.html#bqxoija
但这对你的情况没有帮助。 在“适当的”编程语言中,您将有一个并行运行的发送和接收线程。你不能做这个matlab - 除非你是愿意写java代码。
如果你想坚持使用matlab,最接近线程的就是定时器。
这些将替换您的while
循环。
例如。如下面的简约示例:
function cbtest()
try close('cbtest');end
f = figure('name', 'cbtest');
% create the timers:
period = 0.2; % period in seconds, in which the timer shall execute
sendTimer = timer('TimerFcn', @sendFcn, 'ExecutionMode', 'fixedDelay', 'Period', period, 'TasksToExecute', Inf);
recvTimer = timer('TimerFcn', @recvFcn, 'ExecutionMode', 'fixedDelay', 'Period', period, 'TasksToExecute', Inf);
uicontrol(f, 'position', [10 10 100 25], 'Callback', @(a,b) start(sendTimer), 'string', 'start1');
uicontrol(f, 'position', [120 10 100 25], 'Callback', @(a,b) stop(sendTimer), 'string', 'stop1');
uicontrol(f, 'position', [10 50 100 25], 'Callback', @(a,b) start(recvTimer), 'string', 'start2');
uicontrol(f, 'position', [120 50 100 25], 'Callback', @(a,b) stop(recvTimer), 'string', 'stop2');
end
function sendFcn(hTimer, timerEvt)
% your send-loop-code
disp('sending');
end
function recvFcn(hTimer, timerEvt)
% your receive-loop-code
disp('receiving');
end
sendFcn
和recvFcn
此处应包含您在相应的while循环中的代码。
您当然可以根据需要降低period
,我选择上述内容进行测试。
答案 1 :(得分:1)
你的问题是你在Callbacks中执行循环。因此,当单击第二个按钮时,第二个回调将开始并无限循环,直到它结束。第一个循环将等待第二个Callback终止,直到它可以恢复。你需要的是一个执行循环的主程序。嵌套回调将确保他们可以访问和更改局部变量,而不会使它们成为全局变量。如果您可以通过编程方式构建GUI,请尝试以下方法:
function main()
sendFlag = false;
receiveFlag = false;
while true
if sendFlag
% Your Sending code
end
if receiveFlag
% Your Receiving code
end
end
function send_Callback(~,~,~)
sendFlag = true;
end
% other Callbacks
end
然后在你的按钮的回调中(你可以使用Toggle Buttons),你只需分别设置sendFlag和receiveFlag。
使用GUIDE,您想使用切换按钮。 我并不完全知道GUIDE如何处理OpeningFcn,因此你应该在你的GUI中放置一个“开始”按钮,基本上执行上面的程序并进行一些更改:
function startbutton_Callback(hObject,~,handles)
while true
handles = guidata(hObject); % Updates handles structure
sendFlag = get(handles.sendtoggle, 'Value');
if sendFlag
% Your Sending code
end
receiveFlag = get(handles.receivetoggle, 'Value');
if receiveFlag
% Your Receiving code
end
end
此外,创建发送和接收切换按钮并将它们的'Min'设置为0,将'Max'设置为1.这将使它们在0和1之间切换它们的'Value'属性(在上面的循环中读取)你点击它们。在回调中,您可以更改它们显示的内容:
function send_Callback(hObject,~,handles)
on = get(hObject,'Value');
if on
set(hObject, 'String', 'Stop sending');
else
set(hObject, 'String', 'Start sending');
end
guidata(hObject,handles); % Update GUI data
现在,您的主要功能(单击开始按钮时启动)会运行循环,只检查切换按钮的状态以确定是否发送和接收。