Save uitable data that is created in GUI callback

Hello!

I have one issue to solve which is the following:

I have a GUI (uipanel) and on that GUI there is a button. When the button is pressed, a figure opens and a uitable is created there. The table is editable and what I want is, when the figure is closed, that the edited data from the table is stored. Since the table is only created during the button press, the table handle only exists temporarily and this makes it difficult for creating callback functions that refer to this table. Are there any ideas on how to do this as simple as possible?

Since the callback function of the uipanel GUI has handles that operate with the guidata function, I tried storing the uitable handle in the structure from the GUI guidata. however, it still does not quite work.

I am thinking the simplest would be to define a deletefcn for the table, however, when the table and its handle is within the callback function of the gui, how can you implement the deletefcn properly? As far as I know I can’t define a callback function within a callback function

Any help apreciated!

I’m not exactly sure if I understand correctly. So, this might or might not work for your case.
IIUC, you have a “main” GUI figure in which you are already storing some guidata.
There is a button in this “main” GUI figure that has a callback function that opens another figure that contains among other things an uitable. You’d like to pass the data from the uitable to the “main” figure.

One possible solution for this might be:

  • Pass the handle to the “main” GUI figure to the function that creates the figure with the uitable.
  • When you create the content of that figure, add a pushbutton that says “Accept” (or something similar).
  • Add a callback to that pushbutton that
    1. takes the handle to the “main” GUI figure as one of its input arguments,
    2. gets the "Data" property of the uitable,
    3. adds that data to the guidata of the “main” GUI figure,
    4. closes the figure with the uitable.
  • Continue like you need with that data in the “main” GUI figure.

Would that do what you are looking for?

Yeah its not that easy to explain for me, sorry for that :see_no_evil:

yes, i have a main GUI, which is in my case a uipanel element. here i have lots of buttons and other elements that all have a callback and that callback is one big function that handles all the graphic elements callbacks of that panel (in the code below “mycallback”). And among those graphic elements, I have two buttons, the first creates a figure and a uitable with some data in it. I want that the table is editable by the user and then to save the changes made to the table (it should work like settings for any program basically). then the data after editing should be transfered to the main callback function of the panel, which then can be used for another button on the panel to process this data.

here would be the quick and dirty structure of the code, for better illustration (might not be 100 % correct syntax and all, its just to illustrate it):

p = uipanel();
handle.button_table = uicontrol(p, 'style', 'pushbutton', 'callback', @mycallback(h,p));
handle.button_start = uicontrol(p, 'style', 'pushbutton', 'callback', @mycallback(h,p));
function mycallback(obj, p)
handle = guidata(obj)
switch (gcbo)
    case {handle.button_table}
        f = figure()
        t = uitable(f)
    case {handle.button_start}
        data_table = ??
endswitch
end
guidata(gcf, h)
mycallback(gcf, true)

so I want to transfer data_table from the uitable t to the button_start element. I figured one way would be to use the deletefcn of the uitable, but here I have the problem that I can’t define the deletefcn within the callback function and therefore the data from the table wont be defined in the callback function anymore.

so a seperate Accept button like you suggest might be the better idea. However, is it possible to have the button here also on the figure f and having the button a callback to the “mycallback” function as well? so its like a callback within a callback that refers to the same callback? is that possible?

It looks like I couldn’t explain myself either.
Maybe it is easier to let code speak:

close all
handle.fig_main = figure(100);
p = uipanel(handle.fig_main);
handle.button_table = uicontrol(p, 'style', 'pushbutton', 'callback', @mycallback, 'units', 'normalized', 'position', [0 0 0.5 1]);
handle.button_start = uicontrol(p, 'style', 'pushbutton', 'callback', @mycallback, 'units', 'normalized', 'position', [0.5 0 0.5 1]);

function table_delete_fcn(h, e, hf_main)
  handle = guidata(hf_main);
  handle.table_data = get(handle.table, "data");
  guidata(hf_main, handle);
end



function mycallback(obj, p)
handle = guidata(obj);
switch (gcbo)
  case {handle.button_table}
    handle.fig_table = figure(101);
    handle.table = uitable(handle.fig_table, 'data', {'1', '2', '3'}, 'columneditable', true(1,3));
    hf_main = handle.fig_main;
    set(handle.table, 'deletefcn', @(h,e) table_delete_fcn(h, e, hf_main));

  case {handle.button_start}
    data_table = handle.table_data;
    disp(data_table)

endswitch

guidata(handle.fig_main, handle);
end

guidata(handle.fig_main, handle);

That is probably personal preference: But I prefer having separate functions for separate functionality. You could probably also squeeze table_delete_fcn into mycallback and let it accept an optional third argument. Imho, that will get pretty messy pretty fast though.

1 Like

That is exactly what I want! Thank you very much! I have to be honest, the guidata function and the indexing is still a bit confusing for me, so I will work through your code to understand whats happening! Anyways, it does work great, thank you very much!