How to intercept key strokes in Matlab while GUI is running - matlab

Do you know how to read keyboard strokes into Matlab while a Matlab gui is running? (I.e., without using the "input" function which sends a prompt to the command window and needs you to press return).
We would like to avoid using a mex function if possible.

You would first have to declare your figure by handle:
fig = figure;
then you can set properties (in quotes below) to activate functions that you've written to respond to user interactions (with the # signs):
set(fig,'KeyPressFcn',#keyDownListener)
set(fig, 'KeyReleaseFcn', #keyUpListener);
set(fig,'WindowButtonDownFcn', #mouseDownListener);
set(fig,'WindowButtonUpFcn', #mouseUpListener);
set(fig,'WindowButtonMotionFcn', #mouseMoveListener);
The above example is from shooter03.m a MATLAB space shooter, an excellent source (from the matlab file exchange) for many aspects of user object interaction in MATLAB:
http://www.mathworks.com/matlabcentral/fileexchange/31330-daves-matlab-shooter/content/shooter03/shooter03.m

If your GUI is based on a figure, you can use the figure property keypressfcn to define a callback function that handles keyboard inputs. See the matlab help for further descriptions: http://www.mathworks.de/help/techdoc/ref/figure_props.html#KeyPressFcn

Try:
hf = figure;
get(hf,'CurrentCharacter')

Related

Close uialert figure by button click

Based on a MATLAB example, I added a close command in order to close the uifigure after pressing the OK button. However, in its current state the figure is closed automatically, rather than on the button click. How can I alter the below to have the figure close on click?
Code:
fig = uifigure;
message = {'Fire hazard!','Consider reducing temperature.'};
uialert(fig,message,'Warning',...
'Icon','warning');
close(fig)
You should use a callback in uialert:
fig = uifigure;
message = {'Fire hazard!','Consider reducing temperature.'};
uialert(fig, message, 'Warning', 'Icon', 'warning', ...
'CloseFcn', #(~, ~)close(fig)); % This will be executed after Ok is pressed
The syntax # is the Matlab way to define an anonymous function (Matlab calls these function handles, other languages usually call these lambdas). It allows passing functions as parameters to other functions. If your anonymous function needs to receive parameters, the syntax #(p1, p2, p3) can be used.
In the case of callbacks for uifigures, the callbacks always expect two parameters: fig and event. fig is the figure where the event happened, event is a structure describing the event. In the case above, since all you want to do is close the figure (and you already know which figure you want to close), you can ignore both parameters. The syntax in Matlab to tell that you are receiving a parameter that you purposefully are ignoring is by using a tilde (~) in the position of the parameter. This can be used anywhere actually, including in the definition of normal functions or when unpacking the return value. For example:
[U,~,V] = svd(A)
tells that you are not interested in the singular values of your SVD, only in left and right singular vectors.
You can read more about function handles in the Matlab documentation.

Programmatically open a Simulink MATLAB function block's code

Can I open a local Simulink MATLAB function block's code in the MATLAB editor via some command?
For example, let us say I have a Simulink model named mainModel.slx.
In it, there is a MATLAB function block named localFunction.
This is not defined in a .m-file.
I would be able to edit the function which path is mainModel/localFunction, without having to open the simulink window and double click on the function block. Is this possible?
I have of course already tried open mainModel/localFunction and edit mainModel/localFunction. I have access to the handle for its StateFlow.EMChart object.
EDIT: Minimal, (hopefully) Complete and Verifiable Example
My minimal Simulink model is shown in the picture below. Code is present below it. For readability, I have not addressed bugs or glitches. It is not for general usage.
The function code for the MATLAB function block localFunction is
function y = fcn(u)
y = 'findThis'; % I want to end up here, in the MATLAB editor!
end
I am using the following code to load the model, search through all MATLAB function blocks and find the ones containing the string 'findThis'. The MATLAB function block named 'localFunction' should then be found. Again, ignore the bugs. The code is saved in a script called tmpScript.m.
% User set
model = 'mainModel';
expression = 'findThis';
blockType = 'Stateflow.EMChart'; % MATLAB function block, right?
% Load model
load_system(model)
% Find all MATLAB function block handles
blockHandles = find(slroot, '-isa', blockType);
% Find first block containing the defined expression
for iHandle = 1:numel(blockHandles)
tmpFind = strfind(blockHandles(iHandle).Script, expression);
if ~isempty(tmpFind)
break
end
end
foundBlockPath = blockHandles(iHandle ).Path; % Function block path
foundCharIdx = tmpFind; % Character index
% Print results in command window
fprintf('Function path: %s\n', foundBlockPath)
fprintf('Character index: %d\n', foundCharIdx)
In this example, the path should be mainModel/localFunction and the character index 29 (Note the three leading white spaces on the function's second line, and that the line break '\n' is worth one characters). The command window shows
>> tmpScript
Function path: mainModel/localFunction
Character index: 29
>>
I can thus load models and search through their MATLAB function blocks for specific strings. When I have found this function, I would like to be able to open it in the matlab editor. What is called when I double click on the block in the Simulink window?
These do NOT work
open(foundBlockPath)
edit(foundBlockPath)
blockHandles(iHandle).openEditor
I cannot change the Simulink model itself. I do not want to change the function script. I just want to be able to open it in the MATLAB editor.
You can open the code in the Editor using,
view(blockHandles(iHandle))
You could change the Matlab function block to an Interpreted Matlab function block.
This does have the limitation that it only can have one input and one output (which can be vectors), so depending on your problem, you might have to mux/demux some data.
Alternatively you can change to an S-function, which gives more flexibility, but might be a bit more complex to setup.

Pass data between gui's matlab

I have two gui's one is main gui and other is sub gui. In opening function of main gui i used open('subgui.fig'); to open sub gui. Main consists of 5 edit box and one pushbutton. After pressing pushbutton the data in those 5 edit boxes should be passed to sub gui and main gui should close. Please any one help me to do this.
Let us take a simple case of one editbox and one pusbutton in main GUI and one editbox in sub GUI that will get value from the editbox in main GUI. One can easily extend this to as many editboxes as needed. The basic medium of data storage and retrieval would be a global structure data1.
For the sake of understanding the codes, let us take the following assumptions -
Main GUI is named as main_gui.m and thus has an associated
main_gui.fig from GUIDE. Main GUI's figure has the tag main_gui_figure.
Sub GUI is named as sub_gui.m and thus has an associated sub_gui.fig
from GUIDE.
Edits to be made in main_gui.m
Inside editbox's callback, add this -
global data1;
%%// Field in data1 to store the string in editbox from main GUI
data1.main_gui.edit1val = get(hObject,'String');
Inside the pushbutton's callback, add this right before it's return -
global data1;
sub_gui;
delete(handles.main_gui_figure);
Edits to be made in sub_gui.m
Inside sub_gui_OpeningFcn, add this -
global data1;
set(handles.edit1,'String',data1.main_gui.edit1val);%%// Tag of editbox in sub-gui is edit1
Hope this works out for you! Let us know!
There are probably more than one ways to achieve this. But one of the approaches is to define a function that takes two input arguments: 1) handles to the destination figure and 2) whatever data from the source figure.
The following psuedo code doesn't necessarily run in MATLAB, but it gives the basic idea:
function takeAction(uihdls, data)
set(0, 'CurrentFigure', uihdls.fig); % uihdls.fig is the handle of the destination figure.
set(gcf, 'CurrentAxes', uihdls.aexs1); % axes1 is inside fig
plot(data.x, data.y); % Do some plotting
set(uihdls.editBox, 'String', data.string); % Modify some property of a control inside fig.
key_Callback(uihdls.fig, data.keyData); % Call a callback function of the destination figure
return
This function can be called by the source figure whenever it is ready to do so.
A bit more work - but I think it's worth it.
I usually use the MVC pattern for that. Practically it means to write a controller object that will pass the messages through to the required fields.

Use Matlab PDE toolbox from command line

I would like to solve a PDE with Matlab PDE toolbox using only the command window of the system. I can create the problem and run the solver, but the PDE toolbox window pops up occaisionally and asks questions (e.g., "Do you want to save unsaved document?").
How can I avoid these popups or how can I use the PDE toolbox without opening its window?
I am using the following code. The window is pops up when I call the pdeinit function on the first line.
[pde_fig,ax]=pdeinit;
set(ax,'XLim',[-0.1 0.2]);
set(ax,'YLim',[-0.1 0.2]);
set(ax,'XTickMode','auto');
set(ax,'YTickMode','auto');
% Geometry description:
pderect([0 0.05 0.05 0],'R1');
pderect([0 0.1 0 0.1],'R2');
set(findobj(get(pde_fig,'Children'),'Tag','PDEEval'),'String','R2-R1');
...
The help for pdeinit is short: "Start PDETOOL from scripts." pdetool, like most *tool M-files from The MathWorks, is a GUI and the help/documentaion for it indicates as much.
I'm confused because, not only does pdeinit open a figure window, but you're using it to return handles to the figure and axis of that figure. Your code then proceeds to manipulate those handles. You can't get those handles without first creating and opening a figure. Is the issue that you just want a regular figure window instead? If so, then you can replace [pde_fig,ax]=pdeinit; with:
pde_fig = figure;
ax = gca;
You can look at the code for pdeinit: type edit pdeinit in your command window. You'll see that all it does is open pdetool (unless it's already open) and return handles to the resultant figure and axis.
Additionally, pderect will open pdetool on its own. You're using a bunch of functions that are all tied to the PDE app. Many of the tutorials and examples on The MathWorks's site use this. You might check out this article on how to solve PDEs programmatically. The examples might also be helpful.

How do I tell my MATLAB GUI that I want to plot on it using an external .m file?

I have a GUI(made using GUIDE) in which there is an axes on which I can draw. When I saved the gui, i have a .fig file and a .m file (whose names are start_gui.m and start_gui.fig). Now, I am trying to plot on these axes using an external M file, to which I have passed the GUI handles. This is as follows:
function cube_rotate(angle1,angle2,handles)
gcf=start_gui.fig; %this is the name of the gui.fig file in GUIDE
set(gcf,'CurrentAxes',handles.cube_axes)%this allows us to plot on the GUI
%plot something
end
handles.cube_axes is the name of the handle in the GUI created using guide. Inspite of passing the handles, it won't allow me to plot in the gui. It throws up an error saying:
??? Undefined variable "start_gui" or class "start_gui.fig".
start_gui.fig is the name of the GUI figure that was generated in GUIDE. How do i make it plot in the axes in start_gui.fig?
Thanks for all the help!
You've made a few errors. The first is referring to a file name without single quotes to denote a string. The second is trying to open an existing figure by assigning it as a variable named gcf. This will just give you a variable gcf which contains the string 'start_gui.fig'.
Instead, open the figure with this command:
fH = hgload('start_gui.fig');
% Then find/assign the axes handle (assuming you only have one axes in the figure):
aH = findobj(fH,'Type','axes');
% And finally plot to the axes:
plot(aH,0:.1:2*pi,sin(0:.1:2*pi));
On a secondary note, is there a reason you're not using the M-file generated by MATLAB to carry out this functionality? By using the auto-generated M-file, you'll be able to access the handles structure rather than using findobj.
The error you're getting is because of your second line: gcf=start_gui.fig;
It's looking for a variable named start_gui, which you don't have. (start_gui.fig is a filename, not a variable.)
To solve your plotting problem, take a look at this Mathworks support article.