想要在 C# 中绘制一个圆圈来跟随我的鼠标
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1140076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Want a drawn circle to follow my mouse in C#
提问by ck_
First off, I'm a real beginer at C# so please be gentle.
首先,我是 C# 的真正初学者,所以请保持温和。
I'm trying to have a circle follow my cursor. I don't want any "trails" to be left behind.
我试图让一个圆圈跟随我的光标。我不想留下任何“痕迹”。
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
drawCircle(e.X, e.Y);
}
private void drawCircle(int x, int y)
{
Pen skyBluePen = new Pen(Brushes.DeepSkyBlue);
Graphics graphics = CreateGraphics();
graphics.DrawEllipse(
skyBluePen, x - 150, y - 150, 300, 300);
graphics.Dispose();
this.Invalidate();
}
This works ok, as it draws it and centers on the mouse for every mouse move. However, the "this.Invalidate();" is wrong. It "undraws" the shape after every movement, so I can only see glimpses of it. However, not including it causes every single drawn circle to remain on screen.
这可以正常工作,因为它会在每次鼠标移动时绘制它并以鼠标为中心。但是,“this.Invalidate();” 是错的。它在每次运动后“展开”形状,所以我只能看到它的一瞥。但是,不包括它会导致每个绘制的圆圈都保留在屏幕上。
How do I get one circle to "gracefully" follow my mouse around, without being too jumpy and without retaining all of the past circles?
如何让一个圆圈“优雅地”跟随我的鼠标四处走动,而不会太紧张,也不会保留过去的所有圆圈?
采纳答案by Erich Mirabal
You can do something like this:
你可以这样做:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Point local = this.PointToClient(Cursor.Position);
e.Graphics.DrawEllipse(Pens.Red, local.X-25, local.Y-25, 20, 20);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
Invalidate();
}
}
Basically, on the mouse move, invalidate. On the Paint, draw your circle.
基本上,在鼠标移动时,无效。在 Paint 上,绘制您的圆圈。
回答by Chris Thompson
You need to invalidate the form BEFORE you draw your circle.
您需要在绘制圆圈之前使表单无效。
I'm positive that there are more efficient ways to do this using double-buffering, but I don't have an example off the top of my head.
我很肯定有更有效的方法可以使用双缓冲来做到这一点,但我没有想到一个例子。
回答by Erich Mirabal
You don't generally want to do any drawing outside of the paint handler because whenever the paint handler does execute (which could be at any time) it will overwrite whatever you did.
您通常不想在绘制处理程序之外进行任何绘制,因为无论何时绘制处理程序执行(可能在任何时间),它都会覆盖您所做的任何事情。
There are a bunch of things that you will have to think about eventually (like what happens when the mouse goes outside of your form, but this should get you started.
有很多事情你最终必须考虑(比如当鼠标离开你的表单时会发生什么,但这应该让你开始。
using System;
using System.Drawing;
using System.Windows.Forms;
class C:Form
{
static void Main(){Application.Run(new C());}
private Point? _MousePosition = null;
protected override void OnMouseMove(MouseEventArgs e) {
_MousePosition = e.Location;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
if(_MousePosition.HasValue) {
using(Pen skyBluePen = new Pen(Brushes.DeepSkyBlue)) {
e.Graphics.DrawEllipse(skyBluePen, _MousePosition.Value.X - 150, _MousePosition.Value.Y - 150, 300, 300);
}
}
}
}
回答by Erich Mirabal
This works - just tested it...
这有效 - 刚刚测试过......
private int x = 0;
private int y = 0;
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Pen skyBluePen = new Pen(Brushes.DeepSkyBlue);
e.Graphics.DrawEllipse(skyBluePen, x - 150, y - 150, 300, 300);
}
回答by colithium
The best way to draw something that is quickly changing is to use a concept known as double buffering. It's really easy to do yourself and you don't have to rely on the double buffering flag. Doing it yourself gives you complete freedom and control.
绘制快速变化的事物的最佳方法是使用称为双缓冲的概念。自己做真的很容易,而且您不必依赖双缓冲标志。自己动手为您提供完全的自由和控制权。
Basically, instead of drawing on the Form itself, you do all of your drawing on an off-screen Bitmap. You only draw when you know something has changed (in your case, on the mouse move event). You only draw on the screen when you know you have to (after mouse move or when the Paint event is raised).
基本上,您不是在 Form 本身上绘图,而是在屏幕外位图上进行所有绘图。只有当您知道某些事情发生了变化(在您的情况下,在鼠标移动事件上)时,您才能进行绘制。只有在您知道必须这样做时(在鼠标移动后或引发 Paint 事件时),您才可以在屏幕上进行绘制。
private void DrawScene(Point mouseLocation)
{
myGraphics.Clear(Color.White)
myGraphics.DrawEllipse(skyBluePen, mouseLocation.X - 150, mouseLocation.Y - 150, 300, 300);
myDrawingSurface.Refresh(); //myDrawingSurface can be a Form or a PictureBox or whatever you'd like. Normally, you'd only Invalidate areas that have changed
}
private void myDrawingSurface_MouseMove(object sender, MouseEventArgs e)
{
DrawScene(e.Location);
}
private void myDrawingSurface_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(myBitmap, 0, 0); //Can't remember the exact signature
}
Another "cheating" way of doing it is to simply assign a PictureBox's Image property to the image you are drawing on and call Refresh on the PictureBox. It will handle drawing its image on screen for you. No Paint handler required.
另一种“欺骗”的方法是简单地将 PictureBox 的 Image 属性分配给您正在绘制的图像,并在 PictureBox 上调用 Refresh。它将为您处理在屏幕上绘制其图像。不需要油漆处理程序。
Note. You need to declare myBitmap and myGraphics once. The Bitmap will have to be recreated at the appropriate size when the drawing surface changes size. Also, do NOTkeep re-declaring Pens and other graphics objects over and over again. They should be declared once when your program starts. And dispose of them properly when your program is closing.
笔记。您需要声明一次 myBitmap 和 myGraphics。当绘图表面更改大小时,必须以适当的大小重新创建位图。另外,千万不要继续再宣布钢笔和其他图形对象一遍又一遍。它们应该在您的程序启动时声明一次。并在您的程序关闭时正确处理它们。
回答by bufferz
Try adding the following lines in your Form constructor:
尝试在您的 Form 构造函数中添加以下几行:
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
This will tell the Form to only repaint when you tell it to do so. It will also provide double buffering. Good luck!
这将告诉表单仅在您告诉它时才重新绘制。它还将提供双缓冲。祝你好运!