MATLAB: How do I Assign Push Buttons to Values so that I can Track the Data??

14 views (last 30 days)
Hello,
For clarity, I will explain my project:
I need to create a UI where participants can listen to two versions of a speech shaped noise (2 .wav files) and choose which one they think sounds the best. I then need to collect the data on the user responses.
My progress:
I used GUIDE to create an interface with two push buttons that is presented AFTER listening to the sounds. Here is the code for one of the .m files I'm using:
function varargout = simple_gui(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @simple_gui_OpeningFcn, ...
'gui_OutputFcn', @simple_gui_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
function simple_gui_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
function varargout = simple_gui_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
handles.output = hObject;
function pushbutton1_Callback(hObject, eventdata, handles)
function pushbutton3_Callback(hObject, eventdata, handles)
Where I need help:
I am having trouble assigning both push buttons as different values (like 1 and 2) and have the data represented in a clean way. If I could plot them on a bar graph, that would be an added plus.
Thanks!

Accepted Answer

Joe
Joe on 24 Jul 2015
Edited: Joe on 24 Jul 2015
If you are going to be programming a GUI, I strongly recommend that you acquaint yourself with the basics of MATLAB's object-oriented capabilities. OOP is not the end-all-be-all of programming as most CS people would have us believe, but is definitely the way to go when making a GUI. Here is a minimal example that does what you need; it stores the number of button presses as an object property which can be accessed from any other method in the class. You can run this as a standalone .m file without needing a wrapper script or anything. (Sorry that I tend to write lines a bit longer than desirable...)
classdef simple_gui < handle % Make sure to inherit from handle class
properties
f; % Holds figure
width = 400; % Panel width
height = 500; % Panel height
mainPanel; % Main GUI panel
playSoundButton;
response1Button;
response2Button;
nResponse1 = 0; % Track response 1
nResponse2 = 0; % Track response 2
end
methods
function obj = simple_gui
% Create figure, hide during creation
obj.f = figure('Visible', 'off', 'Position', [400, 500, obj.width, obj.height], ...
'resize', 'off', 'NumberTitle', 'off');
% Create Main Panel
k = obj.width/obj.height;
obj.mainPanel = uipanel('FontSize',12, 'units', 'normalized', 'fontweight', 'bold', ...
'Position',[0.025*[1, k], ...
[(1 - 2*0.025), (1 - 2*k*0.025)]]);
% Create Buttons
buttonWidth = 0.25; buttonHeight = 0.15;
obj.playSoundButton = uicontrol('style', 'pushbutton', 'Parent', obj.mainPanel, ...
'Units', 'normalized', 'Position', [0.1, 0.5, buttonWidth, buttonHeight], ...
'String', 'Play Sound', 'Callback', @obj.playSound);
obj.response2Button = uicontrol('style', 'pushbutton', 'Parent', obj.mainPanel, ...
'Units', 'normalized', 'Position', [0.4, 0.5, buttonWidth, buttonHeight], ...
'String', 'Response 1', 'Callback', @obj.response1);
obj.response2Button = uicontrol('style', 'pushbutton', 'Parent', obj.mainPanel, ...
'Units', 'normalized', 'Position', [0.7, 0.5, buttonWidth, buttonHeight], ...
'String', 'Response 2', 'Callback', @obj.response2);
% Assign a name to appear in the window title.
set(obj.f, 'Name', 'Sound Survey Tool');
% Move the window to the center of the screen.
movegui(obj.f,'center')
% Set GUI as visible
set(obj.f, 'Visible', 'on');
end
%%%CALLBACK FUNCTIONS
function playSound(obj, eventData, handles) %#ok eventData and handles are unused
fprintf('Sound played\n');
% Code to play sound goes here
end
function response1(obj, ~, ~)
obj.nResponse1 = obj.nResponse1 + 1;
fprintf('Response 1 selected; response 1 count = %i\n', obj.nResponse1);
end
function response2(obj, ~, ~)
obj.nResponse2 = obj.nResponse2 + 1;
fprintf('Response 2 selected; response 2 count = %i\n', obj.nResponse2);
end
end
end
In my opinion, this is much more readable than the functional style GUIDE uses, and it is much, much easier to store data for access later. I've been writing GUI's with OOP for about a year now and forgotten most of what I knew about the function-based approach, so I'm afraid I can't help you if you want to go with that route.
  1 Comment
Emeka Anekwe
Emeka Anekwe on 30 Jul 2015
Thank you so much. I found the manipulative power of hand-crafting the gui much more desirable, so I agree with you entirely. There's too much going on "under the hood" when using GUIDE, and that annoys me a lot.
I am now trying to see if I can graph the data or simply put it in a table when the user presses one of the buttons. The tricky thing as is is that I need to have this done over 100 sound files! So there must be a way to tell MATLAB to look in a specified folder and replace the currently played sound files with un-played ones. I found some leads on how to do that, so hopefully I can get it.

Sign in to comment.

More Answers (1)

Emeka Anekwe
Emeka Anekwe on 14 Aug 2015
Hi Joe,
While I successfully made a solid GUI using OOP rather than the messy GUIDE feature, I am still haveing trouble programming MATLAB to take the output values of the puhsbuttons and placing them in a simple table (like a 3x3 array). So suppose I have pushbutton1 output a '1' and pushbutton2 output a '2', I want to put the values in a table that looks something like this:
User 1 User 2 . . . User n
Sound 1 1 2 2
Sound 2 2 1 2
.
.
.
Sound n 2 2 1
How can I got about getting started on that?
  1 Comment
Joe
Joe on 16 Aug 2015
So is the main issue the "flow control" of the GUI, i.e. how to tell when you've moved from one sound to the next, and one user to the next? I'm going to assume that's the case, correct me otherwise.
- To handle sound advancement, your "play sound" button can track an index of which sound to play; it can be advanced each time the button is pressed. This will also index the rows of your results matrix. Every time the GUI moves to the next user, reset the sound index.
- I would add a "next user" button the GUI as well -- you could have the "play sound" button perform that function if desired -- and add a corresponding "user index" as an object property to keep track of the column index on users.
This might also be a good time to make use of a structure array , especially if there are other user data you want to keep track of.
Finally, always overestimate the ability of your users to screw up your GUI, especially one that relies on careful flow control. I'd recommend you make heavy use of the "enable" feature to turn off buttons as necessary - for example, disable the "voting" buttons until a sound has finished playing. The pre-2014b call for that is
set(button, 'enable', 'off');
or
set(button, 'enable', 'on');
I think this syntax works in new versions as well but there is also a more OOP-like interface that will do the same thing; I haven't gotten familiar with it.
Hope this helps.

Sign in to comment.

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!