WinForms 创建透明的可清除 pictureBox 覆盖
WinForms create transparent clearable pictureBox overlays
我想在 WinFrom 应用程序中为 pictureBox 创建 2 个透明覆盖层,这样我就可以分别在两者上绘制,也可以在我想空白透明覆盖层时清除它。
我在一张叠加层上绘制矩形。我一直想要这些矩形。
在第二个叠加层上我画了圆,但我只想画 1 个圆,在用户输入后清除这个圆并画另一个。
目前我正在使用
var transparentOverlay = pictureBox.createGraphics();
但我不知道如何清除覆盖以空白透明图形。
我试过了
transparentOverlay.Clear(Color.Transparent)
将所有叠加层变为黑色
pictureBox.Invalidate()
清除了两个叠加层中的所有图形,因此我的矩形保留在原处
- 使用我在任何绘图之前创建的一些备份图形,并通过将此图形分配给它来清除我的叠加层
transparentOverlay = transparentOverlayBackup
但这没有任何作用,所有矩形和所有圆圈都保留在它们的位置
有没有办法创建粘在 pictureBox 上的可清除透明图形?
编辑:
我在那个图片框中有一张带文字的图片。而我想要做的是在文本的文字周围绘制矩形,并且这个矩形应该一直保留在图片上。
比我想画一个圆圈并等待用户点击屏幕。这一切都很好,但是当用户点击屏幕时,我想清除那个圆圈并绘制另一个。
//this method I call by click on a button to start annotation
private void ExpertAnnotate(object sender, EventArgs e)
{
var pen = new Pen(Color.Black, 1);
if (!annotationIsRunning) //check if annotation is in process or not
{
annotationIsRunning = true;
annotationOverlay = pictureBox.CreateGraphics(); //create transparent overlay for drawing
//draw rectangles around all words in text (AOIs)
annotationAOIs.ForEach(a =>
{
annotationOverlay.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
});
//subscribe mouseMove and mouseClick events on pictureBox
pictureBox.MouseMove += HighlightAOI;
pictureBox.MouseClick += SelectAOI;
}
//define brushes for drawing circles (fixations)
var brush = new SolidBrush(Color.FromArgb(128, Color.BlueViolet));
var dotBrush = new SolidBrush(Color.DarkBlue);
pen.Color = Color.Blue;
long sizeOfFixation;
var f = Fixations[fixationCounter - 1]; //get current fixation to draw
sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT; //compute size of circle
annotationOverlay.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
//draw fixation on overlay
annotationOverlay.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);
}
//eventHandler for mouseMove - this method color rectangle over which mouse hover to red border
private void HighlightAOI(object sender, EventArgs e)
{
//this just draw last highlighted rect to black when we not yet hover mouse above it
if (lastHighlightedAOI != null)
{
annotationOverlay.DrawRectangle(new Pen(Color.Black, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
}
//get position of mouse sursor
var x = pictureBox.PointToClient(Cursor.Position).X;
var y = pictureBox.PointToClient(Cursor.Position).Y;
var tempFix = new Fixation() { PosX = x, PosY = y };
//get rectangle over which mouse hover
lastHighlightedAOI = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
if (lastHighlightedAOI != null)
{
//highlight rectangle by painting red border
annotationOverlay.DrawRectangle(new Pen(Color.Red, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
}
}
//eventHandler for mouse click
private void SelectAOI(object sender, EventArgs e)
{
//get position of cursor
var x = MousePosition.X;
var y = MousePosition.Y;
var tempFix = new Fixation() { PosX = x, PosY = y };
//get rectangle which we selected by a mouse click
var aoi = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
//assign last shown fixation to selected rectangle
if (aoi != null)
{
aoi.AssignedFixations.Add(Fixations[fixationCounter - 1]);
}
//if it wasn't last fixation again call ExpertAnnotation function to draw another Fixation over image (!!! here I need to clear last drawn fixation (circle) disappear and draw next fixation in ExpertAnnotate method)
if (fixationCounter != Fixations.Count)
{
ExpertAnnotate(sender, e);
}
else
{
TerminateExpertAnnotation("regular");
}
}
最好的方法是使用 PictureBox 控件的 OnPaint 事件处理程序并将所有绘图调用放在其中。
您可以使用传递给事件处理程序的 Graphics 对象来获取要绘制的表面(即图片框),然后使用各种方法绘制您想要的形状。
要绘制 'transparent' 形状,只需绘制轮廓而不是填充形状。
感谢 @Reza Aghaei 在聊天中指导我解决问题。
对我来说,可接受的解决方案是构建多层图像并将其分配给 pictureBox.Image 属性。
我通过从文件加载图像来构建图像:
Image im = new Bitmap(path); // loads image from file
然后从这个图像创建图形:
var g = Graphics.FromImage(im); // creates graphics from loaded image
将所有需要的矩形绘制到此图像并将此图像备份到某个全局 Image
实例:
var pen = new Pen(Color.Black, 1);
// draws all rectangles on the image
annotationAOIs.ForEach(a =>
{
g.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
});
g.Dispose(); // disposes used graphics
ImageBackup = new Bitmap(im); // backup image with rectangles
在上面的部分我创建了一个图像的静态部分,它不会改变并且我备份了它所以下次我将只从备份创建新的 Image
实例而不绘制任何矩形。
然后当我想在这张图片上显示新的圆圈时,我只是:
var image = new Bitmap(ImageBackup); // creates new instance of image with rectangles from backup
var g = Graphics.FromImage(image); // creates graphics from image
// in this part draw circle at specific point
var f = Fixations[fixationIndex];
sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT;
g.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
g.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);
pictureBox.Image.Dispose(); // dispose old pictureBox image
pictureBox.Image = image; // set new image
imageOverlay = pictureBox.CreateGraphics(); // get transparent graphics overlay for pictureBox so we can draw anything else over picture (in my case highlighting rectangles over which I hover a mouse)
g.Dispose(); // dispose used graphics
我想在 WinFrom 应用程序中为 pictureBox 创建 2 个透明覆盖层,这样我就可以分别在两者上绘制,也可以在我想空白透明覆盖层时清除它。
我在一张叠加层上绘制矩形。我一直想要这些矩形。
在第二个叠加层上我画了圆,但我只想画 1 个圆,在用户输入后清除这个圆并画另一个。
目前我正在使用
var transparentOverlay = pictureBox.createGraphics();
但我不知道如何清除覆盖以空白透明图形。 我试过了
transparentOverlay.Clear(Color.Transparent)
将所有叠加层变为黑色pictureBox.Invalidate()
清除了两个叠加层中的所有图形,因此我的矩形保留在原处- 使用我在任何绘图之前创建的一些备份图形,并通过将此图形分配给它来清除我的叠加层
transparentOverlay = transparentOverlayBackup
但这没有任何作用,所有矩形和所有圆圈都保留在它们的位置
有没有办法创建粘在 pictureBox 上的可清除透明图形?
编辑:
我在那个图片框中有一张带文字的图片。而我想要做的是在文本的文字周围绘制矩形,并且这个矩形应该一直保留在图片上。
比我想画一个圆圈并等待用户点击屏幕。这一切都很好,但是当用户点击屏幕时,我想清除那个圆圈并绘制另一个。
//this method I call by click on a button to start annotation
private void ExpertAnnotate(object sender, EventArgs e)
{
var pen = new Pen(Color.Black, 1);
if (!annotationIsRunning) //check if annotation is in process or not
{
annotationIsRunning = true;
annotationOverlay = pictureBox.CreateGraphics(); //create transparent overlay for drawing
//draw rectangles around all words in text (AOIs)
annotationAOIs.ForEach(a =>
{
annotationOverlay.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
});
//subscribe mouseMove and mouseClick events on pictureBox
pictureBox.MouseMove += HighlightAOI;
pictureBox.MouseClick += SelectAOI;
}
//define brushes for drawing circles (fixations)
var brush = new SolidBrush(Color.FromArgb(128, Color.BlueViolet));
var dotBrush = new SolidBrush(Color.DarkBlue);
pen.Color = Color.Blue;
long sizeOfFixation;
var f = Fixations[fixationCounter - 1]; //get current fixation to draw
sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT; //compute size of circle
annotationOverlay.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
//draw fixation on overlay
annotationOverlay.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);
}
//eventHandler for mouseMove - this method color rectangle over which mouse hover to red border
private void HighlightAOI(object sender, EventArgs e)
{
//this just draw last highlighted rect to black when we not yet hover mouse above it
if (lastHighlightedAOI != null)
{
annotationOverlay.DrawRectangle(new Pen(Color.Black, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
}
//get position of mouse sursor
var x = pictureBox.PointToClient(Cursor.Position).X;
var y = pictureBox.PointToClient(Cursor.Position).Y;
var tempFix = new Fixation() { PosX = x, PosY = y };
//get rectangle over which mouse hover
lastHighlightedAOI = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
if (lastHighlightedAOI != null)
{
//highlight rectangle by painting red border
annotationOverlay.DrawRectangle(new Pen(Color.Red, 1), lastHighlightedAOI.Start.X, lastHighlightedAOI.Start.Y, (lastHighlightedAOI.End.X - lastHighlightedAOI.Start.X), (lastHighlightedAOI.End.Y - lastHighlightedAOI.Start.Y));
}
}
//eventHandler for mouse click
private void SelectAOI(object sender, EventArgs e)
{
//get position of cursor
var x = MousePosition.X;
var y = MousePosition.Y;
var tempFix = new Fixation() { PosX = x, PosY = y };
//get rectangle which we selected by a mouse click
var aoi = tempFix.LiesIn(annotationAOIs).FirstOrDefault();
//assign last shown fixation to selected rectangle
if (aoi != null)
{
aoi.AssignedFixations.Add(Fixations[fixationCounter - 1]);
}
//if it wasn't last fixation again call ExpertAnnotation function to draw another Fixation over image (!!! here I need to clear last drawn fixation (circle) disappear and draw next fixation in ExpertAnnotate method)
if (fixationCounter != Fixations.Count)
{
ExpertAnnotate(sender, e);
}
else
{
TerminateExpertAnnotation("regular");
}
}
最好的方法是使用 PictureBox 控件的 OnPaint 事件处理程序并将所有绘图调用放在其中。
您可以使用传递给事件处理程序的 Graphics 对象来获取要绘制的表面(即图片框),然后使用各种方法绘制您想要的形状。
要绘制 'transparent' 形状,只需绘制轮廓而不是填充形状。
感谢 @Reza Aghaei 在聊天中指导我解决问题。
对我来说,可接受的解决方案是构建多层图像并将其分配给 pictureBox.Image 属性。
我通过从文件加载图像来构建图像:
Image im = new Bitmap(path); // loads image from file
然后从这个图像创建图形:
var g = Graphics.FromImage(im); // creates graphics from loaded image
将所有需要的矩形绘制到此图像并将此图像备份到某个全局 Image
实例:
var pen = new Pen(Color.Black, 1);
// draws all rectangles on the image
annotationAOIs.ForEach(a =>
{
g.DrawRectangle(pen, a.Start.X, a.Start.Y, (a.End.X - a.Start.X), (a.End.Y - a.Start.Y));
});
g.Dispose(); // disposes used graphics
ImageBackup = new Bitmap(im); // backup image with rectangles
在上面的部分我创建了一个图像的静态部分,它不会改变并且我备份了它所以下次我将只从备份创建新的 Image
实例而不绘制任何矩形。
然后当我想在这张图片上显示新的圆圈时,我只是:
var image = new Bitmap(ImageBackup); // creates new instance of image with rectangles from backup
var g = Graphics.FromImage(image); // creates graphics from image
// in this part draw circle at specific point
var f = Fixations[fixationIndex];
sizeOfFixation = (int)f.Length / FIX_SIZE_COEFICIENT;
g.FillEllipse(dotBrush, f.PosX - 1, f.PosY - 1, 3, 3);
g.FillEllipse(brush, (f.PosX - sizeOfFixation), (f.PosY - sizeOfFixation), sizeOfFixation * 2, sizeOfFixation * 2);
pictureBox.Image.Dispose(); // dispose old pictureBox image
pictureBox.Image = image; // set new image
imageOverlay = pictureBox.CreateGraphics(); // get transparent graphics overlay for pictureBox so we can draw anything else over picture (in my case highlighting rectangles over which I hover a mouse)
g.Dispose(); // dispose used graphics