1

I'm using Octave GNU for GUI Excel data. I want to ask you guys how can I call defined argument in another function. Here is my code.

%%First Function = pushbutton_Callback

function pushbutton_Callback(hObject, eventdata, handles)
fileName = uigetfile('*.xlsx')%%excel data import

handles.fileName=fileName;

guidata(hObject, handles)

endfunction

%%Second Function = popupmenuX_Callback

function popupmenuX_Callback(hObject, eventdata, handles)
fileName = fileName @pushbutton_Callback; 
printf ("in popupmenuX_Callback, calling pushbutton_Callback\n");

%%To nested function to prevent (because in Octave nested function is not accepted), I used subfunction as alternative%%

handles.fileName=fileName; %% This argument fileName I want to bring from first function
[numbers, colNames]=xlsread(fileName); %%read columns of excel data in first function
set(hObject,'string',colNames);
endfunction

If I put my functions like this, always come these errors.

>> fileName = V8.xlsx
error: superclass calls can only occur in methods or constructors
error: called from
    popupmenuX_Callback at line 61 column 10

So what I want to do is, I want to bring defined Argument "fileName" in first function (pushbutton_Callback) to second function (popupX_callback). But it can not be defined in second function. I've heard that nested function in octave can be resolved with "foo", "foobar" or "ex_top", "ex_a" function. But I can't not resolve the problem with "ex_"function. Then should I have to use "foo", "foobar" function to call arguments into other function?

Best regards!

===========================================================================

I edited my questions with my full codes. (Full codes below) So what I want to do is, just like this video. But in Matlab like in video, it can be made with GUIDE or Application designer but in Octave there are no functions like that. So as a octave Beginner, it is hard for me to solve the problem.

%%Versuch
%% Diagramm zeichen
%%============================================================================
close all
clear h
graphics_toolkit qt
pkg load io
%%Uicontrols
%%Graph
h.ax = axes ("position", [0.3 0.25 0.6 0.5]);


%%Title
h.plot_title_label = uicontrol ("style", "text",
                                "units", "normalized",
                                "string", "Versuchsergebnis",
                                "horizontalalignment", "left",
                                "position", [0.03 0.9 0.25 0.08]);
                                  
%% Design for excel data import
    
h.print_pushbutton = uicontrol ("style", "pushbutton",
                                "units", "normalized",
                                "string", "Excel Datei mitbringen",
                                "callback", @pushbutton_Callback,
                                "position", [0.03 0.8 0.3 0.09]);


%% Drawing axis
h.popupmenuX        = uicontrol("Style","popupmenu",
    "units", "normalized",
    "string","X Axis",...
    "callback", @popupmenuX_Callback,
    "Position",[0.7 0.04 0.2 0.05]);
    
h.popupmenuY        = uicontrol("Style","popupmenu",
    "units", "normalized",
    "string","Y Axis",
    "callback",@popupmenuY_Callback,
    "Position",[0.03 0.5 0.2 0.05]);
%%=============================================================================                              
%% Functions
%%=============================================================================

%% 1. Excel Data import
function pushbutton_Callback(hObject, eventdata, handles)
fileName            = uigetfile('*.xlsx')%%excel data import
handles.fileName    = fileName;
guidata(hObject, handles)
endfunction

%% 2. X Axis Information from excel data import

function popupmenuX_Callback(hObject, eventdata, handles)
fileName            = pushbutton_Callback(hObject, eventdata, handles)
%%This code fileName causes error, that 'handles' is not defined.%%
handles.fileName    = fileName; %% This argument fileName I want to bring from first function
[numbers, colNames] = xlsread(fileName); %%read columns of excel data in first function
set(hObject,'string',colNames);
endfunction

%% 3. Y Axis Information from excel data import
function popupmenuY_Callback(hObject, eventdata, handles)
filename            = pushbutton_Callback(hObject, eventdata, handles)
handles.fileName    = fileName;
[numbers, colNames] = xlsread(fileName);
set(hObject,'string',colNames);
endfunction

%%%% Plot the graph
a                   = xlsread (fileName);
xColNum             = get(popupmenuX_Callback,'value');
yColNum             = get(popupmenuY_Callback,'value');
fileName            = handles.fileName;
x                   = a(:,xColNum);
y                   = a(:,yColNum);
h.ax                = plot(x,y);
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
Heewonny
  • 25
  • 6
  • Your mental model of functions and variables is wrong. Variables defined in a function only exist while that function is running. At the end of the function, all its variables are destroyed. So if you need one of those values later, you must save it somewhere where you can access it from where you need it. Oh, you actually already do this: `handles.fileName=fileName; guidata(hObject, handles)`. Read the `guidata` documentation to learn how to read your data. – Cris Luengo Jul 21 '21 at 14:26
  • Thank you @Cris for your answer. Sorry, but I can't understand your advice not so good, because I'm first in Octave. Could you tell me what kind of mistake did I make in this function and variables? I thought that it works good, I mean it works for importing the fileName in first function and that's what I expected. I've read the documention about [guidata](https://wiki.octave.org/Uicontrols), but still I can't not understand what is wrong with mein. – Heewonny Jul 21 '21 at 14:59

3 Answers3

2

Example of GUI which allows loading a .csv file, and populating two popupmenus based on the csv headers.

Example data.csv file:

Col1, Col2, Col3
1,    2,    3
2,    4,    8
3,    8,    9

Example myscript.m

  pkg load io

% Create the Gui Window which will hold all controls and relevant data.
  GuiWindow = figure()

% An 'axes' object for displaying plots in the Gui Window
  axes ("position", [0.3 0.25 0.6 0.5], 'tag', 'plotarea' );

% Static text element used as a title
  uicontrol ("style", "text", "units", "normalized", "string", "Fur Zoo Hair Geb knees.", "horizontalalignment", "left", "position", [0.03 0.9 0.3 0.08] );
                                    
% A button for importing (excel) data
  uicontrol ("style", "pushbutton", "units", "normalized", "string", "CSV Dat Eye Meat Bringen", "callback", { @pushbutton_Callback, GuiWindow }, "position", [0.03 0.8 0.35 0.09], 'tag', 'button' );

% Popupmenus for selecting appropriate X and Y axis to display in plots
  uicontrol("Style","popupmenu", "units", "normalized", "string","X Axis", "callback", { @popupmenuX_Callback, GuiWindow }, "Position",[0.7 0.04 0.2 0.05], 'tag', 'XAxisMenu' );
  uicontrol("Style","popupmenu", "units", "normalized", "string","Y Axis", "callback", { @popupmenuY_Callback, GuiWindow }, "Position",[0.03 0.5 0.2 0.05], 'tag', 'YAxisMenu' );

  %%=============================================================================                              
  %% Functions (preferably placed in their own files!)
  %%=============================================================================

  function pushbutton_Callback(hObject, eventdata, GuiWindow)

    % Read in data from file, graphically selected by user
      fileName = uigetfile('*.csv');
      CellCsv  = csv2cell( fileName );
      Header   = CellCsv(1, :);
      Data     = CellCsv(2:end, :);

    % Populate the menu items for the X and Y Axis from the csv header
      XAxisMenu = findobj( 'tag', 'XAxisMenu' );
      set( XAxisMenu, 'string', Header );

      YAxisMenu = findobj( 'tag', 'YAxisMenu' );
      set( YAxisMenu, 'string', Header );

    % Also store headers and data as GuiWindow app data, in case we need them again later.
      setappdata( GuiWindow, 'Header', Header );
      setappdata( GuiWindow, 'Data'  , Data   );

    % Plot a preliminary plot in the plot area
      XData = [Data{:, 1}];
      YData = [Data{:, 1}];
      plot( XData, YData, 'bo-', 'tag', 'plotobject' );          
  endfunction

  %% 2. X Axis Information from excel data import
  function popupmenuX_Callback( hObject, eventdata, GuiWindow )
      Axes      = findobj( 'tag', 'plotarea' );
      Selection = get( hObject, 'value' );
      XData     = [ getappdata( GuiWindow, 'Data' ){ :, Selection } ];
      PlotObj   = findobj( 'tag', 'plotobject' );
      set( PlotObj, 'xdata', XData )
  endfunction

  %% 3. Y Axis Information from excel data import
  function popupmenuY_Callback( hObject, eventdata, GuiWindow )
      Axes      = findobj( 'tag', 'plotarea' );
      Selection = get( hObject, 'value' );
      YData     = [ getappdata( GuiWindow, 'Data' ){ :, Selection } ];
      PlotObj   = findobj( 'tag', 'plotobject' );
      set( PlotObj, 'ydata', YData )
  endfunction

This demonstrates two methods of accessing other graphical objects within callbacks. One is providing an object as an argument (e.g., GuiWindow), and the other is providing 'tags' that can be used to identify objects via the findobj function.

Note that I stored data in the GuiWindow object only, not to each individual graphical object (like buttons etc). Also, I preferred setappdata, because it allows to store multiple data under individual names (whereas guidata only stores a single object, although this can be a struct).

Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57
  • Thanks a lot @Tasos! That was what I want. I applied your code to my code, which works with excel files. I'll put it on my answer for someone, who needs for excel file import. I've never realized, that there are code like `tag`, `findobj` or something like that. Really thanks a lot! – Heewonny Jul 29 '21 at 08:41
1

Above there is Tasos's answer (with csv file), I applied his answer to my code, which works with excel file. Because the code xlsread ignores the columns, users should have to care about that.

Thank you again Tasos!

 pkg load io

% Create the Gui Window which will hold all controls and relevant data.
  GuiWindow = figure()

% An 'axes' object for displaying plots in the Gui Window
  axes ("position", [0.3 0.25 0.6 0.5], 'tag', 'plotarea' );

% Static text element used as a title
  uicontrol ("style", "text", "units", "normalized", "string", "Versuchsergebnis",'ForegroundColor','w','BackgroundColor',[0 0.4470 0.7410],'Fontweight','bold', "horizontalalignment", "center", "position", [0.03 0.9 0.35 0.08] );
                                    
% A button for importing (excel) data
  uicontrol ("style", "pushbutton", "units", "normalized", "string", "Datei(xlsx) mitbringen", "callback", { @pushbutton_Callback, GuiWindow }, "position", [0.03 0.8 0.35 0.09], 'tag', 'button' );

% Popupmenus for selecting appropriate X and Y axis to display in plots
  uicontrol("Style","popupmenu", "units", "normalized", "string","X Axis", "callback", { @popupmenuX_Callback, GuiWindow }, "Position",[0.7 0.04 0.2 0.05], 'tag', 'XAxisMenu' );
  uicontrol("Style","popupmenu", "units", "normalized", "string","Y Axis", "callback", { @popupmenuY_Callback, GuiWindow }, "Position",[0.03 0.5 0.2 0.05], 'tag', 'YAxisMenu' );

  %%=============================================================================                              
  %% Functions (preferably placed in their own files!)
  %%=============================================================================

  function pushbutton_Callback(hObject, eventdata, GuiWindow)

    % Read in data from file, graphically selected by user
      fileName      = uigetfile('*.xlsx');
      [num,txt,raw] = xlsread(fileName);
      header        = raw(1,:);
      Data          = xlsread(fileName);
    % Show fileName
      button   = findobj('tag', 'button');
      set( button, 'string', fileName)
    % Populate the menu items for the X and Y Axis from the csv header
      XAxisMenu = findobj( 'tag', 'XAxisMenu' );
      set( XAxisMenu, 'string', header );

      YAxisMenu = findobj( 'tag', 'YAxisMenu' );
      set( YAxisMenu, 'string', header );

    % Also store headers and data as GuiWindow app data, in case we need them again later.
      setappdata( GuiWindow, 'header', header );
      setappdata( GuiWindow, 'Data'  , Data   );

    % Plot a preliminary plot in the plot area
      XData = Data(:, 1);
      YData = Data(:, 1);
      plot( XData, YData, 'tag', 'plotobject' );          
  endfunction

  %% 2. X Axis Information from excel data import
  function popupmenuX_Callback( hObject, eventdata, GuiWindow )
      Axes      = findobj( 'tag', 'plotarea' );
      Selection = get( hObject, 'value' );
      XData     = [ getappdata( GuiWindow, 'Data' )( :, Selection ) ];
      PlotObj   = findobj( 'tag', 'plotobject' );
      set( PlotObj, 'xdata', XData )
  endfunction

  %% 3. Y Axis Information from excel data import
  function popupmenuY_Callback( hObject, eventdata, GuiWindow )
      Axes      = findobj( 'tag', 'plotarea' );
      Selection = get( hObject, 'value' );
      YData     = [ getappdata( GuiWindow, 'Data' )( :, Selection ) ];
      PlotObj   = findobj( 'tag', 'plotobject' );
      set( PlotObj, 'ydata', YData )
  endfunction
Heewonny
  • 25
  • 6
  • You're welcome! If you are satisfied with your answer, do mark it as correct; this marks the question as answered in the main screen (and is treated differently when searching on the site). – Tasos Papastylianou Jul 29 '21 at 13:35
0

The line

fileName = fileName @pushbutton_Callback; 

doesn't do what you think it does.

It's a bit complicated to explain the background, but basically in matlab, new-style classes created with the classdef keyword, which also allow inheritance, allow you to call a method of a 'parent' class (or "superclass") via the methodname@parentclassname(args) syntax. Octave has ported this system to octave too, for matlab compatibility. The error you get effectively says you're trying to call a superclass method, in a context where it doesn't make sense (which is true, since you're not inside a classdef block).

This explains why you get that error.

Now, in terms of what you're trying to do, I think you basically just want to call the pushbutton_Callback function from within your popupmenuX_Callback one, right? So just do that, with appropriate arguments, e.g.:

filename            = pushbutton_Callback(hObject, eventdata, handles)
[numbers, colNames] = xlsread(fileName);

PS. I would recommend you always indent code inside functions. It looks clearer and helps catch bugs!

Tasos Papastylianou
  • 21,371
  • 2
  • 28
  • 57
  • Thank you for your advice @Tasos. Because I'm new in Octave, I didn't know what can I do. Base from what you've mentioned, I tried to put 'classdef' into my code. But it doesn't not work and always occurs parse error. [link](https://stackoverflow.com/questions/68525844/parse-error-subclass-and-classdef-in-octave) here I've uploaded my errors. I'd like to appreciate, if you could also read this question. Thanks Tasos!! – Heewonny Jul 26 '21 at 07:20
  • Right. Forget about classdef, and ignore the first part of my answer. I was just trying to explain why you see that particular error message. Sorry, I didn't mean to confuse you. Just focus on the last paragraph. – Tasos Papastylianou Jul 26 '21 at 08:48
  • basically replace `fileName = fileName @pushbutton_Callback;` with `filename = pushbutton_Callback(hObject, eventdata, handles);` – Tasos Papastylianou Jul 26 '21 at 08:49
  • Also, it sounds like you have more basic problems, relating to what is a function handle, how to use function handles of a particular signature as callbacks, and how to use this to make gui programs. This is more than can be covered in a stackoverflow answer ... have a look at [this simple gui program](https://stackoverflow.com/a/43536882/4183191) as an example to get you started with gui programming on octave. – Tasos Papastylianou Jul 26 '21 at 08:52
  • Thank you again Tasos, Replacing `fileName = fileName @pushbutton_Callback;` with `filename = pushbutton_Callback(hObject, eventdata, handles);`I tried that also but then, it seems that handles is undefined. `>> fileName = V8.xlsx error: 'handles' undefined near line 62, column 62 error: called from popupmenuX_Callback at line 62 column 21 `. – Heewonny Jul 26 '21 at 09:05
  • And you're right. I have problem with function handle... the examples that you linked, I saw already. But I can't understand how I apply in my case, because in my case, I should have to import excel data and use mind. two functions. But I'll try to solve it, thanks! – Heewonny Jul 26 '21 at 09:18
  • @Heewonny this sounds like a problem with how you "call" the callback function. Read the [relevant section in the manual](https://octave.org/doc/v6.3.0/Callbacks.html); effectively all callbacks expect the first two arguments, and any extra arguments need to be passed separately. So, e.g., if you're assigning this callback to a button ui element, it would look something like this: `uicontrol( 'style', 'pushbutton', 'callback', { @popupmenuX_Callback, handles } )` – Tasos Papastylianou Jul 26 '21 at 19:51
  • Thanks for everytime @Tasos ! Yes, I looked at that [site](https://stackoverflow.com/questions/43519040/how-to-code-a-slider-in-octave-to-have-interactive-plot/43536882#43536882), what you mentioned last time. And in order to return my callbacks, I know that I should have to use `gcbo` something like that. But I'm not sure, in which Situation or codes should I have to use it.... so I edit my question and when you have a free time, I would be glad, if you see my edited questions with full codes. Anyway thanks again. – Heewonny Jul 28 '21 at 07:52
  • @Heewonny Your code looks a bit weird to me. What are you trying to achieve? E.g., you have the X-Axis popupmenu: what do you want to happen when you select an item from the menu? It's a bit weird that you're setting up the X-Axis popupmenu to launch the file-selection dialog. Why isn't that the job of "Excel Datei Mitbringen" button exclusively? – Tasos Papastylianou Jul 28 '21 at 10:10
  • Thank you Tasos, I'd like to make GUI like [this](https://de.mathworks.com/videos/reading-excel-data-into-matlab-with-a-gui-part-3-98226.html) in Octave. I tried to make, if I click popupmenu X or Y, then I can choose the columns from excel. And with this values from Columns that I choosed, I can get graph from that. That was my goal. And according to this [video](https://de.mathworks.com/videos/reading-excel-data-into-matlab-with-a-gui-part-3-98226.html), it was seperatly pushbutton and popupmenu. – Heewonny Jul 28 '21 at 10:27
  • And yes I also tried to put all the callbacks in one button and use switch function like [this](https://wiki.octave.org/Uicontrols). But if I use this function, it appears error `error: matrix can not be indexed with`. – Heewonny Jul 28 '21 at 10:32
  • Ok, still a bit confused, but I've provided an example below as a separate answer of what I think you may be trying to do. (I don't have access to Excel on my machine, so the example uses a simple csv file instead -- but the principle should be the same) – Tasos Papastylianou Jul 28 '21 at 11:49