I have a problem in my GUI. In my opening function I defined an img_new variable to be an image I have stored.
My GUI has two axes, one displays the original image and the other one the filtered one. I have 4 filters in a panel with the 4 radiobuttons. And in the end of each one's code there's the img_new = the image created through the radiobutton filter.
Here's some code:
% --- Executes when selected object is changed in uipanel3.
function uipanel3_SelectionChangeFcn(hObject, eventdata, handles)
handles.count = handles.count + 1;
% Change filter orientation depending on which radiobutton is chosen
switch get(eventdata.NewValue,'Tag')
case 'hte'
h_te = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(h_te);
handles.img_new = h_te;
case 'hc'
h_c = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(h_c);
handles.img_new = h_c;
case 'vlr'
v_lr = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(v_lr);
handles.img_new = v_lr;
case 'vc'
v_c = zeros(handles.rows, handles.colums);
# code of the filter...
axes(handles.axes2);
imshow(v_c);
handles.img_new = v_c;
end
guidata(hObject, handles)
and here's the imwrite function:
% --------------------------------------------------------------------
function save_img_ClickedCallback(hObject, ~, handles)
% writing the new image
imwrite(handles.img_new, strcat('filtered_image_', num2str(handles.count), '.png'));
guidata(hObject, handles)
Here's the function to get the image to axes1 the original) and filter it to axes2 (filtered)
% --- Executes on button press in img2.
function img2_Callback(hObject, ~, handles)
% Read image 2
img = imread('./coimbra_estadio.jpg');
handles.img_d = im2double(img);
% image size
size_img = size(handles.img_d);
handles.colums = size_img(2);
handles.rows = size_img(1);
if rem(handles.rows,2) == 0
handles.row_0 = ((handles.rows/2)+1);
else
handles.row_0 = ((handles.rows/2)+0.5);
end
if rem(handles.colums,2) == 0
handles.colum_0 = ((handles.colums/2)+1);
else
handles.colum_0 = ((handles.colums/2)+0.5);
end
axes(handles.axes1);
imshow(img);
% Generate eventdata to call the radiobuttons function
eventdata_new.EventName = 'SelectionChanged';
eventdata_new.OldValue = get(handles.uipanel3,'SelectedObject');
eventdata_new.NewValue = get(handles.uipanel3,'SelectedObject');
uipanel3_SelectionChangeFcn(handles.uipanel3, eventdata_new, handles);
guidata(hObject, handles)
As you can see, in the end I call the panel function so when the image is loaded it is automatically filtered and the axes2 image changes.
The problem is when I call the save function it saves the old img_new.
If I change the radiobutton the img_new is refreshed, but if it is not changed it is not refreshed. It should be as loading an image automatically calls for the panel of radiobuttons function.
The problem is that guidata(hObject,handles); at the end of img2_Callback saves old handles object as a final gui state, updates made in uipanel3_SelectionChangeFcn are lost. You need to eitehr manually update handles after calling uipannel3_SelectionChangeFcn by putting handles = guidata(hObject,handles);
or handles=guidata(hObject);
(forgot which call to guidata updates handles, please see help for that), or simply remove the line guidata(hObject,handles); at the end of img2_callback (less safe if code is going to change later, updating handles after uipannel3_SelectionChangeFcn is safer approach...
Related
I'm creating a function that lets an user add or remove his/her input to the list. In this case, uitable. (Matlab)
In fact, the following code was a draft and just thinking about ideas.
Does anybody know a similar example?
(edit_com : add, delete_com : remove)
% to add an input to a list
function edit_com_Callback(hObject, eventdata, handles)
value = get(handles.insert_com, 'String'); %user input (char)
data = get(handles.uitable1, 'Data') % read table matrix
data(end+1,:) = 0; % add below the data matrix sequently.
% this is for test and I want to put an char input instead of numbers.
set(handles.uitable1, 'Data',data);
% cell selection function before a delete function
function uitable1_CellSelectionCallback(hObject, eventdata, handles)
% no selection
if ( numel(eventdata.Indices) == 0 )
% only one selected
elseif ( numel(eventdata.Indices) == 1 )
set(handles.delete_com, 'Enable', 'on'); % "delete" buttion activate
selected_com = eventdata.Indices(1); % read currently selected row
set(handles.edit_com, 'UserData', selected_com);
% more than 2 selected
else
set(handles.delete_come, 'Enable', 'on'); % "delete" buttion activate
selected_com = eventdata.Indices(:,1); % read currently selected rows
set(handles.edit_com, 'UserData', selected_com);
end
% deletion part
function delete_com_Callback(hObject, eventdata, handles)
if get(handles.edit_com, 'UserData') ==0 % none selected
else if get(handles.edit_com, 'UserData') ==1 % one selected
data = get(handles.uitable1, 'Data') %
data(row_1,:)=[]; % delete
else % more than one selected
data = get(handles.uitable1, 'Data')
data(row_2,:)=[]; % delete them
end
first it separates several cells from the cell and then separates them (separated by user data). I'm just trying to figure out which column is selected, and I try to erase it from a function. It's hard to deal with it
because it consists of characters and I don't know how to handle cells. What's the best way to get started?
If you want to use strings (character arrays) inside pass to your uitable a Data parameter being of type cell, for example;
data = cell(10,10); % a 10-by-10 empty cell matrix
set(handles.uitable1,'Data',data);
or:
data = repmat({'hi'},10,10); % a 10-by-10 matrix of cells containing the string "hi"
set(handles.uitable1,'Data',data);
For what concerns the main function:
% Here you should disable your delete button when nothing is selected,
% and enable it back when something is selected. Your indices data should
% always be kept up-to-date. You don't need to handle too many cases,
% "something selected" and "nothing selected" is enough.
function uitable1_CellSelectionCallback(hObject,eventdata,handles)
if (isempty(eventdata.Indices))
set(handles.delete_com,'Enable','off');
rows = [];
else
set(handles.delete_com,'Enable','on');
rows = eventdata.Indices(:,1);
end
set(handles.edit_com,'UserData',rows);
end
Now, for what concerns the addition of rows:
function edit_com_Callback(hObject, eventdata, handles)
value = get(handles.insert_com,'String');
data = get(handles.uitable1,'Data');
data(end+1,:) = {value};
set(handles.uitable1,'Data',data);
end
And for what concerns the removal of rows:
function delete_com_Callback(hObject, eventdata, handles)
data = get(handles.uitable1,'Data');
rows = get(handles.edit_com,'UserData');
idx = (1:size(data,1))';
idx(rows) = [];
data = data(idx,:);
set(handles.uitable1,'Data',data);
end
I have program where at the end a GUI is launched. I built it using guide. I load 4 variables from my program into 4 GUI text boxes using a mat file called n.mat (and a pushbutton feature).
In the program
n = [nuno, ndue, ntre, nquattro];
save n.mat
In the GUI interface pushbutton
% --- Executes on button press in upload.
function upload_Callback(hObject, eventdata, handles)
% hObject handle to upload (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
S = load('n.mat');
handles.v1 = S.nuno;
handles.v2 = S.ndue;
handles.v3 = S.ntre;
handles.v4 = S.nquattro;
set(handles.initial1,'String',num2str(handles.v1));
set(handles.initial2,'String',num2str(handles.v2));
set(handles.initial3,'String',num2str(handles.v3));
set(handles.initial4,'String',num2str(handles.v4));
guidata(hObject, handles);
Then I have other 4 text boxes where I change the value of the variables and save them in another mat file. I'm not sure if I'm doing this correctly.
In the program (before calling myGUI) I initialize the m vector for the updated variables.
nunof = 0;
nduef = 0;
ntref = 0;
nquattrof = 0;
m = [nunof, nduef, ntref, nquattrof];
save m.mat
In the program (after calling myGUI) I try and load the m.mat file and extract the variables from it so I can use them in some calculations further in the program.
load m.mat;
nunof = m.nunof;
nduef = m.nduef;
ntref = m.ntref;
nquattrof = m.nquattrof;
Before this, in the GUI interface 'done' button I try and save my inputs into the m.mat file like this:
function done_Callback(hObject, eventdata, handles)
% hObject handle to done (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% save the parameters to file
load('m.mat');
m = [nunof, nduef, ntref, nquattrof];
nunof = str2num(get(handles.final1,'String'));
nduef = str2num(get(handles.final2,'String'));
ntref = str2num(get(handles.final3,'String'));
nquattrof = str2num(get(handles.final4,'String'));
save('m.mat','-append');
I want to know why this isn't working and how can I change it. Thanks a lot.
You can't use save('m.mat','-append');. You're missing an option to get to append.
In order to use append you have to declare a filename, the variable and then append.
save(filename,variables,'-append')
Taken from - https://au.mathworks.com/help/matlab/ref/save.html
Also, from your code you're not redefining the variables in your m struct.
I have 2 guis in matlab which are named main and sub. I do some calculation on a image by push button in subgui and want to transfer the results (handles.sh and handles.sv) to edit box of main gui and these results should be showed in separate lines in edit box. I used setappdata and getappdata but it doesn't work and it doesn't show any thing or more probably I made a mistake.
edit box callback of main gui
function edithistory_Callback(hObject, eventdata, handles)
% hObject handle to edithistory (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
handles.sh = getappdata(0,'horizontal');
set(hObject,'String',num2str(handles.sh));
handles.sh = getappdata(0,'vertical');
set(hObject,'String',num2str(handles.sv));
push button callback of subgui
Bw = im2bw(handles.D);
s = regionprops(Bw, handles.D, 'Centroid');
handles.sx = round(s.Centroid(1));
handles.sy = round(s.Centroid(2));
handles.roi = handles.roi/2;
i = (handles.sx-((handles.roi)-1)):(handles.sx+ handles.roi);
j = (handles.sy-((handles.roi)-1)):(handles.sy+ handles.roi);
ROI = (handles.D(i,j));
ROI = (2^16)-ROI;
avg = sum(ROI(:))/((2*handles.roi).^2);
profileh1 = (handles.D(handles.sx,:));
profileh = (2^16-profileh1);
profileh(1)= profileh(2);
FieldSizeh = profileh(profileh>=avg*0.5);
FieldSizeh(:) =avg;
handles.sh = (size(FieldSizeh,2)*0.25);
setappdata(0,'horizontal',handles.sh);
profilev1 = handles.D(:,handles.sy);
profilev = (2^16-profilev1);
profilev(1)= profilev(2);
FieldSizev = profilev(profilev>=avg*0.5);
FieldSizev(:)=avg;
handles.sv = (size(FieldSizev,1)*0.25);
setappdata(0,'vertical',handles.sv);
I am setting the handles in the opening function:
function Select_A_B_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.string = '';
new_count = 1;
set(handles.counter,'String',num2str(new_count));
if isempty(varargin)
varargin{1} = 1;
varargin{2} = 1;
end
A = {'Apple';'Orange';'Bag';'Cowboy'};
handles.pushbutton1text = A;
new_count = str2double(handles.counter.String);
handles.pushbutton1 = handles.pushbutton1text(new_count);
guidata(hObject, handles);
Then I am trying to change the handles to pushbutton1 when the pushbutton tagged as 'Next' is pushed:
function next_Callback(hObject, eventdata, handles)
current_count = str2double(get(handles.counter, 'String'));
new_count = current_count+1;
set(handles.counter,'String',new_count);
set(handles.pushbutton1,'String',get(handles.counter,'string');
guidata(hObject, handles);
I get the following error when I try to set the handles to pushbutton1:
Error using set
Conversion to double from cell is not possible.
I have tried several ways to fix the error, but no success yet. What am I doing wrong?
Here is a programmatic GUI which does what you want and is, in my opinion, much simpler to understand/debug. You can easily implement this using GUIDE; everything that comes before the pushbutton's callback can be put into the GUI Opening_Fcn.
I added comments in the code; if something is unclear please tell me.
function DisplayFruits
clear
clc
hFig = figure('Position',[200 200 300 300]);
handles.A = {'Apple';'Orange';'Bag';'Cowboy'};
handles.counter = 1;
%// Counter text
handles.CounterTitle = uicontrol('Style','text','Position',[50 200 60 20],'String','Counter');
handles.CounterBox = uicontrol('Style','text','Position',[130 200 60 20],'String','1');
%// Content of A
handles.TextTitle = uicontrol('Style','text','Position',[50 170 60 20],'String','Content');
handles.TextBox = uicontrol('Style','text','Position',[130 170 60 20],'String',handles.A{handles.counter});
%// Pushbutton to increment counter/content
handles.PushButton = uicontrol('Style','push','Position',[130 100 80 40],'String','Update counter','Callback',#(s,e) UpdateCallback);
guidata(hFig,handles);
%// Pushbutton callback
function UpdateCallback
%// Update counter
handles.counter = handles.counter + 1;
%// If maximum value possible, set back to 1.
if handles.counter == numel(handles.A)+1;
handles.counter = 1;
end
%// Update text boxes
set(handles.CounterBox,'String',num2str(handles.counter));
set(handles.TextBox,'String',handles.A{handles.counter});
guidata(hFig,handles);
end
end
Sample screenshot of the GUI:
As the user presses the button, the counter is incremented and the "content box" is updated.
Hope this helps!
As a side note, I think the error you got above was due to this command:
handles.pushbutton1 = handles.pushbutton1text(new_count);
here you assigned a string to the pushbutton but later you try to modify its String property and Matlab does not like it.
Initially my prog is like that (playing sound and judge what kind of sound is) :
n_repetition=10
for i=1:n_repetition
playsound(strcat(i,'wav'));
answer=input(' answer q/z/e ?','s');
switch answer
case 'q'
asw="bird";
case 'z'
asw="water";
case 'e'
asw="wind";
otherwise
disp('error');
end
end
Now I'm trying to make it more interactive with GUI, I'm using GUIDE and i've generate a .fig which contain 4 buttons: OK button, BIRD, WATER, WIND
I've also my callbacks which are empty now
What I want to do is:
-Initially all buttons are inactive
-Participant should press on ok to begin
-play sounds
-activate the buttons (sound bird, water, wind)
-catch response
-deactivate button
-wait for press ok for new trial
How could I adapt my initial code the the callback, where should I put my loop ? Thanks
Add these at the start of guiname__OpeningFcn -
handles.song_count = 0;
handles.asw = cell(10,1);
Edit your button callbacks to these -
% --- Executes on button press in ok_button.
function ok_button_Callback(hObject, eventdata, handles)
handles.song_count = handles.song_count +1;
filename = strcat(num2str(handles.song_count),'.wav');
[y,~] = audioread(filename);
%%// Use soundsc or your custom playsound function to play the sounds
soundsc(y); %playsound(strcat(i,'wav'));
guidata(hObject, handles); %%// Save handles data
return;
% --- Executes on button press in bird_button.
function bird_button_Callback(hObject, eventdata, handles)
asw = 'bird'; %%// Do something with 'asw'
handles.asw(handles.song_count) = {asw}; %%// Store the 'asw' values as a cell array
guidata(hObject, handles); %%// Save the handles data
return;
% --- Executes on button press in water_button.
function water_button_Callback(hObject, eventdata, handles)
asw = 'water'; %%// Do something with 'asw'
handles.asw(handles.song_count) = {asw}; %%// Store the 'asw' values as a cell array
guidata(hObject, handles); %%// Save the handles data
return;
% --- Executes on button press in wind_button.
function wind_button_Callback(hObject, eventdata, handles)
asw = 'wind'; %%// Do something with 'asw'
handles.asw(handles.song_count) = {asw}; %%// Store the 'asw' values as a cell array
guidata(hObject, handles); %%// Save the handles data
return;
Note: At any point of time view handles.asw to look at the button clicks history.
Suggestion: If it's okay to show the choices made by the GUI user as a list, you might consider adding a Table into the GUI. You can put the data from handles.asw into such a Table.