Basically I have a really complex Matlab GUI, where the user can add different strings by an editextbox (the one you can type in). The problem is that I assigned different functions to different keyboard button pushdowns, for example 's' and 'e' are in use. Every time you try to type in for example 'snake' the functions assigned to 's' and 'e' are executed. Is there any way to determine wheter I clicked in the edittextbox, and it is in use -> like a logical value so i can block the keypressfunctions by checking it.
Within your callback, you can use gco to get the current object. You can then check if this is the graphics handle to your edit box.
fig = figure('WindowKeyPressFcn', #(s,e)keypress());
hedit = uicontrol('Style', 'edit');
function keypress()
if ~isequal(gco, hedit)
disp('Window Key Press')
end
end
If on the other hand you didn't set a global key press callback (using WindowKeyPressFcn) and you instead set the KeyPressFcn of each uicontrol individually, just specifying a different (or no) KeyPressFcn for the edit box would work.
Related
How do I mimic a button click in matlab?
Simply excecuting the callback function doesn't work since within its callback it uses the gcbo command and I cannot alter the excecuting function. I furthermore would not like to shadow gcbo for obvious reasons.
In case it matters I look for a solution which works on matlab R2012a.
you can try calling the java.awt.Robot class, for example.
robot = java.awt.Robot;
pause(2) % wait some time
robot.keyPress (java.awt.event.KeyEvent.VK_ENTER); % press "enter" key
robot.keyRelease (java.awt.event.KeyEvent.VK_ENTER); % release "enter" key
read more about GUI automation using a Robot here...
I'm not sure this will work on Matlab R2012a, but it does on later versions.
gcbo only contain the button handle. If you have (or can retrieve/find) the button handle, just call the function callback with the button handle as first argument and an empty variable as the second argument.
something looking like that:
button_callback( buttonHandle , [] ) ;
The callback will not make any difference between gcbo or the button handle and will function exactly the same.
If you do not have the button handle in the first place, you can try to find it with findobj:
buttonHandle = findobj(gcf,'Style','PushButton','String','The Button Text')
Depending on how the GUI was built/defined, then handle visibility may not be immediately apparent, in which case you can search deeper with findall:
buttonHandle = findall(gcf,'Style','PushButton','String','The Button Text')
or may be the handle was nicely saved in the guidata structure:
handles = guidata(gcf) ;
and search the structure for what may be your button handle.
Note: in the last 3 examples above, make sure the GUI figure which contains the button has the focus before you call gcf, or better yet, replace gcf by the actual figure handle.
I am using a Matlab based program that does some nice plots of some model results. It adds uicontrol slides and buttons in figures. I have no expierence with gui programming in Matlab, and I dont need it, I just wanna add on my matlab script a couple of lines to hide slides and buttons. I can do it manually from the property editor and set "Visible" to "off", but I was reading the Matlab manual and it does not explain how to retrieve an existing uicontrol and change its properties. Any hint? I tried this with no luck:
b = get(gcf,'uicontrol');
set(b,'Style','pushbutton','Visible','off');
Thanks
You simply need to access the element from the handles structure and change its property from there.
For example, if the pushbutton is stored in the handles structure like this:
handles.b %// Whatever name you gave it and see in the Property Inspector
you can make it not visible using the command
set(handles.b,'Visible','off')
and likewise for every other properties.
Little trick: If you need to repeatedly turn on and off elements of your GUI, you can put them in an array of handles for example in the Opening_Fcn of the GUI and change them all at once using this array anywhere in the GUI. This way you won't have to always call them one by one which can be tedious.
Example:
handles.AllButtons = [handles.button1; handles.button2; handles.button3]
this contains the handles to 3 pushbuttons let's say. Now if yu need to turn them all off/on at the same time, you can do:
set(handles.AllButtons,'Visible','off')
instead of doing
set(handles.button1,'Visible','off')
set(handles.button2,'Visible','off')
set(handles.button3,'Visible','off')
From GUIDE, you can check the actual name of any uicontrol component in the Property Inspector. Here is a screenshot from a GUI I made with GUIDE:
In this case, the Tag associated with the button is pushbutton28_ReferenceChannelApply.
Therefore, in order to change any of its properties I would need to use:
set(handles.pushbutton28_ReferenceChannelApply,'Property','value')
EDIT 2
You can look for pushbuttons in your GUI with the findobj command like so:
FindButtons = findobj('Style','push')
which will output an array of handles to those pushbuttons. Then you can query their properties using the get command:
get(FindButtons(1))
I have a GUI with an edit box and a push button on the tool bar (well, more things than that, but those are the only things that matter!) Anyway, I have it so when you press the push button tool a variable is set to equal the string in the edit box. A simple var = get(handles.edit1, 'string'). However, when I go straight from entering the value in the box to clicking the pushbutton (without clicking anywhere else or pressing return), var is assigned the previous value in the edit box. Why is this? Is there any way to make sure the push button tool will pick out the correct value?
The GUI was made using guide, if that matters.
This is happening because the uipushtool callback is executing before the text box has time to 'validate'. There is surely a more elegant way to do that but this trick works:
You can use the waitfor command to tell the uipushtool callback to wait for the editable box to validate its input. Unfortunately is is not exactly enough so we'll have to:
1) pass the focus to a dummy control (I created a dummy pushbutton named pushbutton1 which does nothing. The focus could be send to any other dummy control.
2) now wait for the text box to validate its content.
3) When the text box is done, then retrieve the content the traditional way.
This method requires:
- A dummy control to send the focus to (but you can use a real one too)
- An dummy (or not) callback function for your editable box. (the waitfor instruction will wait for the callback to finish, if there is no callback, it will error
function uipushtool1_ClickedCallback(hObject, eventdata, handles)
uicontrol( handles.pushbutton1 ) ; %// pass the focus to a dummy control
waitfor(handles.edit1,'String'); %// wait for the editable box to validate its content
var = get(handles.edit1, 'string') ; %// now retrieve the editable box content
set( handles.text1 , 'String' , var ) %// this can be deleted, just to verify the method
% --------------------------------------------------------------------
function edit1_Callback(hObject, eventdata, handles)
%// This is the dummy callback function for the editable box
%// Do absolutely nothing here (or do if you want ... your choice)
EDIT
as I feared, my initial solution was too dirty to be robust enough. With 2 (or more) textboxes, I tried a large number of things but without success. I dropped the waitfor, I noticed that in some case, when the uipushtool was pressed, the callback of the editbox would fire but the uipushtool would not execute at all ... so i tried to managed things directly from the editbox callback => from the editbox keypressedFcn send each character as we type to a variable ... but even this editbox callback doesn't know the content of the edit box at the time it is executed ?? (This link provide a very simple example to reproduce that).
So to my great own disappointment, I had to resort to an 'external' solution. (If you accept that it becomes very simple though). The trick is to retrieve the handle of the Java EditBox object. Once we have the handle, getting the "real time" content is just matter of converting the Java string into a Matlab string.
To retrieve the Java object handles, you need the function FindJObj from Matlab central.
Put that anywhere in your matlab path, then the code for your pushbutton become something like :
To make sure there was no interferences between the text boxes and the uipushtools I made 2 separate uipushtools each controlling 1 editbox
function uipushtool1_ClickedCallback(hObject, eventdata, handles)
jEditbox = findjobj(handles.edit1); %// get the handle of the java editbox #1
var = char(jEditbox.getText) ; %// retrieve Java string and convert it to matlab string
disp(['uipushtool1_ClickedCallback running. Textbox1 content = ' var ]) %// debug line, you can delete or comment that
% --------------------------------------------------------------------
function uipushtool2_ClickedCallback(hObject, eventdata, handles)
jEditbox = findjobj(handles.edit2); %// get the handle of the java editbox #2
var = char(jEditbox.getText) ; %// retrieve Java string and convert it to matlab string
disp(['uipushtool2_ClickedCallback running. Textbox2 content = ' var ]) %// debug line, you can delete or comment that
Thanks to Yair Altman for the findjobj function, and many other contributions for Matlab users.
I tried to replicate your problem and created a new GUI using guide with only a pushbutton and an edit field. If I set the button callback to:
function pushbutton1_Callback(hObject, eventdata, handles)
get(handles.edit1,'string')
it always prints the current value of the edit field, no matter if I click somewhere else after entering the value or not. Which version of Matlab are you using? I've tested it using Matlab 2010a.
I'm having a bit of trouble with Matlab's uicontrol handling. Here's the situation:
My (programmatic) GUI contains an editable text field. This field originally contains a numeric value and is supposed to always contain one. In order to ensure that, the 'String' parameter is to be repeatedly checked, converted to numeric, and re-entered into the 'String' property of the uicontrol. This is supposed to happen whenever a user enters a visible character into the text field.
Additionally, the program is supposed to notice at any point whether the current value of said text field differs from the original value, which is stored in memory. If the user closes the figure, a modal dialog opens and asks if he wants to save the change to that value or discard it. If the figure is then reopened (through the rest of the GUI), the value of the text field starts out as either the same it started out as before (if the user discarded the changes) or the changed value defined by the user.
Both of these things fail in some instances because of a strange behaviour: The uicontrol's 'String' property is only updated after the uicontrol loses focus. This is not a problem if the user wants to do other things on that GUI or knows how to handle this. I can also live with my text field only updating to a meaningful numeric value after it loses focus.
The problem is, when I close the figure via Windows' red X button in the top right corner after changing the value of the text field, but without first clicking somewhere else, the 'String' value is never updated, so the CloseRequestFcn doesn't notice the change and simply closes the window. Even pausing for a whopping 100ms and then explicitly calling the text field's Callback from within the CloseRequestFcn doesn't help, it just closes without my dialog. The reverse is also true, if I do change the value, click somewhere else, and then change it back, it will display the dialog unless I first click somewhere else again.
So the question is this: How do I ensure the uicontrol correctly updates/executes its Callback when I click the red X button provided by Windows?
And bonus question: How do I execute this Callback "on the fly" in order to correct any impossible values the user enters as soon as he does (e.g. letters other than e and i)?
Here's the isolated part of my GUI that causes the problem, copy into a file called 'guitest.m' and run in order to test what I'm talking about.
function guitest
changed = false; %// tracks changes to catch closing without saving
startval = 1; %// the starting value
handles.figure = figure('Resize','off','Toolbar','none','Menu',...
'none','Name','Change text field value','CloseRequestFcn',...
#closefig,'Visible','off'); %// not visible until fully created
handles.textfield = uicontrol('Style','edit','Units','normalized',...
'Parent',handles.figure,'String',startval,...
'Position',[.4 .6 .2 .1],'Callback',#changedValue);
handles.button = uicontrol('String','Push me','Units','normalized',...
'Parent',handles.figure,'Position',[.4 .3 .2 .2],'Callback',#dispval);
%// all done, display GUI
set(handles.figure,'Visible','on');
%// callback functions
function closefig(~,~) %// Quit program
pause(0.1);
changedValue(handles.textfield); %// update fields
if changed
disp('Do you really want to close?'); %// save dialog
else
delete(handles.figure); %// this is used as CloseRequestFcn!
end
end
function changedValue(hObject,~)
newval = uint16(str2double(get(hObject,'String')));
changed = (startval ~= newval);
end
function dispval(~,~)
disp('With buttons inside the GUI, it works properly:');
disp(get(handles.textfield,'String'));
disp(changed);
end
end
Will forcing a GUI focus change with uicontrol in your closing function provide the correct behavior? From the documentation:
uicontrol(uich) gives focus to the uicontrol specified by the handle,
uich
For the 'bonus' you're likely going to have to leverage the underlying Java. See the article on editbox data input validation from Undocumented Matlab.
I've a pop-up menu with 5,10,15,20 the contents in that menu. using switch I've created this
val=get(hobject,'value');
switch val
case '5'
n=5;
case '10'
n=10;
case '15'
n=15;
case '20'
n=20;
end
guidata(hObject, handles);
where it represents number of output images. On pressing search button in the same GUI window it calls another function where i need to use this 'n'.
for i = 1:n % Store top n matches...
tempstr = char(resultNames(index(i)));
fprintf(fid, '%s\r', tempstr);
disp(resultNames(index(i)));
disp(sortedValues(i));
disp(' ')
end
How can i pass this 'n' to that code or function?
any proper answer is appreciable.
Well, to start with your switch statement is incorrect and unnecessary. The Value property of a dropdown is not the text contained in the current selection, it is the index of the current selection in its list. To get the string value of the list item currently selected, you would do:
contents = cellstr(get(hObject,'String')) % returns contents as cell array
contents{get(hObject,'Value')} % returns value of selected item from dropdown
That is, of course, assuming hObject is a handle that points to your dropdown box - which it will be only if you're in a callback that was raised by the dropdown itself. Further to that, note that there is no need to convert the string value via a discretised switch statement; you can just use the str2num or str2double functions.
Finally, if you need to access the value of the dropdown from outside one of its own callbacks, you need to use the handles structure that is passed into every callback (or that, in your sample, is returned from guidata). There will be a field in handles with the same name as your dropdown - this will be the handle via which you can access its properties.
The way to pass information around a GUI is to use the the handles structure. If you created your GUI using GUIDE handles should have been created in the opening function. You can modify the opening function to add field and initial values to handles. For example, you could add the following to the opening function:
handles.n = 1; % This initializes handles.n to a default value in case the search button is
% pushed before an item in the menu is selected.
Then include the following in the call back for the menu to update and store the value of n:
handles.n = val; % This is updated every time an item from the menu is selected.
guidata(hObject,handles);
In the call back from the search button you can access the value of n and pass it to your other function like this:
n = handles.n;
myFunction(n);
Your other function will have start with something like this:
function [] = myFunction(n)
followed by the rest of the code you included above. You'll have to make sure myFunction.m is in the Matlab search path (can be set using addpath or by clicking the set path button in Matlab.)