Reputation: 1275
I'm writing a GUI in Matlab, which among other functionalities should allow you to write a text in an edit
-uicontrol
, and then add that text to a list when pressing the enter key.
I am using the KeyPressFcn
method for the edit box to test whether enter is pressed, and my problem is that it does not update the String
value of the edit
uicontrol
, so the string added to the list is not actually the one I just entered, but a previous incarnation of the string in the edit
.
Now I have already searched for solutions to this problem and found a solution, but I would very much prefer a solution strictly contained in Matlab - that is not referring to java.
Is this is possible? And if it is, how?
A minimal working example:
function [fig] = tmpGUI()
fig = figure('MenuBar','none');
handles.fig = fig;
handles.edit = uicontrol(fig,'Style','edit','Units','Normalized','Position',[.05,.75,.9,.2],'Backgroundcolor','white','String','','KeyPressFcn',@edit_KeyPressFcn);
handles.list = uicontrol(fig,'Style','listbox','Units','Normalized','Position',[.05,.05,.9,.65],'Backgroundcolor','white','String','First element in list');
guidata(fig,handles);
uicontrol(handles.edit);
end
function edit_KeyPressFcn(hObject, eventdata)
handles = guidata(hObject);
switch eventdata.Key
case 'return'
str = get(handles.edit,'String');
liste = cellstr(get(handles.list,'String'));
liste{end+1} = str;
set(handles.list,'String',char(liste),'Value',numel(liste));
end
end
Edit: I'm running Matlab R2014a.
Upvotes: 1
Views: 1233
Reputation: 11812
The callback
property of the edit
uicontrol will be triggered when you press enter
, so it would be easier to use this callback instead of the KeyPressFcn
.
Just when you enter the callback, check that the last character pressed was enter
. If yes update your list, if not just do nothing and go on.
This example seems to do what you asked. Let me know if they are other conditions to be checked.
function [fig] = tmpGUI()
fig = figure('MenuBar','none');
handles.fig = fig;
handles.edit = uicontrol(fig,'Style','edit','Units','Normalized','Position',[.05,.75,.9,.2],'Backgroundcolor','white','String','','Callback',@edit_callback);
handles.list = uicontrol(fig,'Style','listbox','Units','Normalized','Position',[.05,.05,.9,.65],'Backgroundcolor','white','String','First element in list');
guidata(fig,handles);
uicontrol(handles.edit);
end
function edit_callback(hObject, evt)
handles = guidata(hObject);
%// just check if the last key pressed was "enter"
%// if yes, update the list
if double(get(gcf,'currentcharacter'))==13
str = get(handles.edit,'String');
liste = cellstr(get(handles.list,'String'));
liste{end+1} = str;
set(handles.list,'String',char(liste),'Value',numel(liste));
end
%// if not, the callback has been trigerred by a click somewhere else
%// this is not a validation condition to update the list so we just
%// do ... nothing
end
Edit: To add more information, the Matlab edit uicontrol are not updated internally before they are validated. The value in the edit will only be validated by (i) The enter
key is pressed, or (ii) the txtbox looses focus (user click somewhere else).
In your initial case you are intercepting the enter
key and executing code, but because you intercepted the enter
key, the textbox didn't validate yet and in its internal memory it still have the old value, so your interception code capture the old value. Remembering a older question I answered relating to these textbox, there is not Matlab way of forcing the textbox to validate its content programmatically without using some java tricks.
So in your case (you want to react to the enter
key), it is possible in pure Matlab thanks to the callback mechanics. If you want to execute some code when reacting to any other key, then you will have to force the textbox validation programmatically which can only be done by calling java methods (actually the link you mentioned in your original post is quite neat, the way I found before was quite more convoluted).
Upvotes: 1
Reputation: 12638
The problem with your solution is that the keypressfunction is called every time you enter a single character. Use a Callback
instead:
function [fig] = tmpGUI()
fig = figure('MenuBar','none');
handles.fig = fig;
handles.edit = uicontrol(fig,'Style','edit','Units','Normalized','Position',[.05,.75,.8,.2],'Backgroundcolor','white','String','', 'Callback',@edit_KeyPressFcn);
handles.list = uicontrol(fig,'Style','listbox','Units','Normalized','Position',[.05,.05,.9,.65],'Backgroundcolor','white','String','First element in list');
guidata(fig,handles);
uicontrol(handles.edit);
end
function edit_KeyPressFcn(hObject, eventdata)
handles = guidata(hObject);
str = get(handles.edit,'String');
% ignore empty strings
if isempty(str)
return;
end
liste = cellstr(get(handles.list,'String'));
liste{end+1} = str;
set(handles.list,'String',char(liste),'Value',numel(liste));
end
Upvotes: 1