I built in GUI (using GUIDE) a uitable (4x5) that last row is logical so I can select lines to delete.
d = {'L1',1,10,true;'L2',2,20,true;'L3',3,30,false;'L4',4,40,true;'L4',5,50,false};
set(handles.outputTable,'Data',d)
I created a button to delete the selectd rows but I does not work:
function deleteButton_Callback(hObject, eventdata, handles)
% hObject handle to deleteButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
dataTable = (get(handles.outputTable,'data'));
[m n] = size(dataTable);
disp(dataTable);
for i = 1:m
if num2str(cell2mat(dataTable(i,4))) =='1'
dataTable(i,:)=[];
end
end
disp('Modifed table')
disp(dataTable);
How can I fix it so I get set the table again in the GUI?
This is wrong:
for i = 1:m
if num2str(cell2mat(dataTable(i,4))) =='1'
dataTable(i,:)=[];
end
end
First of all, if num2str(cell2mat(dataTable(i,4))) =='1' is a convoluted equivalent of if dataTable{i,4}==1. You should learn to use curly braces {} to access the content of a cell array.
Then, it will work only if the counter is decreased.
See what happens:
Test if row n should be deleted
Delete line n; the content of row (n+1) have now moved to row n
Increment counter i from value n to n+1
The row now at position n has never been tested for deletion !
What was at row (n+1) is never tested, since the delete operation moves it backwards first, then the counter is incremented without testing again. The solution is to decrement the counter.
for i = m:-1:1
if dataTable{i,4}
dataTable(i,:)=[];
end
end
The rows moved by the deletion operation have already been tested, so in the end it is certain that all lines will have been tested.
Now, the same can be obtained in a vectorized form with a single line:
dataTable = dataTable(cell2mat(dataTable(:,4))==0,:);
The whole function boils down to:
function deleteButton_Callback(hObject, eventdata, handles)
dataTable = get(handles.outputTable,'data');
% Do some checks to make sure that the values input by are correct %
assert(all(cellfun(#isscalar,dataTable(:,4))), 'Last colum should contain scalars!');
set(handles.outputTable,'data' , dataTable(cell2mat(dataTable(:,4))==0,:));
end
Related
Im trying to do a GUI in matlab that accepts the values in a table to converting it to a matrix, but the idea is that a user can set the number of rows and columns first.
The panel looks like this
and the code for the push button is
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
rows =str2double(get(handles.edit_rows,'String'));
cols=str2double(get(handles.edit_cols,'String'));
num_elem=cell(rows,cols);
num_elem(:,:)={"};
set(handles.uitable1,'Data',num_elem)
set(handles.uitable1,'ColumnEditable',true(1,cols))
But then, how can export or convert to a matrix so I can apply functions to it?
UPDATE
With the help of byetisener I updated the code to
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
filas=str2double(get(handles.edit_fila,'String'));
column=str2double(get(handles.edit_col,'String'));
num_elem=cell(filas,column);
num_elem(:,:)={''};
set(handles.uitable1,'Data',num_elem)
set(handles.uitable1,'ColumnEditable',true(1,column))
handles.uitable1.Data = cell(filas, column);
matrix = cell2mat(handles.uitable1.Data);
matrix
but this is giving an empty matrix
It is not taking the values of the cells, it is supposed that the button resizes and copy the values at the same time, if not how con copy in another button once the matrix is resized?
There are some problems about your code:
You do not really assign values here, you are just setting the Data of the uitable to an array of empty cells.
num_elem =
1×2 cell array
{0×0 char} {0×0 char}
If you ever succeed, you code will write everything you want to only the first column of the uitable. Because you are not iterating through rows. The pushbutton only adds to the first row.
cell2mat() function won't work if you have different data types in your table. You may think that you do not have different data types, but empty cells are type cell and the data you enter is type double, so there it is.
To solve all of this I have rewritten a callback function for you. You may directly paste this code to your callback, replacing yours. I should give you the matrix you want at the end, it does in my computer.
filas = str2double(handles.edit_fila.String);
column = str2double(handles.edit_col.String);
% This loop looks for an empty row to write new data
for i = 1:length(handles.uitable1.Data)
if isempty(handles.uitable1.Data{i,1})
handles.uitable1.Data(i,1) = {filas};
handles.uitable1.Data(i,2) = {column};
break;
else
disp('Error occured');
end
end
% This double for loop check if there are any empty cells
% if it finds one, it changes it to 0, so all the cells have the same type
for i = 1:length(handles.uitable1.Data)
for j = 1:2
if isempty(handles.uitable1.Data{i,j})
handles.uitable1.Data(i,j) = {0};
else
disp('Error occured');
end
end
end
matrix = cell2mat(handles.uitable1.Data); % The matrix you want
Just check if all the variable names are the same and do not forget to accept is as an answer. Hope it helps.
I am not sure if this answers you question but you can follow this approach.
First of all, if you are interested, using dot notation is faster in MATLAB than setter and getter methods.
So, what you can do is:
handles.uitable1.Data = cell(rows, cols);
or, of course, alternatively:
set(handles.uitable1, 'Data', cell(rows,cols));
If what you want to is to convert the data in uitable to a matrix, you can use:
matrix = cell2mat(handles.uitable1.Data);
If you table contains non-numeric values:
tableData = handles.uitable1.Data;
tableData = [str2double(tableData(:, 1)), cell2mat(tableData(:, 2))];
Hope this helps. Let me know if you solve your problem.
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 am trying to write a list in a listbox.
code:
function listbox1_Callback(hObject, eventdata, handles)
% hObject handle to listbox1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: contents = cellstr(get(hObject,'String')) returns listbox1 contents as cell array
% contents{get(hObject,'Value')} returns selected item from listbox1
error = getappdata(0, 'error_norm');
rows = size(error,1);
for i = 1:rows
set(handles.listbox1,'string',strcat('filt_',num2str(i)));
for j = 1:length(error)
set(handles.listbox1,'string',strcat('sig_',num2str(i),'_',num2str(j)));
for k = 1:length(error{j}.main)
set(handles.listbox1,'string',strcat('seg_',num2str(i),'_',num2str(j),'_',num2str(k)));
end
end
end
Where error is a array of structure, this array contains filters, singals in these filters, segments of these signals. based on the number of all these components, i want to write the list. I want to write something like this in the listbox:
filt_1
sig_1_1
seg_1_1_1
seg_1_1_2
sig_1_2
seg_1_2_1
seg_1_2_2
But apparently, 'set' function overwrites the elements, so all i am getting is 1 element and the last element.
Any suggestion to how to overcome this problem will be appreciated.
Yes, since set always overwrites the string, it is better to firstl build the string and then pass it to set.
Example
% Sample data
rows=4;
error=cell(1,5);
for i=1:length(error)
error{i}.main=rand(1,4);
end
% Build string
str={};
for i=1:rows
str{end+1}=sprintf('filt_%i',i);
for j=1:length(error)
str{end+1}=sprintf('sig_%i_%i',i,j);
for k=1:length(error{j}.main)
str{end+1}=sprintf('seg_%i_%i_%i',i,j,k);
end
end
end
% Set data
set(handle.listbox1,'String', str);
Depending on the size of the final string it might be a good idea to preallocate str for performance.
I've been working on a little custom made database in MATLAB.
I have a GUI with a bunch of 'Edit Text' boxes and buttons.
The key is that I should be able to register an undefined number of students with some information like names, surnames, code etc. I've managed to store only one student (i.e the first time i push the 'Submit Button') but when i enter another student's information, MATLAB just overwrites the information from the previous registration.
Here's the Callback for the 'Submit' button
function Submit_Callback(hObject, eventdata, handles)
global n
n=n+1
% hObject handle to Submit (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
name1 = get(handles.name,'String'); %edit1 being Tag of ur edit box
name2=get(handles.name2,'String');
name3=get(handles.name3,'String');
major=get(handles.major,'String');
labavg=num2str(get(handles.labavg,'String'));
finalgrade=num2str(get(handles.finalgrade,'String'));
email=num2str(get(handles.email,'String'));
code=num2str(get(handles.code,'String'));
for ii=1:numel(n)
student_information(ii).name=name1
student_information(ii).surname1=name2
student_information(ii).surname2=name3
student_information(ii).code=code
student_information(ii).major=major
student_information(ii).final_grade=finalgrade
student_information(ii).laboratory_average=labavg
student_information(ii).email=email
end
assignin('base', 'student_information', student_information)
end
I've declared the counter 'n' as a global variable set to '0' in the workspace.
I'm not sure if my code isn't looping properly. Maybe the mistake is in there but I can't see how to fix it.
Can you please help me with my code?
Thanks!
I'm not sure what you were trying to achieve with your loop, but I don't see the need for it. Also, by using assignin, you are overriding the contents of student_information in your workspace. You are better off making student_information global in Submit_Callback in addition to n, then construct a new_student structure using your information and append it to student_information as follows:
name1 = get(handles.name,'String'); %edit1 being Tag of ur edit box
name2=get(handles.name2,'String');
name3=get(handles.name3,'String');
major=get(handles.major,'String');
labavg=num2str(get(handles.labavg,'String'));
finalgrade=num2str(get(handles.finalgrade,'String'));
email=num2str(get(handles.email,'String'));
code=num2str(get(handles.code,'String'));
new_student.name = name1;
new_student.surname1 = name2;
new_student.surname2 = name3;
new_student.major = major;
new_student.laboratory_average = labavg;
new_student.final_grade = finalgrade;
new_student.email = email;
new_student.code = code;
student_information(n) = new_student;
n = n + 1;
and that should append the new entry at the end of the struct array.
I have in my gui an edit text field that accepts multiple lines with a Max value of 5, and i can't find a way to display a matrix with the input values...something like this:
m=[m(1) m(2) m(3) m(4) m(5)];
set(handles.show,'string',m)
how can i store the values in the calculate callback..every time i run this, it brings me an error..
function masa_Callback(hObject, eventdata, handles)
% hObject handle to masa (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%h_edit is the handle to the edit box
m=str2double(get(hObject,'String'));
function calculate_Callback(hObject, eventdata, handles)
% hObject handle to agregarm (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
f = str2double(get(h_fuerza,'string')); %h_edit is the handle to the edit box
m = str2double(get(h_masa,'string')); %h_edit is the handle to the edit box
[row, column] = size(m);
for i = 1:row
eval(m{i,:}) %evaluate each line as in MATLAB command prompt
end
I have the masa_callback,rigidez_callback and fuerza_callback i try to read the user input in the edit text box...so i want to pass those values to the calculate_callback as an array to perform certain operations according to the value of n...the error that i am getting is that when for example n=2, i add two values in the masa_callback column and fuerza_callback and 3 values in the rigidez_callback, those values are passed to the case n==2, and when my program tries to display for example the matrix m, it displays all the values i enter together in the spaces of m(1) and m(2)...i want to put only each separated value, not joined together!...How can i fix this,, i believe that is whith an array and a loop but i dont know how, and how to pass the array values to the equation to perform operations(as numbers) and display it as string
To fix the problem with the input (assuming you have your data in some cell array, and that handles.show refers to a text box), use strvcat:
someCellArray = {'a','b'};
m = strvcat(someCellArray{:});
set(handles.show,'string',m)
Your problem stems from the line
m = str2double(get(h_masa,'string'));
You do not want to convert the string to double.
Since the String property actually returns a multiline string, you have to modify your code like this:
m = get(h_masa,'String');
nRows = size(m,1);
for iRow = 1:nRows
eval(m(i,:));
end