1

With Guide I made a Matlab Gui that have 10 Axes in which i want to display images, in all of them at once, after i press a Button.

I made a separate .m file with function Load_Write_Img_Results(img_index) that i call from the Button Callback which have the following code:

for i = 1 : 10
    handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]);
    set(handles_imgOut, 'HandleVisibility', 'ON');
    axes(handles_imgOut);
    image(imgs_data{img_index(i)});
    ...
end

Every time when i run the main Gui and press the button for the first time, images are displayed in all axes, so everything works ok.


The problem appear when i press the button for the second time and i get this error:

    Error using axes  
    Invalid object handle

on this line:

    axes(handles_imgOut);

When debugging, i saw that after handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]); the handles_imgOut is not getting any value and is empty, so it's obvious that error.

Is there any chance i can't get handles for axes at the second press of the button?

Also, i want to know how can i solve this warning from Matlab:

Calling AXES(h) in a loop can be slow. Consider moving the call to AXES outside the loop.

Thanks in advance, any suggestions are welcome!


[SOLUTION]:

for i = 1 : 10
    handles_imgOut = findobj('Tag', ['imgOut' num2str(i)]);
    set(handles_imgOut, 'HandleVisibility', 'ON');
    axes(handles_imgOut);
    image(imgs_data{img_index(i)});

    set(gca, 'Tag', ['imgOut' num2str(i)]); //! renew the tag
    ...
end
asawyer
  • 17,642
  • 8
  • 59
  • 87
Florin Vîrdol
  • 395
  • 2
  • 10
  • 28
  • Please, whoever down-voted this question, i ask to justify his/her action!! Thanks. – Florin Vîrdol May 30 '12 at 23:58
  • Off the top of my head, one reason that axes can become invalidated is if another set of axes overlaps it. This may cause the handle to become invalid, or (in your case) fail to be found using `findobj` the second time around. I suggest adding stepping through in a debugger and checking to see at each iteration whether `findobj` for all of your different axes works properly. – tmpearce May 31 '12 at 00:17
  • @tmpearce After i press the button for the first time, `findobs` works properly in the ten iterations and images are displayed correctly in axes. As i mentioned, the error occurs after the second press, where `findobj` does not return anything from the first iteration. – Florin Vîrdol May 31 '12 at 00:31
  • Right... my question is, when does the invalidation happen? If you try and find the first object (`imgOut1`) when i=2 or i=3 on the *first loop through - the first button press* - is it still valid in those cases? – tmpearce May 31 '12 at 00:35
  • @tmpearce I'm not sure if i understood your question exactly... The invalidation happens when trying to assign `axes(handles_imgOut); ` at the second button press -> first iteration (`i = 1`) because `findobj` does not find `imgOut1`. (iteration `i` corresponds to the `i`-th axes named `imgOut i`) – Florin Vîrdol May 31 '12 at 00:52
  • I'm asking whether the axes for `imgOut1` gets invalidated earlier than you realize: sometime during the first button click loop. When you click again, the axes object is invalid; but that doesn't tell you exactly *when* it was invalidated. – tmpearce May 31 '12 at 01:01
  • @tmpearce I now understood what you asked. During the first button click loop `findobj` finds all the axes and display in them the corresponding images. But, at first iteration from second button click - when i want to update the axes `imgOut1` to display other image, `findobj` doesn't find `imgOut1`.. – Florin Vîrdol May 31 '12 at 01:21
  • @FlorinVîrdol, please add your solution as answer to yourself. You can accept it as well. – Andrey Rubshtein May 31 '12 at 09:14

2 Answers2

1

I'm fairly new to GUIDE and I've encountered similar problems, with the graph not being updated more than once / axes not found. In the end, I used the following approach, which I hope can be useful to you too:

    % I get my axes directly from the handles object, instead of using findObj:
        graph1 = handles.axes1;
        graph2 = handles.axes2;
    % clear axes
        cla(graph1);
        cla(graph2);
    % showTrial is my function that draws the graphs - 
    %notice that I used handles to store other variables as well (.data, .trials)
    showTrial(handles.data, handles.trials(1), graph1, graph2)

To sum it up:

  • don't use findObj, get your axes from handles (it should automatically contain them as imgOut1,imgOut2, etc.)

  • pass the axes to your drawing function or pass directly the handles variable e.g. Load_Write_Img_Results(img_index, handles)

BlueCoder
  • 293
  • 5
  • 13
0

The fact that it works on the first button press, but not thereafter hints that

image(imgs_data{img_index(i)});

opens new axes instead of drawing into the existing ones. Since the new axes are not initialized with your tags, findobj will not find them. Either

(1) make sure to hold the original axes by placing a hold on command right after their creation,

or

(2) renew the tag right after the image command by

set(gca, 'Tag', ['imgOut' num2str(i)]);
H.Muster
  • 9,297
  • 1
  • 35
  • 46
  • Thanks a lot! I used your second suggestion (`set(gca, 'Tag', ['imgOut' num2str(i)]);` after `image(...)` command) and works like a charm - it's updating axes with new images! First suggestion (using `hold on` after `axes(...)` command) doesn't resolve my problem, because previous images remain displayed and next images are overlapping.. – Florin Vîrdol May 31 '12 at 09:05
  • For the latter case, you would use `cla` before drawing a new image. This would still leave the tags intact. – H.Muster May 31 '12 at 09:35
  • As you suggested, putting commands `hold on; cla;` after `axes(...)` command, images are updated within axes and not overlapping anymore, **BUT** all of them are **displayed upside down** in axes. – Florin Vîrdol May 31 '12 at 11:32
  • The `image` command normally sets the y axis direction to `reverse`, which it does not when plotting in an existing subplot. Use `set(gca, 'ydir', 'reverse');` right after the `hold on` command to solve this. – H.Muster May 31 '12 at 11:47