I'm creating a tool for our engineering team to view data coming off our systems in the field. The underlying data isn't critical to it. Basically, it consists of vectors containing Y data at X time.
I'm plotting a series of vectors using subplot. Each plot has the ButtonDownFcn defined to launch a window that allows for deeper analysis. The problem is that when I click on the axes in the deployed application, nothing happens. There are no error messages or anything. When I click on the axes running it in Matlab, it works exactly as expected.
I'm not sure what's going on once the code is deployed that is preventing it from functioning properly. I'm a little lost on where to go. I've included my code and some sample data.
Test Data:
stats = struct('name','Car 54', ...
'date', '11-Aug-2014');
stats.SOC = struct('time', linspace(1,24,100)*3600', ...
'plugdata', [100*ones(20,1); NaN(70,1); (20:4:56)'], ...
'drivedata', [NaN(20,1); (100:-2:60)'; NaN(10,1); (40:-2:20)'; NaN(20,1); (30:-2:16)'; NaN(10,1)], ...
'eptodata', [NaN(41,1); (58:-2:40)'; NaN(11,1); (18:-2:5)'; NaN(13,1); NaN(7,1); NaN(11,1)], ...
'engchargedata', [NaN(69,1); (5:2:30)'; NaN(18,1)], ...
'otherdata', NaN(100,1));
Code:
function [output] = summarytablepopup(stats)
FH = figure('Name','Summary Table Popup', ...
'Units', 'normalized', ...
'Position', [0.05 0.05 0.9 0.8], ...
'Tag', 'sumTablePU', ...
'Toolbar', 'none', ...
'NumberTitle', 'off', ...
'WindowStyle', 'normal', ...
'Resize', 'on', ...
'CloseRequestFcn', #closereq, ...
'MenuBar', 'none', ...
'UserData', {});
movegui(FH,'onscreen')
noStats = numel(stats);
screensize = get(0,'ScreenSize');
mapIMG = imread([pwd '\icons\map.jpg']);
noGraphs = 5;
AH = NaN(noStats,1); % axes handles
TT = NaN(noStats,1); % name text handles
MB = NaN(noStats,1); % map button handles
TH = NaN(ceil(noStats/noGraphs),1); % tab handles
warning('off','all')
TGH = uitabgroup('Parent',FH); % tab group handle
for ii = 1:length(TH)
TH(ii) = uitab('parent',TGH,'title',sprintf('Page %d',ii));
end
warning('on','all')
for ii = 1:noStats
currentPage = ceil(ii/noGraphs);
vehiclename = stats(ii).name;
vehicledate = stats(ii).date;
if isfield(stats(ii),'SOC') && ~isempty(stats(ii).SOC) && isfield(stats(ii).SOC,'time') && ~isempty(stats(ii).SOC.time)
SOC = stats(ii).SOC;
time = SOC.time/3600;
subplot(5,1,mod(ii-1,noGraphs)+1,'Parent',TH(currentPage))
HH = plot(time, SOC.plugdata, 'g-x', ...
time, SOC.eptodata, 'b-x', ...
time, SOC.engchargedata, 'b-x', ...
time, SOC.drivedata, 'r-x', ...
time, SOC.otherdata, 'k-x');
AH(ii) = get(HH(1),'Parent');
set(HH,'Marker','.')
set(HH(3),'Color',[0 0.75 1])
set(HH(3),'MarkerFaceColor',[0 0.75 1])
else
subplot(5,1,mod(ii-1,noGraphs)+1,'Parent',TH(currentPage))
HH = plot([0 12 24],[NaN NaN NaN]);
AH(ii) = get(HH(1),'Parent');
%}
end
pos = get(AH(ii),'Position');
pos(1) = 0.25;
pos(3) = 0.72;
set(AH(ii),'Position',pos)
set(AH(ii),'UserData', ii)
set(AH(ii),'ButtonDownFcn', #divedeep)
set(AH(ii),'YLim',[0 100])
set(AH(ii),'YTick',[0 25 50 75 100])
set(AH(ii),'YTickLabel',{'0','25','50','75','100'})
set(AH(ii),'XLim',[0 24])
set(AH(ii),'XTick',[0 4 8 12 16 20 24])
set(AH(ii),'XTickLabel',{'0000','0400','0800','1200','1600','2000','2400'})
mapHeight = 0.1;
mappos = [0.18 pos(2)+pos(4)/2-mapHeight/2 mapHeight*screensize(4)/screensize(3) mapHeight];
MB(ii) = uicontrol('Parent', TH(currentPage), 'Style', 'pushbutton', ...
'Tag', sprintf('mapButton%d',ii), ...
'String', '', ...
'Units', 'normalized', ...
'Position', mappos, ...
'CData', mapIMG, ...
'Callback', #mapbutton);
if isfield(stats(ii),'location') && ~isempty(stats(ii).location) && isfield(stats(ii).location,'time') && ~isempty(stats(ii).location.time)
set(MB(ii),'Enable','on')
else
set(MB(ii),'Enable','off')
end
textHeight = 0.05;
textpos = [0.01 pos(2)+pos(4)/2-textHeight/2 0.15 textHeight];
TT(ii) = uicontrol('Parent', TH(currentPage), 'Style', 'text', ...
'Tag', sprintf('text%d',ii), ...
'String', vehiclename, ...
'FontSize', 12, ...
'Units', 'normalized', ...
'Position', textpos);
end
uiwait(FH)
function mapbutton(source, event)
tag = get(source,'Tag');
splittag = strsplit(tag,'n');
jj = str2num(splittag{2});
loc = stats(jj).location;
if ~isempty(loc)
len = numel(loc.time);
map = [linspace(1,0,len)', linspace(0,1,len)', zeros(len,1)];
MFH = figure;
MPH = plot(loc.lon, loc.lat, 'r:');
hold on;
MSH = scatter(loc.lon, loc.lat, 50, 'o', 'filled', 'CData', map);
plot_google_map
else
msgbox('No location information available for this vehicle. Really should disable this button.')
end
end
function electric(source, event)
ratio = get(SH,'Value')/100*(0.9-startheight)+0.05;
set(PH, 'Position', [panpos(1) ratio panpos(3) panpos(4)])
end
function divedeep(source, event)
HEDtimeplot([],stats(get(source,'UserData')));
end
function closereq(source,event)
uiresume(source)
delete(source)
end
end
Related
I have been trying to plot two images side by side with two sliders using uicontrol. I am relatively new to uicontrol using matlab. Only the second subplot updates when I change the slider.
close all;
clear all;
clc;
set(0,'defaultAxesFontSize',14)
set(0,'DefaultFigureWindowStyle','docked')
data = rand(3,1024,64,20);
nslice = size(data,4);
nidx = size(data,1);
if nslice == 1
sampling = 1; % in some of my data nslice would be 1 so I would like my slider to not give me error in such a case
else
sampling = 5;
end
idx = 1;
slice = 1;
h.f = figure(1);
x_axis = linspace(0,0.5,size(data,3));
y_axis = linspace(0,70,size(data,2));
set(h.f,'doublebuffer','on')
h.data = data;
inst_data = squeeze(data(nidx,:,:,slice));
h.ax(1) = subplot(1,2,1,'Parent',h.f,'Units','Normalized');
imagesc(h.ax(1),x_axis,y_axis, inst_data)
colorbar;
colormap(h.ax(1),'gray')
caxis(h.ax(1),[min(abs(inst_data(:))),max(abs(inst_data(:)))])
xlabel('xaxis')
ylabel('yaxis')
title('figure 1')
h.ax(2) = subplot(1,2,2,'Parent',h.f,'Units','Normalized');
log_data = log(inst_data);
imagesc(h.ax(2),x_axis,y_axis, log_data)
colorbar;
colormap(h.ax(2),'jet')
caxis(h.ax(2),[-max(abs(log_data(:))),max(abs(log_data(:)))])
xlabel('xaxis')
ylabel('yaxis')
title('figure 2')
sgtitle({'Sample data ', ['Slice: ',num2str(slice),' index: ', num2str(idx)]},'FontSize',16,'FontWeight','Bold')
h.slider1=uicontrol('Parent',h.f,...
'Units','Normalized',...
'Position',[0.1 0.06 0.8 0.05],...
'Style','slider',...
'SliderStep',[1,sampling],...
'Min',1,'Max',nslice,'Value',1,...
'Callback',{#slider_Callback,data,x_axis,y_axis});
txt1 = 'Slice';
txt2 = 'Index';
annotation('textbox', [0.05 0.07 0.05 0.04], 'string', txt1);
annotation('textbox', [0.05 0.021 0.05 0.04], 'string', txt2);
h.slider2=uicontrol('Parent',h.f,...
'Units','Normalized',...
'Position',[0.1 0.02 0.8 0.05],...
'Style','slider',...
'SliderStep',[1,1],...
'Min',1,'Max',nidx,'Value',1,...
'Callback',{#slider_Callback,data,x_axis,y_axis});
guidata(h.f,h)
%%
function slider_Callback(hObject,eventdata,data,x_axis,y_axis)%#ok<INUSD>
h=guidata(hObject);%retrieve struct
slice_i = round(get(h.slider1, 'Value'));
idx_i = round(get(h.slider2,'Value'));
inst = squeeze(data(idx_i,:,slice_i));
colorbar;
colormap(h.ax(1),'gray')
caxis(h.ax(1),[min(abs(inst(:))),max(abs(inst(:)))])
h.ax(1) = imagesc(x_axis,y_axis,inst); colorbar
lg = log(inst);
colorbar;
colormap(h.ax(2),'jet')
caxis(h.ax(2),[-max(abs(lg(:))),max(abs(lg(:)))])
h.ax(2) = imagesc(x_axis,y_axis, lg ); colorbar;
sgtitle({'Sample data ', ['Slice: ',num2str(slice_i),' index: ', num2str(idx_i)]},'FontSize',16,'FontWeight','Bold')
drawnow
end
Other problems include:
The slider slides with a floating value which shouldnt be the case
When my data has only 1 slice, the slider moves to value zero which shouldn't happen. You can try the same example with data = rand(3,1024,64,1);
The code below works. You can copy-paste this code in case you don't understand what I ask below.
In my gui, I have a pushbutton, popupmenu and edittext. Pushbutton enables adding new strings to popupmenu with the answers obtained from inputdlg. The strings in popupmenu have additional information which is defined in windowType function. When scrolling between popupmenu list, pmh_call calls windowType function and displays the information on edittext. The information on windowType function is predefined. However, what I want is to add new window types and information to this function. This is the first time I develop a GUI. So, I may have started this saving new info business to a function all wrong. Any help is appreciated.
function [] = mygui(varargin)
S.fh = figure('Visible','on','numbertitle','off','Name','Gunebakan GUI',...
'units','pixels','Position',[500 500 200 100]);
S.pbh_definewindow = uicontrol(S.fh,'Style','pushbutton','String','Define window',...
'HorizontalAlignment','center','BackgroundColor',[0.6602 0.0234 0.2539],...
'Position',[10 80 100 20]);
S.pmh_window = uicontrol(S.fh,'Style','popupmenu','String',{'Type1','Type2'},...
'Value',1,'BackgroundColor','w','Position',[10 50 150 18]);
S.eth_windowlength = uicontrol(S.fh,'Style','edit','String','4','Position',[10 10 50 20]);
set(S.pbh_definewindow,'callback',{#pbh_call,S});
set(S.pmh_window,'callback',{#pmh_call,S});
function [] = pmh_call(varargin)
S = varargin{3};
string = get(S.pmh_window,{'String','Value'});
string = string{1}(string{2});
[ windowtypeinfo ] = windowType( string );
str = num2str(windowtypeinfo.length);
set(S.eth_windowlength,'String',str);
function [] = pbh_call(varargin)
S = varargin{3};
error = 1;
prompt = {'Type name:','Type length:'};
name = 'Yeni Agac Tanimlama';
numlines = 1;
defaultanswer = {'benimagacim','2'};
answer = inputdlg(prompt,name,numlines,defaultanswer);
options.Resize = 'on';
options.WindowStyle = 'normal';
options.Interpreter = 'tex';
q = get(S.pmh_window,'String');
error = 1;
while error == 1
if ~any(strcmpi(answer{1},q))
error = 0;
else
answer(1) = inputdlg('Type name already used, enter another!')
error = 1;
end
end
P = get(S.pmh_window,{'string','value'});
q(length(q)+1) = answer(1);
set(S.pmh_window,'string',q);
function [ windowtypeinfo ] = windowType( string )
if strcmpi(string,'Type1')
windowtypeinfo.typename = 'Type1';
windowtypeinfo.length = 4;
elseif strcmpi(string,'Type2')
windowtypeinfo.typename = 'Type2';
windowtypeinfo.length = 5;
end
The question isn't really well posed but I think I understand what you're asking. To answer your final thought, I would say there is a better way to store your data. Consider the following simplified example:
function testgui
% Initialize GUI
h.myfig = figure;
h.mybutton = uicontrol( ...
'Style', 'pushbutton', ...
'Units', 'normalized', ...
'Position', [0.15 0.70, 0.70 0.15], ...
'String', 'Add Style' ...
);
h.mymenu = uicontrol( ...
'Style', 'popupmenu', ...
'Units', 'normalized', ...
'Position', [0.15 0.50 0.70 0.10], ...
'String', ' ' ...
);
h.myedit = uicontrol( ...
'Style', 'edit', ...
'Units', 'normalized', ...
'Position', [0.15 0.15 0.70 0.10], ...
'String', ' ' ...
);
set(h.mybutton, 'callback',{#addwindow, h});
set(h.mymenu, 'callback',{#changewindow, h});
% Initialize data structure
mydata(1).typename = 'Type1';
mydata(1).windowlength = 4;
mydata(2).typename = 'Type2';
mydata(2).windowlength = 5;
updatepopup(mydata, h);
% Set initial editbox value
set(h.myedit, 'String', mydata(1).windowlength);
% Store data for later
guidata(h.myfig, mydata);
end
function updatepopup(mydata, h) % Update strings in popup menu based on data array
typenames = {mydata.typename}; % Collect all the existing typenames
set(h.mymenu, 'String', typenames); % Update popup menu
end
function addwindow(~, ~, h) % Prompt user to add window
prompt = {'Type name:','Type length:'};
name = 'myprompt';
nlines = 1;
defaultanswer = {'asdf', '1'};
myanswer = inputdlg(prompt, name, nlines, defaultanswer);
% Prepare new information for storage
newwindow.typename = myanswer{1};
newwindow.windowlength = str2double(myanswer{2});
mydata = guidata(h.myfig); % Pull in existing data
mydata = [mydata newwindow]; % Add new data to existing data
updatepopup(mydata, h); % Update popup menu
guidata(h.myfig, mydata); % Store data for later
end
function changewindow(~, ~, h) % Update editbox based on popup menu selection
mydata = guidata(h.myfig); % Pull in stored data
windowselected = get(h.mymenu, 'Value'); % Get index of window selected
set(h.myedit, 'String', mydata(windowselected).windowlength); % Change editbox
end
Rather than manually getting your window type with a separate function (windowType() in your example), I would try storing your data in the GUI as a data structure and pulling it out as necessary. This allows you to use more generalized code and not have to think about how to handle every case with the loop you have now. Hopefully this is easy to follow and adapt to your needs.
You should use guide in order to easily develop GUI's in MATLAB. If you do, you will find that each element in your GUI is called by a handles.something.
For example:
Lets say that you want to add the string in the inputdlg to your popup menu, you should do something like this:
set(handles.popupMenu,'String',[predefStrings; get(handles.inputdlg,'String')]);
The 'String' argument in a popup menu must be an array of strings.
I have written the following code the plot the height of water in a tank vs. time.
A_t = 16;
[h1, t1] = update_plot(A_t);
f = figure;
h = plot(t1, h1);
b = uicontrol('Parent',f,'Style','slider','Position',[81,54,419,23], 'value',A_t, 'min',14, 'max',17);
bgcolor = f.Color;
set(b,'Callback',#(es,ed) updateSystem(h,update_plot((es.Value))))
The function to update the h (height of water) and t (time) vectors is:
function [h1, t1] = update_plot(A_t)
t = 0:0.01:100;
h = zeros(1, length(t));
h_init = 20;
t_0 = 0;
myeps = 1e-5;
i = 1;
h(1) = h_init;
while h(i) > myeps
i = i + 1;
h(i) = (sqrt(h_init) - (0.18/A_t)*sqrt(981/2)*(t(i) - t_0))^2;
h1 = h(1:i);
t1 = t(1:i);
end
The parameter A_t is the variable for which I want to use a slider.
I cannot get the callback function to work.
I want the plot to be updated as I move the slider.
You can try this:
set(b,'Callback', #slider_callback);
function slider_callback(hObject, callbackdata)
A_t = num2str(hObject.Value);
update_plot(A_t);
end
Then you would also have to clear your figure with cla and use plot with the update values.
I got it working. The modified code and functions are:
function[f] = update_plot(A_t)
t = 0:0.01:100;
h = zeros(1, length(t));
h_init = 20;
t_0 = 0;
myeps = 1e-5;
i = 1;
h(1) = h_init;
while h(i) > myeps
i = i + 1;
h(i) = (sqrt(h_init) - (0.18/A_t)*sqrt(981/2)*(t(i) - t_0))^2;
h1 = h(1:i);
t1 = t(1:i);
end
f = plot(t1, h1);
legend('Measured', 'Tuned')
grid on
The callback function is:
function change_plot(objHandle, ~)
slider_value = get(objHandle, 'Value');
new_A_t = slider_value;
update_plot(new_A_t);
And the main function is:
A_t = 15.5;
ff = figure;
axes('Parent',ff, 'units', 'normalized',...
'position',[0.05 0.15 0.9 0.8])
update_plot(A_t);
b = uicontrol('Parent',ff,'Style','slider',...
'value',A_t, 'min',14, 'max',17,...
'units', 'normalized',...
'position', [0.33 0 0.4 0.1],...
'SliderStep', [0.001 0.1],...
'callback', #change_plot);
disp_h = uicontrol('style', 'edit',...
'units', 'normalized',...
'position', [0.15 0.05 0.15 0.05]);
bgcolor = ff.Color;
Now I want to display the value of the slider in the 'edit' box I've created, but so far have been unable to get it to work.
I made a GUI that gets 2 elements: files (list of files) and options (I will explain later).
there is a function that calls the function below:
// asume that this is my 'options'
options{1} = {'Treatment', 't1', 't2'};
options{2} = {'Tree', '1', '2'};
options{3} = {'Replica', 'r1', 'r2', 'r3'};
// asume that this is my 'files' (may be more than 2 images
files{1} = 'C:\Documents and Settings\erezalon\Desktop\gib_proj_02.10.12\fina3_32bit\IMG_4640.JPG';
files{2} = 'C:\Documents and Settings\erezalon\Desktop\gib_proj_02.10.12\fina3_32bit\grapes03.jpg';
mydata = mainGUI(options, files).
// here I want to check 'mydata'. if it is equal to zero or not.
for each image, the GUI is created in the function 'mainGUI' (but each time, one GUI is showed till the user presses 'next').
I want to do the next thing:
if the user presses the close button in the GUI, I want to stop the displaying of the other GUI-s and set 'data = 0'. then, I will check what is the returned element ('mydata') and if it's equal to 0, I will know that the user closed the GUI and I will act as needed.
I tried to do this by the 'cmdClose_Callback' but it doesn't work.
assume that 'files' = two images, so this is the GUI of the first image.
I press the close button:
and got the GUI of the second image despite of closing the GUI of the first image.
I want that when I close the GUI, the other GUI-s don't appear.
this is my code:
function data = mainGUI(options, files)
%# current options
j = 1;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
data{j} = [ops{1:length(ops)}];
j = j + 1;
options = cellfun(#(c) c(2:1:end), options, 'Uniform',false);
clear ops;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
opts = [ops{1:length(ops)}];
%# create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
a = 1
callback
%# options button callback function
function callback(o,e)
a = 2
%# save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
%# display options dialog and wait for it
for k=1: length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
img = imread(files{k}); %# Read the data from image file data
hAxes = axes('Parent',hOptsGUI,'Units','pixels','Position',[362 242 424 359]); %# so the position is easy to define
image(img,'Parent',hAxes); %# Plot the image
set(hAxes,'Visible','off'); %# Turn the axes visibility off
a = 3
waitfor(hOptsGUI);
a = 4
%# get new options, and update plot accordingly
opts = getappdata(hFig, 'opts');
data{j} = opts;
j = j + 1;
end
end
end
function hFig = secondaryGUI(hParentFig, options, k, num_files)
%# create figure
a = 5
hFig = figure('Name','Step 3 of 4: Choose data for each image','Menubar','none', 'Resize','off', ...
'WindowStyle','modal', 'Position',[300 300 1150 600], 'CloseRequestFcn',#cmdClose_Callback);
set(gcf,'NumberTitle','off')
movegui(hFig, 'center');
options = cellfun(#(c) c(end:-1:1), options, 'Uniform',false);
num = length(options);
%# get saved settings
selected = getappdata(hParentFig, 'opts');
a = 6
%# top/bottom panels
hPanBot = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.0 1 0.2]);
hPanTop = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.2 1 0.2]);
%# buttongroups in top panel
hBtnGrp = zeros(1,num);
width = 1/num;
for i=1:num
%# create button group
hBtnGrp(i) = uibuttongroup('Parent',hPanTop, ...
'Units','normalized', 'Position',[(i-1)*width 0 width 1]);
%# populate it with radio buttons
height = 1./numel(options{i});
for j=1:numel(options{i})
h = uicontrol('Parent',hBtnGrp(i), 'Style','Radio', ...
'Units','normalized', 'Position',[0.05 (j-1)*height 0.9 height], ...
'String',options{i}{j});
%# set initially selected values
if strcmp(selected{i},options{i}{j})
set(hBtnGrp(i), 'SelectedObject',h)
end
end
end
if k ~= num_files
%# save button in bottom panel
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','next', 'Callback',#callback);
else
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','start', 'Callback',#callback);
end
%# save button callback function
function callback(o,e)
a = 7
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
close(hFig)
a = 8
end
function cmdClose_Callback(hObject,varargin)
disp(['Close Request coming from: ',get(hObject,'Type')]);
a = 9
%do cleanup here
delete(hFig);
a = 10
end
end
if 'files' has two images, I push the 'next' button for the first figure, and in the second figure I close, I get:
a = 1
a = 2
a = 5
a = 6
a = 3
a = 7
Close Request coming from: figure
a = 9
a = 10
a = 8
a = 4
a = 5
a = 6
a = 3
Close Request coming from: figure
a = 9
a = 10
a = 4
above the line: hOptsGUI = secondaryGUI(hFig, options, k, length(files));
I tried to put some lines. In order to testthe lines, I print a fit message:
if (ishandle(hFig))
disp('exists');
else disp('was closed');
end;
but it doesn't work :/
for each GUI that the user will close, the next callback will called:
function callback(o,e)
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
%# close options dialog
close(hFig)
end
so I just need to know in the next 'for loop' if this callback was called:
for k=1: length(files)
how can I do that?
Just check to see if hFig1 is a valid handle before you create the second figure.
if ishandle(hFig1)
hFig2 = figure(...)
else
return; % do something else
end
Repeat as needed.
function data = mainGUI(options, files)
% ...
% create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
complete = callback;
if complete == 1
data = data;
else
data = 0;
end
% options button callback function
function complete = callback(o,e)
%save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
% display options dialog and wait for it
complete = 0;
for k = 1 : length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
% ...
end
% we reached the end of the loop!
complete = 1;
end
I succeeded!
I used setappdata and getappdata in order to know if the second callback was called.
#Derek, Derek, thank you very much for your help and that you spent a lot of time for me!
function data = mainGUI(options, files)
%# current options
j = 1;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
data{j} = [ops{1:length(ops)}];
j = j + 1;
options = cellfun(#(c) c(2:1:end), options, 'Uniform',false);
clear ops;
ops = cellfun(#(c) c(1), options, 'Uniform',false);
opts = [ops{1:length(ops)}];
%# create main figure, with plot and options button
hFig = figure('Name','window 1','Visible','Off');
callback
%# options button callback function
function callback(o,e)
%# save current options (sharing data between the two GUIs)
setappdata(hFig, 'opts',opts);
%# display options dialog and wait for it
for k=1: length(files)
hOptsGUI = secondaryGUI(hFig, options, k, length(files));
img = imread(files{k}); %# Read the data from your image file
hAxes = axes('Parent',hOptsGUI,'Units','pixels','Position',[362 242 424 359]); %# so the position is easy to define
image(img,'Parent',hAxes); %# Plot the image
set(hAxes,'Visible','off'); %# Turn the axes visibility off
out = 'FALSE';
setappdata(hFig,'some_var',out);
% show the images
%%Im = imread(files{k});
%%AxesH = axes('Units', 'pixels', 'position', [0.5, 10, 400, 260], 'Visible', 'off');
%%image('Parent', AxesH, 'CData', Im); %# add other property-value pairs as needed
waitfor(hOptsGUI);
some_other_var = getappdata(hFig,'some_var');
if (strcmp(some_other_var, 'OK') == 1)
%# get new options, and update plot accordingly
opts = getappdata(hFig, 'opts');
data{j} = opts;
j = j + 1;
else
k = length(files);
data = 0;
return;
end;
end
end
end
function hFig = secondaryGUI(hParentFig, options, k, num_files)
%# create figure
hFig = figure('Name','Step 3 of 4: Choose data for each image','Menubar','none', 'Resize','off', ...
'WindowStyle','modal', 'Position',[300 300 1150 600]);
set(gcf,'NumberTitle','off')
movegui(hFig, 'center');
options = cellfun(#(c) c(end:-1:1), options, 'Uniform',false);
num = length(options);
%# get saved settings
selected = getappdata(hParentFig, 'opts');
%# top/bottom panels
hPanBot = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.0 1 0.2]);
hPanTop = uipanel('Parent',hFig, 'BorderType','none', ...
'Units','normalized', 'Position',[0 0.2 1 0.2]);
%# buttongroups in top panel
hBtnGrp = zeros(1,num);
width = 1/num;
for i=1:num
%# create button group
hBtnGrp(i) = uibuttongroup('Parent',hPanTop, ...
'Units','normalized', 'Position',[(i-1)*width 0 width 1]);
%# populate it with radio buttons
height = 1./numel(options{i});
for j=1:numel(options{i})
h = uicontrol('Parent',hBtnGrp(i), 'Style','Radio', ...
'Units','normalized', 'Position',[0.05 (j-1)*height 0.9 height], ...
'String',options{i}{j});
%# set initially selected values
if strcmp(selected{i},options{i}{j})
set(hBtnGrp(i), 'SelectedObject',h)
end
end
end
if k ~= num_files
%# save button in bottom panel
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','next', 'Callback',#callback);
else
uicontrol('Parent',hPanBot, 'Style','pushbutton', ...
'Units','normalized', 'Position',[0.3 0.2 0.4 0.2], ...
'String','start', 'Callback',#callback);
end
%# save button callback function
function callback(o,e)
out = 'OK';
setappdata(hParentFig,'some_var',out);
%# get selected values
hObjs = get(hBtnGrp(:), 'SelectedObject');
vals = get(cell2mat(hObjs),{'String'});
%# update settings
setappdata(hParentFig, 'opts',vals);
%# close options dialog
close(hFig)
end
function cmdClose_Callback(hObject,varargin)
%do cleanup here
delete(hFig);
end
end
There is no call to close the figure from the first GUI.
You may want to add a call close(hFig) to the end of the mainGUI function.
I have got a GUI, which imports the data from a *.xls file and plots graph. The last thing I cannot do is the data refreshing, because my xls file updates each 15 sec. I want my GUI to update input data each 20 seconds. How can I do that? And also I would like to have a button which will have an ability to pause/run data updating.
function viewSTUEP
global hPlot hChoice raw
handles.F = figure('Name','viewSTUEP', 'Position',[100 20 900 550], ...
'Color',[0.8 0.8 0.8], 'NumberTitle','off', 'Resize','off');
uicontrol('Style','pushbutton', 'Position',[690 510 94 30], ...
'FontSize',12, 'String','Load', 'Callback',#LoadData);
uicontrol('Style','pushbutton', 'Position',[790 510 94 30], ...
'FontSize',12, 'String','Save plot', 'Callback',#SaveAs);
uicontrol('Style', 'pushbutton', 'Position', [690 475 94 30], ...
'FontSize',12, 'String','Update', 'Callback',#UpdatePlot);
uicontrol('Style','pushbutton', 'Position',[790 475 94 30], ...
'FontSize',12, 'String','Close', 'Callback',{#Close,handles});
set(handles.F, 'CloseRequestFcn', {#Close,handles})
set(gcf, 'Toolbar', 'figure');
clear raw, raw(1,:) = {''};
hPlot = axes('Position',[0.06 0.08 0.68 0.9], 'Visible','on');
uicontrol('Style','text', 'Position',[690 432 130 35], ...
'BackgroundColor',[0.8 0.8 0.8], 'FontSize',12, ...
'HorizontalAlignment','left', 'String','Columns for plot:');
hChoice = uicontrol('Style','listbox', 'Position',[690 420 204 22], ...
'FontSize',12, 'String',raw(1,:), 'Min',1, 'Max',1);
function Close(hObject, eventdata, handles)
delete(handles.F);
function LoadData(hObject, eventdata)
global hChoice raw xdat
[fname, pname] = uigetfile('*.xls','Select a data file');
if fname ~= 0
filename = strcat(pname, fname);
[numeric,text,raw] = xlsread(filename);
num = length(raw(1,:));
if (num > 21) num = 21; end
posY = 442 - (20*num);
set(hChoice, 'String',raw(1,:));
set(hChoice, 'Max',num);
set(hChoice, 'Position',[690 posY 204 (20*num)]);
xdat = datenum(0,0,0,0,0,cell2mat(raw(2:end,6)));
end
function UpdatePlot(hObject, eventdata)
global hPlot hChoice raw xdat
if ~isempty(raw)
cols = get(hChoice,'Value');
plot(hPlot, xdat,cell2mat(raw(2:end,cols(1))), 'LineWidth',2), datetick('x','HH:MM')
grid on
if (length(cols) > 1)
colors = 'brgcmyk'; c = 2;
hold(hPlot, 'on')
for k = cols(2:end)
plot(hPlot, xdat,cell2mat(raw(2:end,k)),colors(c),'LineWidth',2)
c = c+1; if (c > 7) c = 1; end
end
hold(hPlot, 'off')
end
legend(hPlot, raw(1,cols), 'Interpreter','none','Location','SouthEast')
xlabel(hPlot, 'Time in minutes:');
ylabel(hPlot, 'Temperature in C:');
end
function SaveAs(hObject, eventdata, handles)
[Save,savename] = uiputfile('*.eps','Save plot as: ')
fname=fullfile(savename,Save);
print('-depsc','-r300','-noui',fname)
I think you should use a timer object - see here