连续实时绘图
图看上去不是很清晰,KAZAM录屏AVI尺寸80MB, 转换成gif后10MB, 按CSDN对GIF要求,把它剪裁缩小压缩成了上面的GIF,图像质量大不如原屏AVI,但应该能说明原意:随机数据随时间绘制在 gtk 的 drawingArea 上,曲线左移后继续绘制,形成连续的实时数据绘图。
1. 在窗体上放置控件 drawingarea1
drawingarea1是 gtk 的组件,它是 gdk 窗口的一个框,绘图域是 gdkwindow
2. 内存中创建一个足够大的cario图像和cairo context上下文
drawingarea1Width = drawingarea1.Allocation.Width;
drawingarea1Height = drawingarea1.Allocation.Height;
//surfacepub = new ImageSurface(Format.ARGB32, drawingarea1Width, drawingarea1Height);
surfacepub = new ImageSurface(Format.ARGB32, 1920, 1080);
ctxpub = new Cairo.Context(surfacepub);
drawingarea1Width和drawingarea1Height 是读取的drawingarea1的宽高尺寸,surfacepub是内存中的图像的surface,ctxpub 是 surface 的 Cairo Context
3. 在gdk的timer事中判断是否绘图点超界,超界了调用moveleft函数让绘图点左移500个像素,衔接绘图。
private Boolean OnTimedEvent1()
{
drawingarea1Width = drawingarea1.Allocation.Width;
drawingarea1Height = drawingarea1.Allocation.Height;
iArea1ObjX += 10;
if (iArea1ObjX > drawingarea1Width)
{
moveleft();
int movdiff = 500;
iArea1ObjX = drawingarea1Width-movdiff;
iOldX2 = iOldX2 - movdiff; iOldX1 = iOldX1 - movdiff;
//Mark by write Moved!
Gdk.GC gc = new Gdk.GC(drawingarea1.GdkWindow);
gc.RgbFgColor = new Gdk.Color(0, 0, 0);
drawingarea1.GdkWindow.DrawRectangle(gc, true, iOldX2, 0, drawingarea1Width, drawingarea1Height);
gc.RgbFgColor = new Gdk.Color(255,255,255);
var layout = new Pango.Layout(PangoContext);
layout.SetText("Moved!");
layout.FontDescription = Pango.FontDescription.FromString("Serif 12");
drawingarea1.GdkWindow.DrawLayout(gc, iOldX2, iOldY2, layout);
gc.Dispose();
DestroyContext();
CreateContext();
}
ctxpub.MoveTo(iArea1ObjX, iArea1ObjY);
ctxpub.SetSourceRGB(1, 0, 0);
// Draw
var rand = new Random();
iArea1ObjY = rand.Next(10, 150);
iOldX1 = iOldX2; iOldY1 = iOldY2;
iOldX2 = iArea1ObjX; iOldY2 = iArea1ObjY;
ctxpub.MoveTo(iOldX1, iOldY1);
ctxpub.LineTo(iArea1ObjX, iArea1ObjY);
ctxpub.ClosePath();
ctxpub.Stroke();
ctxArea1 = Gdk.CairoHelper.Create(drawingarea1.GdkWindow);
surfacepub.Show(ctxArea1, 0, 0);
ctxArea1.Dispose();
return true;
}
4. drawingarea1 图像左移 moveleft
private void moveleft()
{
int movdiff = 500;
Gdk.Pixbuf pixbuf = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, drawingarea1Width, 1080);
pixbuf = pixbuf.GetFromDrawable(drawingarea1.GdkWindow, Gdk.Colormap.System, movdiff, 0, 0, 0, (drawingarea1Width-movdiff), 1080);
Gdk.Pixbuf pixbuf1 = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, false, 8, drawingarea1Width, 1080);
pixbuf.CopyArea(movdiff, 0, drawingarea1Width, 1080, pixbuf1, 0, 0);
Gdk.GC gc = new Gdk.GC(drawingarea1.GdkWindow);
drawingarea1.GdkWindow.DrawPixbuf(gc, pixbuf, 0, 0, 0, 0, drawingarea1Width, 1080, Gdk.RgbDither.None, 0, 0);
pixbuf.Dispose();
pixbuf1.Dispose();
gc.Dispose();
}
5. 释放内存surface和其cairo context
private void DestroyContext()
{
surfacepub.Dispose();
ctxpub.Dispose();
}
如果在内存surface上显示Hello World, 将图像存成 png 是下面的样子。大小只有4kb,是镂空的,如果在photoshop上的话可以放在任何图层上,在上面的程序中也可以将它拓印到任何共它surface上,drawingarea1.GdkWindow也是一个surface
能绘图了,但后期基本上是操作gdk的东西,从cairo的surface上读取 image试了,将image变换成cairo的surface参照gdk函数,但没找到C# 封装后如何表述,感谢有路过的大神能指点,说明书类的东西太少了、没找到比较全面细致的。