writecell writes empty value for the first row in a for-loop

4 vues (au cours des 30 derniers jours)
Shae Morgan
Shae Morgan le 20 Sep 2023
Modifié(e) : dpb le 21 Sep 2023
I have this .mlapp from App Designer, and I'm using it to loop through some audiofiles and then record what the listener heard. The listener types what they hear in the sentence into an edit text input (app.response), and then presses "Enter" to record the answer and advance to the next stimulus. When I look at the excel file at the end, it shows the recorded response, but it's all offset by 1 row and the last response is never recorded. It's like somehow the waitfor isn't working right, and it's saving the response before it collects the information from the edit text.
I feel like this should be really straighforward, but it's taken me hours now to figure out - so I've come to the community. What am I missing? I feel like it's something to do with the "waitfor" and setting the current character, while changing the current character by typing out a response? I can't get it right though.
function BeginButtonPushed(app, event)
%set default character on keyboard to 0 (so we can advance by
%pressing Enter later)
app.UIFigure.CurrentCharacter = char(0);
%access stimuli
task = 'Type_babble_1'; %Set task name
stim_dir=[cd '\stimuli']; %set directory for stimuli
FileList = dir(fullfile(stim_dir,'*.wav')); %create list of stimuli
%loop that controls stimulus playback
for i=1:length(FileList)
app.Counter.Value = length(FileList)+1-i; %adding a number for the counter
%load the signal
signalpath = [stim_dir '\' FileList(play_order(i)).name];
[fnames,fs]=audioread(signalpath);
%present stimulus
duration = length(fnames)/fs;
sound(fnames,fs);
pause(duration)
%wait to collect response
app.UIFigure.CurrentCharacter = char(0);
waitfor(app.UIFigure,'CurrentCharacter', char(13))
app.UIFigure.CurrentCharacter = char(0);
%collect trial information and write it to the file.
sentence_code=FileList(play_order(i)).name;
output = [cellstr(app.ID.Value) cellstr(task) cellstr(sentence_code) cellstr(app.response.Value)];
disp(output)
writecell(output,[app.ID.Value '-' task '-data.xlsx'],"Sheet",1,'WriteMode','append');
end
fclose('all');
msgbox('You''re done!')
end
  14 commentaires
Shae Morgan
Shae Morgan le 20 Sep 2023
Here's the zip thanks for the suggestion. I'm worried I'm not experienced enough to reduce the code by much more without breaking it as you suggested. I will try it and will post if I'm successful.
Thank you for the helpful suggestions.

Connectez-vous pour commenter.

Réponse acceptée

Voss
Voss le 20 Sep 2023
@Shae Morgan: I think @dpb is exactly right with his comments - the root cause of the problem is that the edit box Value is not updated yet when you try to use it to write to file. In my tests, drawnow doesn't seem to fix it, and I found that presetting a non-empty string in the edit box does indeed cause the string to be written to file on the first iteration (as dpb predicted and contrary to what you observed, strangely).
I also agree with dpb that using the ValueChangedFcn of the edit box is the way to go, rather than relying on the uifigure's CurrentCharacter. The attached app has the structure necessary to do the job as you originally intended/imagined. In my tests, it correctly writes all the information to file.
(Note that I removed the masking/level logic because it wasn't running with the wav files of random data I created for testing, and because that stuff is not relevant to the problem at hand, so you'll have to reintroduce that logic in the right place - in the play_current_sound function, I imagine.)
  9 commentaires
dpb
dpb le 21 Sep 2023
Modifié(e) : dpb le 21 Sep 2023
"... I'm ... used to javascript/html where if the text exists, then it's rendered and something you can capture."
Capturing from the screen buffer would be something different; you were/are returning the internal state of the control .Value property, that's a different thing than the display buffer. As the ValueChanging callback function describes, there's a background ValueChangingData object that is the buffer holding the user text as being type that you can access/query from the ValueChanging callback function that will look like what's on the screen...but the actual control .Value property itself isn't updated until the user either hits <return> or switches focus away from the control, and then only when the ValueChanged callback executes which is, as noted above, after the figure keystroke callback has completed.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Migrate GUIDE Apps dans Help Center et File Exchange

Produits


Version

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by