I have a function which runs when a button is clicked and that function will call another function to perform plotting, which is an animation composed by a series of loops. Problem is, after the program is run, it cannot be stopped unless pressing Ctrl+C which then cause the whole .exe to fail and require reopening it.
I want to make a Reset button, so to stop the loop from running, but how to pass a new variable from the interrupt to the existing function which is two level above the stack?
Thank You
edit # 22:13 27/3/2011 (UKT)
a more clearer of what I am trying to do:
function push_calculate_Callback(hObject, eventdata, handles)
(List of parameters read in the GUI)
fmain(list of paramters required to pass to the function, fmain)
that's first part of the code which linked directly to the GUI, the fmain looks like:
function fmain(List of parameters)
(List of calculations...)
fplotting(list of paramters for plotting)
in which the fplotting is where the animation comes out from, inside the fplotting:
function fplotting(list of parameters)
for i = 1:(end)
(do the animation plot)
end
here is the loop where I want to stop when I press the reset button. coz if anyone press Ctrl+C when the animation is undergoing (looping), it will give an error and the exe file will crash and requires reopening it. So what I want it be able to stop it when someone press the reset button.
If I use persistent, the new value, after I press the reset button, it will not pass into the existing loop and break the loop... looks like I am looking for a way to update the parameter after I have change it outside the function
Thanks
Use exit or quit to exit the program
To stop the loop from running, you can use break or return from a function..
Your best bet might be to use a PERSISTENT variable whose state you check at each iteration of the loop in function 2, and whose value you modify in the "reset"-callback.
reset callback
function reset_callback(hObj,eventdata,handles)
%# "activate" persistent variable
persistent breakThis
%# set it to 1
breakThis = true;
function with the loop
function functionWithTheLoop(someInput)
...
%# "activate persistent variable
persistent breakThis
...
%# start loop
for iter = 1:numOfIterations
%# check whether you need to break out of the loop
if breakThis
%# reset the function value
breakThis = false;
break;
end
...
end
You can use application data information, i.e. setappdata and getappdata:
% animation loop function
function loop(hFig)
setappdata(hFig, 'run', true); % here or somewhere else...
while(getappdata(hFig, 'run'))
plot(....);
end
end
% GUI stop-loop btn callback
function stop(hFig)
setappdata(hFig, 'run', false);
end
I guess that would work.
Related
can anybody help me achieving this with luakit?
I'm running raspbian on rpi3 and for my application I need one luakit window constantly running in full screen mode and triggered by a bash script, I want another browser window open from time to time in a certain size e.g. 800x600. Would be nice if I could also determine the position of the second window.
I was able to launch luakit in full screen or specific size by overwriting the window function in my rc.lua config. I then launch luakit with either the one or the other rc.lua file (-c parameter) . However if one instance of luakit is already running, the second luakit window uses the config of the first one that is already running.
Can I somehow trigger the window size of a new luakit window from bash script?
Thanks for any help.
I found a solution to my problem: instead of giving the browser instance the window size, I let itself decide whether or not to launch in fullscreen by checking the URL.
in my rc.lua I added require "userconf" and created a file userconf.lua in which I have overwritten the function window.new like so:
function window.new(uris)
local w = window.build()
-- Set window metatable
setmetatable(w, {
__index = function (_, k)
-- Check widget structure first
local v = rawget(w, k)
if v then return v end
-- Call each window index function
for _, index in ipairs(window.indexes) do
v = index(w, k)
if v then return v end
end
end,
})
-- Setup window widget for signals
lousy.signal.setup(w)
-- Call window init functions
for _, func in pairs(window.init_funcs) do
func(w)
end
-- Call window init functions
for _, func in pairs(window.init_funcs) do
func(w)
end
-- Populate notebook with tabs
for _, uri in ipairs(uris or {}) do
w:new_tab(w:search_open(uri), false)
end
-- Make sure something is loaded
if w.tabs:count() == 0 then
w:new_tab(w:search_open(globals.homepage), false)
end
-- Set initial mode
w:set_mode()
-- Show window
w.win:show()
-- we check the url, if it points to the URL i want to see in fullscreen we launch in fullscreen otherwise we leave the default.
-- open myapplication.html in fullscreen, every other window in normal mode
w.win.fullscreen = false
for _, uri in ipairs(uris or {}) do
if string.match(uri, "myapplication.html") then
print "got myapplication.html"
w.win.fullscreen = true
end
end
return w
end
It's probably not a 100% solution, but for me it's ok
I have this sprite: spr_meteoriteLv3, which has two sub-images with index image_index 0 and 1 respectively.
I have these objects: obj_meteoriteLv3, obj_tempMeteoriteLv3, and obj_score. Object obj_meteoriteLv3 spawns from above with random position, random amount, and random sub-image. Object obj_tempMeteoriteLv3 makes obj_meteoriteLv3s spawn. When player clicks on a meteorite, the program checks the value of image_index for that object.
obj_meteoriteLv3 has these events:
Create Event: change sprite_index into spr_meteoriteLv3, and start moving downwards.
Left-pressed Mouse Event: destroy the self instance, and check image_index: if image_index == 0 then score += 5; else score -= 5).
obj_tempMeteoriteLv3 has these events:
Create Event: set Alarm 0 to 3600, set variable exist to 1, and set variable add to 1.
Alarm 0: set variable add to 0, and destroy the obj_meteoriteLv3 instance.
Alarm 1: set variable exist to 1.
Step Event: if (exist == 1) then, if (add == 1) then create instance of obj_meteoriteLv3, set variable exist to 0, and set Alarm 1 to 10.
obj_score has these events:
Create Event: set score to 0.
Draw Event: draw the value of score.
The problem is, no matter which sub-image the meteorite image_index has when clicked, the score will always be incremented by 5 points. It's like the else condition isn't working. How can I fix this? Please explain your answer. Thanks.
I add some images for better understanding. Link 1. Link 2
In obj_meteoriteLv3 it's being destroyed before it can execute the rest of the code blocks. Move "Destroy Instance" to the bottom.
In obj_tempMeteoriteLv3 both variables "add" and "exist" are not necessary, instead have-
Create Event-
alarm[0] = 3600
alarm[1] = 10
Alarm[0] Event-
destroy_instance
Alarm[1] Event
Create_instance of obj_meteoriteLv3
alarm[1] = 10
Potentially, when you click, every single meteorite is triggered.
On the left click event of the meteorite, you did not check if the cursor was on the sprite. You have to use the position_meeting function, to which you pass the mouse position and the instance to click.
it would look like :
if (position_meeting(mouse_x, mouse_y, id))
{
//your destroy code
}
Moreover, when the instance_destroy(); line is read, the following code is ignored and the program jumps to the destroy_event. William explained it well and suggested to change the order of the lines of code, but you can also change the score in the destroy event directly.
I would like to add that checking for clicks in every instance of the meteorites is not optimal for performances.
My recommendation would be to use a single object to check for clicks (your player or your meteorite spawner, for example), in which you would check for clicks, and if a meteorite is touched, you would trigger it's destroy event. And in this event, you would increment the score and check the sprite.
Your click event would look like :
with (instance_position(mouse_x, mouse_y, obj_meteoriteLv3))
{
instance_destroy();
}
and in the meteorite destroy event, you would check the image_index and change the score accordingly.
EDIT : why the score doesn't change
I believe you didn't declare the score as a global variable, but as an instance variable. So when you write "score = ..." in an other object, it creates a new score variable, unrelated to the precedent.
You have 2 options :
1 - Declare the score a global variable in the create event of obj_score:
globalvar score;
score = //your starting score
Be aware that a global variable can't be set on it's initialisation line.
2 - Change the score through the score object :
whenever the score has to change :
obj_score.score = ...
I am trying to display and update a gui element (text string). Can someone tell me what I am doing wrong here? The initial text is never replaced by the updating text in the loop.
kills=0
#n::
Gui,Add,Text,vStatus, starting the killing
Gui,Show,w250 h375
Loop
{
GuiControl,,vStatus, killed %kills% Glorks!
kills+=1
Sleep,3000
}
return
Here is working code:
kills=0
#n::
Gui,Add,Text,vStatus, starting the killing
Gui,Show,w250 h375, Glorks counter
Loop
{
IfWinNotExist, Glorks counter
{
Gui, Destroy
return
}
GuiControl,,Status, killed %kills% Glorks!
kills+=1
Sleep,3000
}
return
Your mistakes:
You should use Status instead of vStatus in GuiControl command.
When you close GUI, you are not stopping loop, so IfWinNotExist detect if window exists and if not exists it will destroy all gui variables and exit from loop. So you can again press Win+n and start gui again.
Note:
If you want to start count kills every time from 0 when gui is started then move kills=0 to right after #n::
I have GUI in Matlab that I have made using the Programmatic approach. It has 6 sliders and I want to be able to move one of them and have the others update as if i clicked them again but to stay in the same place. I am guessing I will need to use the set() function. Is there some function to do this in matlab already? I have been looking around. Any suggestions or something to point me in the right direction?
If you are using guide, you can access the other sliders from the handles variable that is available in each callback.
Set the Value property for them.
function Slider1_CallBack(hObj,evt,handles)
set(handles.Slider1,'Value',10);
set(handles.Slider2,'Value',10);
% etc..
end
In case you are using it programmaticaly, you can store the handles manually.
function main
handles.Figure1 = figure(..);
handles.Slider1 = uicontrol(...);
handles.Slider2 = uicontrol(...);
guidata(handles.Figure1,handles);
end
And your slider callback should be:
function Slider1_CallBack(hObj,evt)
handles = guidata(hObj);
set(handles.Slider1,'Value',10);
set(handles.Slider2,'Value',10);
% etc..
end
Edit A good practice in writing UI is separating the GUI logic from the actual data. You always change the data, and call updateGUI routine.
Therefore, you can write your program like this:
function main
handles.gui.Figure1 = figure(..);
handles.gui.Slider1 = uicontrol(...);
handles.gui.Slider2 = uicontrol(...);
handles.data.x = 1;
guidata(handles.Figure1,handles);
end
function UpdateGui(handles)
%Based on the data, update the GUI
set(handles.Slider1,'Value',handles.data.x);
set(handles.Slider2,'Value',handles.data.x+1);
end
And the callback should look like:
function Slider1_CallBack(hObj,evt)
handles = guidata(hObj);
handles.data.x = handles.data.x + 1;
UpdateGui(handles);
guidata(hObj,handles);
% etc..
end
The matlab function getline (image processing toolbox) returns the position of a polyline (which has previously been defined with the cursor) either on a double-click or on pressing the return key or spacebar.
Due to my butter-fingers and accidentally double-clicking I want to remove the ability to end on a double-click.
What part do I need to change, or what functions should I be looking out for, I can't find out how a double click is even defined in matlab.
Cheers!
MATLAB associates "callback" functions with graphics objects, which define what to do when the mouse is clicked, keys are pressed, etc.. In getline(), the section to look at is the NextButtonDown() subfunction. This is the callback that is associated with subsequent mouse presses after the first mouse press to initiate the line. The key is that is checks the SelectionType figure property, which will be open for a double click. When that is the case, it closes the figure. So, to disable that functionality, just remove the extra case and checking logic. Here is the diff for my r2009b version:
306,310d305
< selectionType = get(GETLINE_FIG, 'SelectionType');
< if (~strcmp(selectionType, 'open'))
< % We don't want to add a point on the second click
< % of a double-click
<
322,328d316
<
< end
<
< if (~strcmp(get(GETLINE_FIG, 'SelectionType'), 'normal'))
< % We're done!
< set(GETLINE_H1, 'UserData', 'Completed');
< end
The answer provided by #JohnColby solves your problem by editing the GETLINE.m function file. Basically you comment out every line that check if a double-click was performed. This information is obtained by querying the 'SelectionType' figure property.
Alternatively, if you are like me and you hate making changes to built-in functions, then consider the following solution that doesn't involve changing any existing functions. Here is an example of how we use it:
h = addlistener(handle(gcf), 'WindowButtonDownFcn', 'PostSet', #changedWBDFcn);
[x,y] = getline();
delete(h)
plot(x,y, 'Color','r')
The idea is to create an event listener that gets triggered when the 'WindowButtonDownFcn' figure property changes. We use it to insert a function that gets called just before the previously set callback function (actually we replace the callback with our own function that calls the old one at the end).
This allows us to insert a section that checks if the call was triggered by a double-click, and simply skip such event.
This had to be done twice, because GETLINE first calls FirstButtonDown on first click, which sets NextButtonDown to be called on subsequent clicks, thus the use of the flag variable to differentiate between the two cases.
The code for the above event listener function:
function changedWBDFcn(src,ev,flag)
hFig = ev.AffectedObject; %# figure handle
currFcn = ev.NewValue; %# current callback function
delete(src); %# delete event listener
if nargin < 3, flag = false; end %# determine flag
%# hijack WindowButtonDownFcn function
set(hFig, 'WindowButtonDownFcn',{#wbdFcn,currFcn,flag})
%# callback function
function wbdFcn(o,e,currFcn,flag)
%# skip anything but single-clicks
if ~strcmpi(get(hFig,'SelectionType'),'normal')
return
end
%# evaluate previous callback function
hgfeval(currFcn) %# getline('FirstButtonDown'),getline('NextButtonDown')
%# repeat process after first click
if flag
addlistener(handle(hFig), 'WindowButtonDownFcn', ...
'PostSet', {#changedWBDFcn,true});
end
end
end