0

I am trying to develop a GUI in Octave (4.0.1, using the GUI version) with the code as follows:

  • Main GUI function
    • Function to create figure & various uicontrol
    • Callback function for uicontrol #1
    • Callback function for uicontrol #2
    • Callback function for uicontrol #3
    • etc...

Each function is delimited by function & end. The first callback I tried to write looks like this: the button is defined in the "graphical creation" function as:

gui.select_btn = uicontrol('Style','pushbutton','String','Select log file ...',...
                'Units','normalized','Position',[0.01 0.52 0.25 0.47],...
                'BackgroundColor',get(gui.Window,'Color'),'Parent',gui.file_panel,...
                'Enable','on','Callback',{@browse_log_file,gui});

and the callback for it is defined in the callback function later as:

function browse_log_file(src,data,gui)
  % Called when user presses the "Select log file ..." button
  [fname, pname] = uigetfile({'*.log'},'Select log file');          
  set(gui.log_file_edit,'String',[pname,fname]);
end

whi gui being a struct defined in the main GUI function by calling the "graphical creation" function & accessible by all nested functions.

However, when I try to run the code, I get the following error message:

error: handles to nested functions are not yet supported
error: called from
    GUI_analyser>create_interface at line 71 column 20
    GUI_analyser at line 8 column 7
error: evaluating argument list element number 1
error: called from
    GUI_analyser>create_interface at line 71 column 20
    GUI_analyser at line 8 column 7
error: evaluating argument list element number 16
error: called from
    GUI_analyser>create_interface at line 71 column 20
    GUI_analyser at line 8 column 7

pointing to the line with {@browse_log_file,gui}.

Any suggestions on how to work round this problem?

am304
  • 13,758
  • 2
  • 22
  • 40
  • 1
    Use subfunctions instead of nested functions. – carandraug Jul 21 '16 at 13:31
  • @carandraug Can you give me an example that I can then adapt to my use case? I only one degree of "nesting" in my code. All functions are at the same hierarchical level under the main GUI function. the `gui` struct is defined in there so that it can be seen by all other functions in the code. – am304 Jul 21 '16 at 13:39
  • take a look at the last patch on https://savannah.gnu.org/patch/?8722 which implements `impixelinfoval`. The only difference from your case is that it doesn't share any of its variables with the subfunction. I'm unsure of the scoping rules there, but maybe an handle for an anonymous function will work. – carandraug Jul 21 '16 at 14:06
  • @carandraug Thanks, I have managed to make it work using subfunctions, i.e. having all functions at the same level as the main GUI function, but still all in one file. The only thing I have had to do is set the callbacks for the various `uicontrol` objects at the very end of the "graphical creation" function, otherwise those `uicontrol` objects defined after the callback has been set are not visible from the callback function. – am304 Jul 21 '16 at 14:45
  • The funny thing is I am re-using some code which used to work perfectly well in Octave 3.6.2, so it's almost as if Octave has gone backwards with the most recent releases.... – am304 Jul 21 '16 at 14:46
  • That sounds like a regression but I was not aware that Octave ever supported handles to nested functions (even nested functions in general are not recommended because of some odd Matlab scoping rules). Anyway, if your code was working before, you should [report a bug](https://savannah.gnu.org/bugs/?39257). – carandraug Jul 21 '16 at 15:13
  • @carandraug Thanks, will do when I get more time. Now I have another problem, which is I add data to my `gui` struct during one of the callbacks, except the `gui` struct doesn't get updated. When I try to access this newly created data in a later callback, it's telling me that it doesn't exist. I have tried `guidata(gui.Window,gui)` at the end of the callback, but it doesn't seem to work. The handle to my figure is `gui.Window`, which is part of the overall struct `gui`. So once again, I am stuck. – am304 Jul 21 '16 at 21:58
  • I have managed to solve it by creating another handle/struct for storing data: `h = guidata(gui.Window)` at the beginning of the callback(s), and `guidata(gui.Window,h)` at the end of the callback(s). I will compile all these into my own answer, unless you want to have a go at writing one, in which case I'd be happy to accept it. – am304 Jul 21 '16 at 22:16
  • @carandraug nice; how long has `uicontrol` been around? I remember wanting to use it not too long ago and it was unimplemented. – Tasos Papastylianou Jul 23 '16 at 16:00
  • @carandraug and it looks beautiful btw. Cleaner than the matlab version in my opinion (presumably because it uses native look-and-feel). Good work octave team. – Tasos Papastylianou Jul 23 '16 at 16:05

0 Answers0