matlab set_param function doesn't work in loop - matlab

I have a Matlab GUI code that lets you draw on axes and passes the coordinates to a constant in Simulink. While the mouse button is held down it should draw on the axes and send the coordinates and when it'not, it should send the coordinates but it should not draw. Here is the code:
`
function figure1_WindowButtonUpFcn(hObject, eventdata, handles)
% hObject handle to figure1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global bool;
bool=false;
set(handles.figure1,'WindowButtonMotionFcn',#(hObject,eventdata)figure1_WindowButtonMotionFcn(hObject,eventdata,guidata(hObject)));
%set the WindownButtonMotionFcn back in order to make it work again
function figure1_WindowButtonDownFcn(hObject, eventdata, handles)
set(handles.figure1,'WindowButtonMotionFcn',#empty); %change the windowbuttonmotionfcn in order not to let it work
global bool;
bool=true;
global lastX;
global lastY;
x=0;
while bool
coord=get(handles.axes4,'CurrentPoint');
if coord(1)<0.003
coord(1)=0.003
x=0;
end
if coord(1)>1
coord(1)=1
x=0;
end
if coord(3)<0
coord(3)=0
x=0;
end
if coord(3)>0.95
coord(3)=0.95
x=0;
end
if x>1
arrayX=[lastX coord(1)];
arrayY=[lastY coord(3)];
line(arrayX,arrayY);
set_param('dosya_yukle_deneme/Constant','value',num2str(coord(1)));
end
x=x+1;
lastX=coord(1);
lastY=coord(3);
drawnow;
end
function empty(~,~,~)
% --- Executes on mouse motion over figure - except title and menu.
function figure1_WindowButtonMotionFcn(hObject, eventdata, handles)
coord=get(handles.axes4,'CurrentPoint');
set_param('dosya_yukle_deneme/Constant','value',num2str(coord(1)));
While the mouse button is pressed down, it draws the lines but the set_param function doesn't work. However, the one in the figure1_WindowButtonMotionFcn works pretty well when needed. It seems like the problem is the while loop. Any help would be appreciated.

You can't run your while loop within the figure1_WindowButtonDownFcn callback because the Matlab GUI is single-threaded. This means the while loop is blocking the Matlab GUI and preventing things from updating correctly. You need to let the callback return in order for Matlab to be able to update the GUI. This is a general rule for GUI callbacks in Matlab; whatever you do in the callback will block the GUI.
In fact you don't need a while loop at all, because WindowButtonMotionFcn will call back every time the cursor changes. You put the code inside the loop into the figure1_WindowButtonMotionFcn callback. You will also need an extra global flag indicating whether the button is down or not, but that is easy to create. figure1_WindowButtonDownFcn should set the button down flag, and figure1_WindowButtonUpFcn resets the button down flag. Then figure1_WindowButtonMotionFcn checks whether the button down flag is set, and if it is, then it executes the code within your while loop.

I solved the problem! So I found out that the code was working since the beginning. I had connected the constant to a display, while the figure1_WindowButtonMotionFcn was working it showed the value but not while the other one was working. It seems to be that it's a bug in MATLAB UI; the display doesn't renew itself when a mouse button is detected.

Related

How to detect a push button press and release in matlab

i have a GUI based in matlab 2015 to code
when i push/ press the button one of edit box data keeps changing but i want its value to keep on changing according to my call back until i release it
for now i have to keep on clicking my push button again and again which changes my edit box value
Kindly suggest me a workarround
% --- Executes on button press in pushbutton27.
function pushbutton27_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton27 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
Freq = (str2double(get(handles.edit4,'String')))+ 0.001;
if Freq > 20
set(handles.edit4,'String','20');
else
set(handles.edit4,'String',num2str(Freq));
end
uicontrol has only the Callback and ButtonDownFcn properties that respond to mouse clicks. If the property Enable of the uicontrol is set to 'on', only the function specified in Callback reacts to left-clicks. If the property is set to 'off' or 'inactive' it also reacts to right-clicks. Because for inactive uicontrols you cannot change the Value by clicking on it, I don't see a direct solution using uicontrol.
A solution is to use the figure's WindowButtonDownFcn and WindowButtonUpFcn properties. For the button down you could use something like:
function buttondown(hobj,~,hedit)
hobj.UserData = true;
while hobj.UserData
pause(0.2); % put a pause so it doesnt change too fast
hedit.String = datestr(now); % you can set it to anything you want here
end
end
For the button up:
function buttonup(hobj,~)
hObj.UserData = false;
end
Of course, if you have multiple buttons that have to work this way, in the buttondown function you must test where the cursor's position is that by checking the CurrentPoint property.

continuous slider listener creates a new blank figure

I'm working on a program and have decided to build a GUI around it. What I'd like to start with is pretty simple, load up a movie and be able to scroll through it. I've looked at a lot of the questions regarding listeners, and in fact someone asked this question but the solution there didn't seem to work for me.
in my opening function of the gui I have
handles.output = hObject;
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(hObject, event) Image_Slider_ContValueCallback(...
hObject, eventdata, handles));
% Update handles structure
guidata(hObject, handles);
And then I have the following two call backs :
function Image_Slider_Callback(hObject, eventdata, handles)
% hObject handle to Image_Slider (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles=guidata(hObject);
current_slice = round(get(handles.Image_Slider,'Value'));
%size(handles.Image_Sequence_Data(:,:,current_slice));
im =imagesc(handles.Image_Sequence_Data(:,:,current_slice),'Parent',handles.Image_Sequence_Plot);
colormap('gray');
which works fine (without the listener everything behaves properly)
AND then I also have
function Image_Slider_ContValueCallback(hObject, eventdata, handles)
% hObject handle to Image_Slider (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles=guidata(hObject);
current_slice = round(get(handles.Image_Slider,'Value'));
%size(handles.Image_Sequence_Data(:,:,current_slice));
handles=guidata(hObject);
%im =
imagesc(handles.Image_Sequence_Data(:,:,current_slice),'Parent',handles.Image_Sequence_Plot);
colormap('gray');
which I think should be called when the slider is moved continuously. My issue is that EACH time the slider value is changed a blank ("figure 1") appears. The actual GUI data responds correctly, but I don't understand why/where this 'rogue' figure is coming from..
someone please help. Also, any opinions on imshow vs. imagesc as to which is better (this GUI will involve a lot of user interaction with the image)
I had pretty much the same problem once! I don't have access to Matlab right now so I can't test a working example , but for the moment I would suggest to place this line:
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(hObject, event) Image_Slider_ContValueCallback(...
hObject, eventdata, handles));
in the CreateFcn of your slider. Maybe a blank figure appears each time you move the slider since it does not know that it's linked to a listener object and thus creates one continuously.
If it does not work, you can call a function outside of the GUI to update the current frame displayed in your axes, for instance:
handles.sliderListener = addlistener(handles.Image_Slider,'ContinuousValueChange', ...
#(a,b) UpdateCurrentFrame);
instead of the callback in your GUI. a and b are dummy input arguments and UpdateCurrentFrame can simply contain a call to imshow for example. It might not be the most elegant way but it worked perfectly for me.
Oh and as for your question about imagesc and imshow, I personnally prefer imshow. In my case, I used text annotations and rectangles for ROI selection and so on, and had little problems with imagesc in terms of images not updating correctly or rectangles being stuck...but it might be that I was not using it correctly though.
Hope that helps!

Using addlister in MATLAB GUI seems to "delete" existing handles

I am quite new to MATLAB GUI programming (using GUIDE sorry) and I have the following issue: The GUI displays on an axis an image sequence stored in a cell array. I have a couple of pushbuttons and a slider to scroll through the sequence. In order to get a 'continuous slider' I use a listener, which kind of works but creates some problems:
1) When I press the slider, a figure is created and the first frame of the sequence is displayed in it, but as I move the slider the sequence is displayed in the axis of my GUI (which is what I want) and the figure becomes empty. Can anybody tell me why this figure is created and how can I avoid it?
2) Once I press the slider button and thus use the listener, all handles inside the GUI are not functionnal as Matlab does not recognize them and I'm stuck with a functionnal slider/display but I can't use the pushbuttons.
Any ideas on why this happens? Here is the code I use in the Create Function of the slider:
function slider2_Frame_Video_Callback(hObject, eventdata, handles)
hListener = addlistener(hObject,'ContinuousValueChange',#(a,b) slider2_Frame_Video_Callback(hObject, eventdata, handles)); % a and b are dummy arguments
guidata(hObject,handles)
In the slider callback, the code looks like this (basically imshow in the current axis):
axes(hAxis)
imshow(Movie{frame},'parent',hAxis);
drawnow
% This does not work either as handles.edit_FrameNumber is not recognized by Matlab
set(handles.edit_FrameNumber, 'String', frame);
guidata(hObject,handles);
Any hints are welcome thanks!
I wonder if part of the problem is that a listener is being instantiated each time the user moves the slider since the listener code is within this callback AND that the callback being provided to the listener (seems like some kind of strange back-and-forth there). So every time the user releases the mouse button after a slide, a new listener is created. This may be causing some problems with the other buttons not being responsive.
Rather than instantiating the listener there, I would do this in the Opening_Fcn of your GUI:
% --- Executes just before frameSlider is made visible.
function frameSlider_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to frameSlider (see VARARGIN)
% Choose default command line output for frameSlider
handles.output = hObject;
if ~isfield(handles,'hListener')
handles.hListener = ...
addlistener(handles.slider1,'ContinuousValueChange',#respondToContSlideCallback);
end
% Update handles structure
guidata(hObject, handles);
My GUI is named frameSlider; yours will be something else. The above creates one listener with a callback to a function that you will need to define in the same *.m file, respondToContSlideCallback.
A sample body for the callback that is to respond to the continuous slide is
% --- Executes on slider movement.
function respondToContSlideCallback(hObject, eventdata)
% hObject handle to slider1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% Hints: get(hObject,'Value') returns position of slider
% get(hObject,'Min') and get(hObject,'Max') to determine range of slider
% first we need the handles structure which we can get from hObject
handles = guidata(hObject);
% test to display the current value along the slider
disp(['at slider coordinate ' num2str(get(hObject,'Value'))]);
If you run this code, the Command Window will display continuously the slider coordinate as you move the slider from end to end.
Your above code has a Movies cell array. How is that being accessed by your callback? Is it a global variable or ..? Where does hist come from? If Movies is the result of some other function call, then it can be saved to handles too (in whichever location it gets loaded from file). I suppose you will also have to map the slider control coordinates to the number of frames that you have (though maybe you have already done this?).

Show whether the GUI is running or not in matlab GUIDE

I'm currently creating a GUI using mathlab GUIDE. Since the GUI is very slow I'd like to add an edit_text uicontrol in order to show whether the GUI is running or not.
For instance I have a push_button that changes the plot in an axes. When the user click on this button the GUI takes several seconds to perform the new plot. What I want to do is setting the edit_text with the string 'running' as soon as the button was pressed. When the callback is done and the plot plotted I'd like to set the edit_text with another string : 'ready'.
I used the following code :
function push_button_Callback(hObject, eventdata, handles)
% hObject handle to push_button (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
set(handles.edit_text,'String','Running...');
%a bunch of code...
set(handles.edit_text,'String','Ready.');
guidata(hObject,handles);
I hoped that once the callback is called, the GUI would display 'running...' on my edit_text. Apparently I was wrong. When running the GUI and pressing the push_button the plot changes but the edit_text remains the same.
Then I tried something else using the ButtonDownFcn callback. My idea was that the latter callback would be executed before the actual callback (written above). Here is the code :
function push_button_ButtonDownFcn(hObject, eventdata, handles)
% hObject handle to push_button (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
set(handles.edit_text,'String','Running...');
guidata(hObject,handles);
The problem is that the ButtonDownFcn callback isn't executed every time. As GUIDE says about the latter callback :
% --- If Enable == 'on', executes on mouse press in 5 pixel border.
% --- Otherwise, executes on mouse press in 5 pixel border or over str22.
Obviously I want my push_button to be enabled, otherwise it won't work the way I want. So I don't know what else to try.
Has someone any idea how I could manage to do that ?
You could try doing
set(handles.edit_text,'String','Running...');
drawnow;
%a bunch of code...
The GUI might not be updated until you get to
set(handles.edit_text,'String','Ready.');
So forcing it to update with drawnow might work for you.

Use selected radio button in another function

I have GUI created with GUIDE. I have 3 radiobuttons in a group. When I run the program and after I enter in values for some calculations I get plots for pressure, temperature, lift/drag force (dependent on which radiobutton I push). The structure of program is as follows:
Main code (GUI):
passes values to a function named Apollo after the "Calculate" button is pushed.
Apollo code:
contains sub functions to calculate necessary values for the calculation of the pressure, temperature, and lift/drag force. Last sub function is called plot_data. This function plots the shape of the space craft in one figure and plots the pressure, temperature, lift/drag force in another figure upon selection of the corresponding radiobutton.
Problem - I'm new at programming a GUI. I'm having problems figuring out how to determine which radiobutton is selected from the GUI and using some sort of logic as a switch in my plot_data function. I would like for the select case to be in the plot_data function.
Any help would be appreciated.
Let's say your radiobutton handles are rb1 and rb2 and they are stored in handles structure. Then, you can check if they are selected using the 'Value' property.
function apollo(hObj, eventdata, handles)
if get(handles.hrb1, 'Value')
% do stuff
elseif get(handles.hrb2, 'Value')
% do other stuff
end
end
Update: Response to OP's comment about SelectionChangeFcn:
If you do not have a lot of data you can plot them all at the beginning and then change the Visible properties of the plots.
function cbSelectionChange(hObj, eventdata, handles)
rbTag = get(eventData.NewValue, 'Tag');
switch rbTag
case 'rb1'
set(handles.plotHandle1, 'Visible', 'On');
set(handles.plotHandle2, 'Visible', 'Off');
case 'rb2'
set(handles.plotHandle2, 'Visible', 'On');
set(handles.plotHandle1, 'Visible', 'Off');
end
end
If you do have a lot data you can call plot_data function from SelectionChangeFcn callback.
function cbSelectionChange(hObj, eventdata, handles)
rbTag = get(eventData.NewValue, 'Tag');
switch rbTag
case 'rb1'
plot_data(yourArguments1);
case 'rb2'
plot_data(yourArguments2);
end
end
Performance of your code will not be affected by passing the data unless you modify it. Doug Hull says here:
MATLAB uses a system commonly called "copy-on-write" to avoid making a
copy of the input argument inside the function workspace until or
unless you modify the input argument. If you do not modify the input
argument, MATLAB will avoid making a copy.
If you want to do something after user clicks on a radiobutton, you should edit "callback" property of your object.
If you want to test the state of radiobutton from your code, your should check "Value" property. It would be one for selected button and zero otherwise.
Look through this tutorial