keeping track of multiple lines properties

4 views (last 30 days)
Chad
Chad on 5 Sep 2013
Hi,
I have a gui that makes multiple lines on a single axis. The number of lines depends on the number of "channels" the user selects. I have given the user the ability to change the color of the line and marker style
I have made a structure to keep track of the properties/characteristics of the line. Some of the properties are the line handle, color, and marker style. An array of this structure is created when my plot function is called.
The code:
if true
% function line_edit(src,evnt,num_select,line_struct,handles)
% src - the object that is the source of the event
% evnt - empty for this property
%get selection type
sel_type = get(gcbf,'SelectionType');
%handle to parent axes
h_axes = get(src,'Parent');
%handle to all lines in axes
line_handles = get(h_axes,'Children');
if ~isempty(getappdata(handles.import_data,'line_struct'))
line_struct = getappdata(handles.import_data,'line_struct');
end
%call style_change function which creates structure with line info
line_struct = style_change(sel_type, num_select, line_struct, src);
for i = 1:num_select
if strcmpi(line_struct(i).ChanName, get(src,'DisplayName'))
%set line color
set(src,'Color',line_struct(i).color)
%set line style
set(src,'LineStyle',line_struct(i).linest)
%set marker style
set(src,'Marker',line_struct(i).markerst)
end
end
setappdata(handles.import_data,'line_struct',line_struct) end
I also created a button down function for the lines to dynamically change the color and marker style. When this function is called I use setappdata to save the new line structure and for access by other functions.
However,I am having a hard time keeping the right structure with the right line when I add or delete new lines to the axis. For instance the user has selected channels 1 and 3. The user then changes line 3 from red to green and the marker style from 'none' to '+'. Then the user selects channel 2. All the information from 3 is in 2 and 3 is set to default values. Same thing happens when the user deletes a channel. I am trying to make a unique identifier for each line so the integrity of the structure remains. Any thoughts on how I should go about this?
If my intentions are confusing you, please ask me questions. And if you need a better idea of what my code is doing, please ask me questions
Thanks, Chad
  4 Comments
dpb
dpb on 5 Sep 2013
Why do they all change instead of just deleting one or adding one?
Chad
Chad on 5 Sep 2013
Why do all the handles change? I guess it is just how matlab assigns handles. The value for the handle for each line only changes when a channel is added or deleted. So if I want to keep the properties of all the other lines I need to know the new handles in order to set the new lines to the previous properties. These properties (line style, marker style, color, etc.) are reset when I get the new handles so I need to update them(the properties)by using the previously stored line structure.
One of the lineseries properties is UserData so I am thinking of setting the UserData to hold this line_structure. But then that leads to the question how do I make sure that I have the right handle to individually set the UserData appropriately?
I am out of ideas and have been getting frustrated lol.

Sign in to comment.

Answers (1)

Arthur
Arthur on 5 Sep 2013
Your approach sounds way to complicated - there's no need to make a separate structure with all the object properties. Storing and using the same variable in two different locations (object properties and your extra struct) is very likely to become a disaster.
If I understand correctly, the user can select a trace by clicking it, and then change the properties elsewhere in the GUI. The only thing the ButtonDownFcn needs to do is mark this trace as the 'current' trace. Something like this.
function lineButtonDownFcn(hObject,evnt)
%save line as current in GUI appdata
hGUI = getappdata(0,'yourguihandle')
setappdata(hGUI,'currentTrace',hObject');
In the functions modifying line properties, you simply retrieve the currentTrace handle from appdata, and set the property of choice.
hGUI = getappdata(0,'yourguihandle');
currentTrace = getappdata(hGUI,'currentTrace')
set(currentTrace,'Color','r')
  12 Comments
Chad
Chad on 6 Sep 2013
I am trying to find a way to do this without having to use the struct but I simply cannot. So with that said I have rewritten some code using the struct. I havent compiled it yet but just wanted to show the jist of it:
if isempty(getappdata(handles.import_data,'line_struct'))
%initial line handle
line_handle = plot_options(gca, y_scale, x_scale, pxx, F, t_unit, grid_m, colors);
%create structure to hold information on each line
line_struct = line_structure(num_select, line_handle, channame(index));
%create appdata to be used by other functions
setappdata(handles.import_data,'line_struct',line_struct)
%set appropriate name for each channel to be displayed for legend
for i = 1:num_select
set(line_handle(i),'DisplayName',line_struct(i).ChanName);
end
else
line_struct_temp = getappdata(handles.import_data,'line_struct');
tempSize = max(size(line_struct_temp));
for i = 1:num_select
line_handle(i) = findobj(gca,'DisplayName',channame(index(i)));
for j = 1:tempSize
if strcmpi(get(line_handle(i),'DisplayName'),line_struct_temp(j).ChanName)
line_struct_temp(j).handle = line_handle(i);
end
end
end
line_struct = line_structure(num_select,line_handle, channame(index));
for i = 1:num_select
for j = 1:tempSize
if line_struct_temp(j).handle == line_struct(i).handle
line_struct(i) = line_struct_temp(j);
end
end
set(line_handle(i),'color',line_struct(i).color)
set(line_handle(i),'lineStyle',line_struct(i).linest)
set(line_handle(i),'marker',line_struct(i).markerst)
end
end end
Arthur
Arthur on 6 Sep 2013
Edited: Arthur on 6 Sep 2013
Ok your code is only becoming more and more complicated. Also, you're still updating all the properties of all lines every time, which you don't have to. Let me show you how I would create such a GUI.
First the plot function. This function will be called once, just after loading the data
function update_plot()
%get the data and handles
hGUI = getappdata(0,'myGUI');
handles = getappdata(hGUI,'handles');
data = getappdata(hGUi,'data');
%plot the data with default appearance
hold(handles.axes,'on')
for i = 1:length(data)
handles.line(i) = plot(handles.axes,data(i).x,data(i).y,...
'ButtonDownFcn', @selectTrace);
end
%store handles
setappdata(hGUI,'handles',handles)
function selectTrace(hObject,~)
%store the handle of the selected trace as current
hGUI = getappdata(0,'myGUI');
setappdata(hGUI,'CurrentTrace',hObject);
I'll assume you have some popupboxes and/or tickboxes to set the properties of the lines. For instance, the Callback function for a popup setting the color of the line will look like this
function popup_selectColorCallback(hObject,eventdata,handles)
%get the color that was selected in the popup
switch get(hObject,'Value')
case 1
%red
color = 'r';
case 2
%green
color = 'g';
case 3
%blue
color = 'b';
end
%get the currently selected trace, and update its color
hGUI = getappdata(0,'myGUI');
currentTrace = getappdata(hGUI,'currentTrace');
set(currentTrace,'Color',color)
And that's it. As you see, I only update the property that I want to change, and just forget about the others. In this way, you do not have to collect all the properties of all the lines.
Deleting a line also won't be a problem. Because once it's deleted, the user can not click on it anymore, so it will never become your currentTrace.

Sign in to comment.

Categories

Find more on Graphics Objects in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!