MATLAB - Detect double mouse click on figure - matlab

I'm using impoly to allow the user to edit a polygon on a figure. Right now, I'm using pause() to detect when user is done, but I'd rather if it were a double-mouse click (similar to what roipoly does).
I cannot use roipoly though, since it does not allow an initial polygon be plotted, which is necessary.
Any ideas on how to get that?

The impoly tool appears to modify the WindowButtonDownFcn, WindowButtonMotionFcn, WindowButtonUpFcn, WindowKeyPressFcn, and WindowKeyReleaseFcn callbacks of the figure window. I had originally thought that you couldn't modify any of these because they would be overwritten by the callback function used by impoly for its functionality. However, it turns out that they can still be invoked properly. This gives you a few more options:
Modify WindowButtonDownFcn:
To add the ability to detect a double-click, you would have to use the WindowButtonDownFcn callback. For example:
set(gcf, 'WindowButtonDownFcn', #double_click_fcn);
h = impoly();
% Define this function somewhere (nested, local, etc.):
function double_click_fcn(hSource, ~)
if strcmp(get(hSource, 'SelectionType'), 'open')
% Advance to next frame
end
end
Modify WindowScrollWheelFcn:
Whenever I create a GUI where I have to scroll through a number of time points/plots/images, I like to use the WindowScrollWheelFcn callback to advance (scroll up) or rewind (scroll down) the data. You could use it to scroll from frame to frame, displaying whatever polygon has already been drawn (if there is one) or allowing the user to create a new one. For example:
set(gcf, 'WindowScrollWheelFcn', #scroll_fcn)
h = impoly();
% Define this function somewhere (nested, local, etc.):
function scroll_fcn(~, eventData)
if (eventData.VerticalScrollCount < 0)
% Mouse has been scrolled up; move to next frame
else
% Mouse has been scrolled down; move to previous frame
end
end
Modify WindowKeyPressFcn
You could also use the WindowKeyPressFcn callback to allow you to advance frames using keyboard buttons, like the left and right arrow keys. For example:
set(gcf, 'WindowKeyPressFcn', #keypress_fcn)
h = impoly();
% Define this function somewhere (nested, local, etc.):
function keypress_fcn(~, eventData)
switch eventData.Key
case 'rightarrow'
% Right arrow pressed; move to next frame
case 'leftarrow'
% Left arrow pressed; move to previous frame
end
end
For more information on creating all these callbacks, see here.

Related

How to get the current Axes.View after using rotate3d interaction in MATLAB appdesigner?

I'm using MATLAB R2021b appdesigner to design a UI . And my request is that I want to get the current axes view (azimuth & elevation data) after rotating my plot via rotate3d interation tool using my mouse. I have checked the related documentation and found that the following code worked well in the script form:
function demo_mbd2
% Listen to rotate events
surf(peaks);
h = rotate3d;
h.ActionPreCallback = #myprecallback;
h.ActionPostCallback = #mypostcallback;
h.Enable = 'on';
function myprecallback(obj,evd)
disp('A rotation is about to occur.');
function mypostcallback(obj,evd)
newView = round(evd.Axes.View);
msgbox(sprintf('The new view is [%d %d].',newView));
However, I have no idea of how to embed it in the appdesigner environment. For example, I'm not aware of the right form of callback function - neither mypostcallback(app, obj, evd) nor mypostcallback(obj, evd) worked.
I haven't learned so much about call back functions yet I'm in desperate need of solving this specific problem. Could anyone lend me a hand? Are there any feasible ways to use the previous codes, or do we have any other solutions?
Huge thanks!!!

How can I program the cpu to randomly press buttons?

I am creating a game in matlab app designer in which a player plays against the computer opponent. I want to code the CPU to press a button at random when it is its turn. For example, in TicTacToe the player plays against another player but in this case, the opponent is the CPU. The CPU is able to click buttons at random for example if there are 9 buttons it will press on any of those 9 randomly providing it has not been pressed already. I am not sure how to program this any help would be highly appreciated.
I have tried to use the callback function but do not know how to program the cpu to randomly press buttons.
On second thought, this is not as simple as triggering the callback function, because you have to let the AI know when to "press" the button also. So, the part about notifying the AI should be in the callback function as well:
function ButtonPushed(app, event)
% Get the button that triggered the callback function
btn = event.Source;
btn.Text = 'X';
btn.Enable = 'off';
% Now, notify the AI to make its move
AI_btn = app.Button_(randi(9));
% Obviously there are better ways to do this
% I will leave it for your own improvisation
while ~isequal(AI_btn.Enable, 'on')
% If the button is already pressed...
AI_btn = app.Button_(randi(9));
end
AI_btn.Text = 'X';
AI_btn.Enable = 'off';
end

Real time audio matlab. Loop while answering to gui calls

I'm doing a simple GUI in matlab using guide, where I have some sliders to select a frequency or many which then get plotted and played through the speakers. I'm learning real-time sound right now so I thought it'd be neat to incorporate it into the application. I right now have a button that plays the sinusoidal waves for 10 seconds when I press it, but I want a checkbox that disables the button when checked and immediately starts playing the sound continuously until the checkbutton is unchecked again.
I can't really get my head around how to do this in Matlab since I heard Matlab is inherently single threaded. And how to do it right with the GUI and everything since I suspect GUI creation is something you think you do right, but you miss some kind of detail and it only works in some situations.
What I think would be the easy way would be to have the check of the checkbox set the 'Enable' property of the Play button to false, and start an infinite loop that plays it from the real time system object I create. When I however uncheck the checkbox, it should set a flag or something to false and enable the Play button again. Could someone point me to if this is the right approach? How do I make the application listen to clicks on the check box while simultanously being in an infinite loop that processes and plays sound? The simultanous loop should be sensitive to changes in the sliders determining the frequencies and those frequencies are also stored in the handles variable.
Mockup code:
function playbutton_Callback(hObject, eventdata, handles)
freqs = [handles.freq1, handles.freq2, handles.freq3]
hightensecy = sinewave(handles.hightensecx, freqs); %creates a sinewave consisting of the three frequencies. hightensecx is a time vector of ten seconds with a high sample rate.
sound(hightensecy, handles.highsr);
figure;
plot(handles.hightensecx,hightensecy);
function y = sinewave(x, freqs)
% x in sec
y(:,1:size(freqs,2)) = sin(2*pi*x*freqs);
y=sum(y,2)/size(freqs,2);
end
% --- Other code to make the sliders store their values in handles.freq1, handles.freq2... ---
function continuousbox_Callback(hObject, eventdata, handles)
selected = get(hObject,'Value');
if(selected)
set(handles.playbutton, 'Enable', 'off');
startsound(handles);
else
set(handles.playbutton, 'Enable', 'on');
stopsound();
end
% Plays sound continuously
function startsound(handles)
%%Initialization
SamplesPerFrame = 1024;
Fs = handles.highsr;
Player = dsp.AudioPlayer('SampleRate', Fs);
%%Stream
tic
while(1)
%TODO Read in a new 1024 bytes chunk and make sure it has the same
%characteristics as sinewave(x, freqs)
step(Player, outsound)
end
%Stops the continuously played sound
function stopsound()
%TODO Somehow stop the loop inside startsound(handles)
If it is possible, it would be good if the resulting startsound function plays a sound that sounds exactly like the playbutton callback, only indefinitely. I'm also not sure how to handle phase issues that might occur in the real time loop. Should I use a time counter that tics away and calculates the current 1024 chunk's y-value and in that case, should I just use the time distance from tic, or increase it with 1024/sample rate seconds per time? Thanks in advance.

How can I detect the mouse position anywhere on the screen?

I'm working in MATLAB and I want to get the cursor position from anywhere on the screen.
I would like to continuously get the position of the cursor while the mouse is moving. However, I found that MATLAB can get the mouse position while the mouse is moving only in a GUI.
How can I achieve the same thing but not in a GUI in MATLAB?
Are you sure MATLAB can only get the mouse co-ordinates within a GUI? It's actually quite simple to get the position of your mouse anywhere on your screen, independent of a GUI.
Use the following:
get(0, 'PointerLocation')
Try this by moving your mouse around and invoking this command each time. You will see that the output keeps changing when the mouse moves. You'll see that this works independent of a GUI.
The output of this function will return a two-element array where the first element is the x or column position and the second element is the y or row position of your mouse. Bear in mind that the reference point is with respect to the bottom left corner of your screen. As such, placing your mouse at the bottom left corner of the screen should yield (1,1) while placing your mouse at the top right corner of the screen yields the resolution of your screen.
Now, if you want to continuously get the position of the mouse, consider placing this call in a while loop while pausing for a small amount of time so you don't overload the CPU. Therefore, do something like this:
while condition
loc = get(0, 'PointerLocation');
%// Do something
%...
%...
pause(0.01); %// Pause for 0.01 ms
end

Changing the Value of a Variable While the Code is Running

I'm writing a code that will take the location of the cursor and output a sound signal. But here's the catch: There is already a sin function playing in the background, the mouse click will merely change the x and y values of this sound. Here is what I came up with so far:
clear all
clc
k = 1:1200;
k = k/5000;
x=1;
y=1;
while i<10;
[x,y]=ginput(1)
vib= 0.5*sin(2*pi*y*k);
note=sin(pi*x*k*440);
ses = note+vib;
sound (ses);
end
As you can see my code just plays a sin function but it is discrete. Can someone please help me? I researched handles and callbacks but I just can't get it in my head. The explanations that I find in the net are too complicated for me to understand.
sound (ses); just takes the variable "ses" and plays. While it plays you can not interfere in the data in the way you think. You can observe the change in the next sound() function call.
If you want to continously play a waveform you can look at here:
Matlab: How to get the current mouse position on a click by using callbacks