App designer - deleting an unnamed plot
2 次查看(过去 30 天)
显示 更早的评论
Hi folks,
I have the following code for generating 1 or multiple plots on an image.
function ROI(app, index1, index2)
hold (app.Image, "on")
plot(app.Image, index1, index2, app.innerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
plot(app.Image, index1, index2, app.outerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
end
My question is, suppose there are 3 such plots. Is there a way to delete 1 and only 1 of them selectively?
Thanks
采纳的回答
Cris LaPierre
2021-4-10
If you capture the chart line object for each plot, you could use that with the delete function to remove just that line from the plot.
btw, it's best practice to always pair hold on with a corresponding hold off.
Here's a simple example.
% Create a plot with 3 lines
a=plot(rand(1,5));
hold on
b=plot(rand(1,5));
c=plot(rand(1,5));
hold off
% Now delete one of the lines using the line object
delete(b)
16 个评论
Teshan Rezel
2021-4-11
thanks @Cris LaPierre, but I can't really name them since the position and number of plots is dependant on a user input. so to name each plot proceduraly is not somethig I'm keen to do as it may slow down the app considerably.
Cris LaPierre
2021-4-11
I don't think it will slow it down, but I can understand your concern.
Another way to approach this is to use findobj to collect all the line objects in a plot, and then using delete to remove a specific line object. It may be a little harder to ensure you are removing the intended line.
% Create a plot with 3 lines
plot(rand(1,5));
hold on
plot(rand(1,5));
plot(rand(1,5));
hold off
% Now delete one of the lines using the line object
h = findobj('Type','line')
h =
3×1 Line array:
Line
Line
Line
delete(h(2))

Teshan Rezel
2021-4-16
hi @Cris LaPierre, I've tried doing this on app designer but it isn't deleting the plot. Any ideas why it isn't working please?
function ButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) + 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.tallyOrder(end+1) = index;
app.numManualTally = app.numManualTally + 1;
if app.numManualTally >= app.numSamplesPerImage
app.imageNumber = app.imageNumber + 1;
app.numManualTally = 0;
DeleteCrosshairs(app);
end
end
function DeleteCrosshairs(app)
f = findobj(app.Image, 'Type', 'line');
delete(f(end));
delete(f(end-1));
end
Cris LaPierre
2021-4-16
编辑:Cris LaPierre
2021-4-16
Is ButtonPushed supposed to have something to do with adding or removing a line plot from you image? It doesn't appear to be relevant.
I mocked up a simple example that plotted some lines on top of an image in app designer. The code in your DeleteCrosshairs succesfully removed 2 lines from the axes.
Teshan Rezel
2021-4-18
@Cris LaPierre apologies, I think I've not included the relevant functions! Here's the complete list!
methods (Access = private)
function ButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) + 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.tallyOrder(end+1) = index;
app.numManualTally = app.numManualTally + 1;
TallyCheck(app);
end
function ReverseButtonPushed(app, index)
app.Counts(end) = 0;
app.Percentages(end) = 0;
app.Counts(index) = app.Counts(index) - 1;
app.Counts(end) = sum(app.Counts, 1:7);
for i = 1 : 7
app.Percentages(i) = (app.Counts(i) / app.Counts(end)) * 100;
end
app.Percentages(end) = sum(app.Percentages, 1:7);
app.CokeTable.Data = [app.Counts, app.Percentages];
app.numManualTally = app.numManualTally - 1;
TallyCheck(app);
end
function ROI(app, index1, index2)
hold (app.Image, "on")
plot(app.Image, index1, index2, app.innerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
plot(app.Image, index1, index2, app.outerMarkerStyle, 'LineWidth', app.CrosshairThickness.Value, 'Color', app.crossHairColour, 'MarkerSize', app.CrosshairRadius.Value);
hold(app.Image, "off")
end
function DisplayCrosshairs(app)
I = imshow(app.img, "Parent", app.Image);
app.Image.XLim = [0 I.XData(2)];
app.Image.YLim = [0 I.YData(2)];
app.Width = app.Image.XLim;
app.Height = app.Image.YLim;
quarterHeight = range(app.Height)*0.125;
halfHeight = range(app.Height)*0.5;
threeQuarterHeight = range(app.Height)*0.875;
quarterWidth = range(app.Width)*0.125;
halfWidth = range(app.Width)*0.5;
threeQuarterWidth = range(app.Width)*0.875;
app.positionVector = {quarterWidth quarterHeight;halfWidth quarterHeight;threeQuarterWidth quarterHeight;quarterWidth halfHeight;halfWidth halfHeight;threeQuarterWidth halfHeight;quarterWidth threeQuarterHeight;halfWidth threeQuarterHeight;threeQuarterWidth threeQuarterHeight};
app.checkMatrix = [app.TopLeft.Value app.TopMiddle.Value app.TopRight.Value app.CentreLeft.Value app.CentreMiddle.Value app.CentreRight.Value app.BottomLeft.Value app.BottomMiddle.Value app.BottomRight.Value];
count = 0;
for i = 1 : 9
if app.checkMatrix(i) == 1
ROI(app, app.positionVector{i,1:2});
count = count + 1;
end
end
if count == 0
msgbox('Please select a quadrant for the crosshair to be displayed in');
end
end
function ResinThreshold(app)
imgGrey = rgb2gray(app.img);
[counts, ~] = imhist(imgGrey, 255);
T = otsuthresh(counts);
BW = imbinarize(imgGrey, T);
BW = bwareaopen(BW, app.AreaOpen.Value);
BW = imfill(BW, 'holes');
BW = bwperim(BW);
BW = imdilate(BW, ones(app.DilationMatrixDimensions.Value));
BW = imerode(BW, ones(app.ErosionMatrixDimensions.Value));
BW = imfill(BW, 'holes');
app.img = app.img.*repmat(uint8(BW),[1 1 3]);
end
function DisplayImage(app)
app.currentImage = fullfile(app.imageFolder(app.imageNumber).folder, app.imageFolder(app.imageNumber).name);
app.Image.Position = [0 0 app.UIFigure.Position(3:4)];
app.img = imread(app.currentImage);
if app.ThresholdResin.Value == 1
ResinThreshold(app);
end
DisplayCrosshairs(app);
app.ImageNumber.Value = app.imageNumber;
app.TotalNumber.Value = app.fileNumber;
app.numSamplesPerImage = sum(app.checkMatrix, 1:9);
end
function TallyCheck(app)
if app.numManualTally >= app.numSamplesPerImage
app.imageNumber = app.imageNumber + 1;
app.numManualTally = 0;
elseif app.numManualTally <= 0
app.imageNumber = app.imageNumber - 1;
app.numManualTally = app.numSamplesPerImage;
end
end
end
Cris LaPierre
2021-4-19
Still missing something. This code never even attempts to delete an object from your plot.
If you code is the combination of your two previous replies, then you you have two functions names ButtonPushed. They do different things, so perhaps you have a naming conflict?
Are you gettting any error messages? If so, share the entire message (all the red text).
Teshan Rezel
2021-4-19
Hey @Cris LaPierre, I think it's best if I attach the file as it saves some confusion...I don't think I'm explaining it well!
The way the app works is it will prompt you to select a folder with jpeg images on startup. Once selected, you can push each of the buttons on the left of the table to move to the next image. The number of times you need to click the buttons to move will depend on the number of crosshairs drawn, which can be varied by selecting the checkboxes in the "crosshair position" part of the "crosshair" tab.
Basically, I'm looking to delete a crosshair once a tally has been made. In other words, each time a button is pushed, a crosshair gets deleted.
Hope this is clear and I haven't missed anything out!
Cris LaPierre
2021-4-19
I've added the delete function you shared before to the app you shared previously. It is attached. I was able to confirm it deletes the crosshairs, but I'm definitely not comfortable navigating the app. Still, this should get your started.
Teshan Rezel
2021-4-19
hi @Cris LaPierre, below is an image of when the top left plot should have been removed, but isn't. I'm not seeing any error messages!

Cris LaPierre
2021-4-19
It removes the last crosshair added. However, pressing on a button also advances to the next image. If you had a way to go back to the previous image, you would see the crosshair removed.
Comment out the DisplayImage(app); in the corresponding callback function to prevent the images from advancing.
Teshan Rezel
2021-4-19
Hi @Cris LaPierre, thanks. This appear to work for only one crosshair. However, for more than one crosshair per image, the app will now not progress to the next image once the requisite number of tallies has been made...
Cris LaPierre
2021-4-19
You have the code, and I've shown you it works for a single crosshair. Now you can adapt that into your app to obtain the behavior you want.
You may need to think through your design and logic to accomplish that. Right now the confusion was because you are removing a crosshair from the visible image, but then the same code immediately advances to the next image, where all crosshairs are shown again, making it appear like the crosshair was not removed.
Teshan Rezel
2021-4-19
hi @Cris LaPierre, sorry about this...I was just being very stupid...well, more than usual! This has been a tremendous help, thank you!
更多回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Line Plots 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)