我发现图形g和e.Graphics与绘画事件有区别.e.Graphics就像“更多PRO”,它允许转换矩阵更有趣。
像https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx
我正在编写app,其中包含几个对象。在这个问题中有例子
C# rotation (transformation) issue
我发现如何覆盖OnPaint方法https://msdn.microsoft.com/en-us/library/b818z6z6(v=vs.71).aspx
我不明白的想法是用法如何使用它。我需要覆盖OnPaint方法 - 确定,但是在什么对象?
让我们想象一下简单的情况我将在c#中使用Form
public partial class Form1 : Form {
private Bitmap canvasBitmap; //bitmap for drawing
private Graphics g;
...
public Form1() {
//on Form there is placed PictureBox called canvas
//so canvas is PictureBox 640x480 px
canvasBitmap = new Bitmap(canvas.Width, canvas.Height);
canvas.Image = canvasBitmap;
//prepare graphics
g = Graphics.FromImage(canvasBitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
...
g.Invalidate();
}
}
所有绘图都将在PictureBox上完成,这将是我的画布。可以保留Graphics g而不是e.Graphics吗?
我会有一些对象:
List<Fish> fishes = new List<Fish>();
List<Food> food = new List<Food>();
我想和他们做一些有趣的事情,例如像这里的一些变换(scalling,translation,rotation) https://msdn.microsoft.com/en-us/library/eews39w7(v=vs.110).aspx
这是对象。我试着编写OnPaint方法(不确定它是否在正确的位置。)
class Fish {
Point position;
Fish(int x, int y) {
...
}
protected override void OnPaint(PaintEventArgs e){
...
}
}
class Food {
Point position;
public Food(int x, int y) {
...
}
protected override void OnPaint(PaintEventArgs pe) {
....
}
}
问题是:在这种情况下应该如何使用OnPaint方法?使用它的用法是什么?我想我可能会像Fish一样在Fish和Food对象上覆盖这个方法。我是怎么画的?我怎么重绘它?我如何将它放在Form中的Graphics g画布上?应该在哪里以及如何使用Invalidate?
我使用
canvas.Invalidate();
请参阅表单示例。 我可以混合使用Graphics g和e.Graphics吗?也可以使用e.Graphics使用一些双重缓冲或类似的东西。
修改
E1)那么Form和PicutreBox是否可以控制?我的鱼类和食物课程不受控制?好?
E2)在图片框上可以以某种方式最多可以切换3个图形,以便进行平滑绘图。但为简单起见,我可以留在一个?好吗?
E3)图形g是工具e.Graphics是一些图形库的包装器,其中有一些支持转换格式(使用转换矩阵)。 OK?
E4) OnPaint(PaintEventArgs e)
会让我能够使用e.Graphics,但如果我在计时器中有“循环”(在计时器对象的句柄中,我只是放在我的表单上并设置了句点)并从中我调用更新的方法并更新一些列表中的鱼类和食物的所有对象(根据我的计算,Update =与它们进行转换)。有可能在某种程度上使用e.Graphics的方法吗?
E5)如果E1为真,那么Food和Fish类中的覆盖OnPaint方法是无效的吗?
答案 0 :(得分:1)
e.Graphics
来自OnPaint
或Paint
事件,因此仅适用于控件。
从位图创建的Graphics
对象仅适用于该位图。
你应该使用你真正想要的那个:在表面上绘制或到位图中。
请注意,位图可能会在控件中显示(也可能不会在曲面下方显示)。
例如,一个图片框甚至可以在其表面下方显示两个位图,因此您可能需要使用三个 Graphics
个对象..
他们将相同的内容与不同的像素进行比较而不是,不能更多地使用...您可以使用矩阵和其他转换来应用。
从e.Graphics
参数中获取OnPaint
的原因是系统需要在某些时候重新绘制表单中的所有控件,因此除了必须调用您的绘图代码之外内部控制绘图程序。
因此您需要使用此事件和/或其e.Graphics
,否则您的绘图将在重绘时消失。使用e.Graphics
绘制到控件上会使绘图 保持 。 (*)
另一方面,位图将始终以其当前状态显示。不需要重绘它们;完成更改后,只需致电Refresh()
一次,让系统了解它们。
最后:DoubleBuffering
是控件的属性,而不是Graphics
对象的属性。请注意,对于大多数,特别是像Panel这样的容器来说,它是隐藏的,所以要打开它,你需要对它们进行子类化。 PictureBox
用于绘图,开箱即用DoubleBuffered = true
。
Graphics
对象不包含任何图形;它是一个工具,可让您绘制到相关的位图,包括控件的表面。
(*)请注意并非所有绘图需要或应该保留:橡皮筋线或矩形不应该在这里使用第3 Graphics
construstor:Graphics g = someControl.CreateGraphics();
。