[英]How to create Cairo Context for drawing in code with Gtk Sharp and C#
我有几个按钮,还有一个要绘制一些东西的区域。 由于Gtk的“ Drawing Area
小部件似乎不知道如何绘制基本形状(或者我只是找不到它的工作方式),因此我一直在尝试使用Cairo创建用于绘制的表面。
我找到了一些与此相关的基本教程(例如: http : //zetcode.com/gui/gtksharp/drawing/或http://www.mono-project.com/docs/tools+libraries/libraries/Mono.Cairo/ tutorial / ),但无法弄清楚如何在我的应用程序中制作用于绘图的表面,以及按钮和标签,而不仅仅是一个仅用于开罗绘图的新空白窗口。
这是我的应用现在的外观:
因此,我希望中间的空白部分成为我的绘图区域。
我尝试过这个,我认为应该可以使我在应用程序中使用“开罗”绘制的“绘图区域”小部件可绘制:
我不太明白该怎么办。
我只需要在上面画一些基本的圆和线,所以我真的不需要开罗,在我使用Gtk#进行任何绘画方面的任何帮助将不胜感激!
您走在正确的轨道上。 不幸的是,GTK#和开罗有一些怪癖。 首先,我强烈建议您使用EventBox小部件而不是DrawingArea。 从直觉上来说,我从来没有遇到过让DrawingArea正常工作的运气。 除了可以通过将VisibleWindow设置为false来使背景透明之外,EventBox的工作方式几乎相同。
public class YourWidget : EventBox
{
public YourWidget() {
Visible = true;
VisibleWindow = false;
ExposeEvent += OnExpose;
}
}
接下来,在事件框中绘制时使用的纵坐标基于父窗口(即整个应用程序窗口)的原点。 每个小部件对象都包含一些属性Allocation
,用于指定其在父窗口中的位置以及其大小。 为了在自定义窗口小部件窗口的范围内绘制,您必须参考这些要点。 这仅适用于自定义小部件,扩展了EventBox小部件。 如果有内存,则从窗口小部件位置引用使用DrawingArea的窗口小部件。 最后,我将在一个using
块中包含Cairo Context,这样您就不会忘记处理该对象。
protected void OnExpose(object sender, ExposeEventArgs args) {
using (Context cr = Gdk.CairoHelper.Create(this.GdkWindow)) {
int top = Allocation.Top;
int left = Allocation.Left;
cr.Rectangle(left + 8, top + 8, 10, 10);
cr.SetSourceRGB(255, 0, 0);
cr.Fill();
}
}
另外,自从我启动了新的GTK#应用程序以来已经有一段时间了,但是您可能必须将Mono.Cairo包添加到项目的引用中。 最后,我使用了基于EventBox
的窗口小部件为触摸应用程序创建了多个自定义窗口小部件,它们也可以作为入门的参考。 希望对您有帮助。
我可以在这里添加一些内容。 您可以使用DrawingArea,我从未遇到过与Skyler一样的麻烦,但是Cairo几乎可以在任何小部件或基本窗口上进行绘制。 我大量使用了DrawingAreas,并且还扩展了基本小部件并使用cairo进行渲染。
我可以给出的关键指标:
使用小部件的Expose事件获取对开罗将需要绘制到的GdkWindow的引用。 例如:
protected void OnExpose (object o, Gtk.ExposeEventArgs args) { Draw (args.Event.Window); }
在绘图操作中,使用Cairo Helper创建Cairo上下文。
private void Draw (Gdk.Window w) { double _bg = (55.0 / 255.0); using (Cairo.Context _c = Gdk.CairoHelper.Create (w)) { _c.LineWidth = 2; _c.SetSourceRGB (_bg, _bg, _bg); _c.Rectangle (0, 0, this.WidthRequest, this.HeightRequest); _c.StrokePreserve (); _c.SetSourceRGBA (_bg, _bg, _bg, 0.5); _c.Fill (); _c.Dispose (); } }
最后使用Dispose(),否则会遇到内存问题。
如果您愿意,我还可以向您展示如何使用Pango文本呈现库。 与使用cairo库中的SetText()op相比,它们有些复杂,但要好得多。
M,干杯
您可以在没有Cairo的情况下进行绘制,但是至少使用C#认为已作废。
可以在这里找到最详尽的信息(尽管不多): http : //www.mono-project.com/docs/tools+libraries/libraries/Mono.Cairo/
就个人而言,正如#muszeo所述,我使用了自定义的DrawingArea :
public class MyWidget: Gtk.DrawingArea {
public MyWidget(int width, int height)
{
this.Width = width;
this.Height = height;
this.SetSizeRequest( width, height );
this.ExposeEvent += (o, args) => this.OnExposeDrawingArea();
}
/// <summary>
/// Redraws the widget
/// </summary>
private void OnExposeDrawingArea()
{
using (var canvas = Gdk.CairoHelper.Create( this.GdkWindow ))
{
// Draw with the canvas
// /* i.e. */ canvas.LineTo( 100, 100 );
canvas.Stroke();
// Clean
canvas.GetTarget().Dispose();
}
}
}
然后,您只需要在一个窗口中创建窗口小部件(也许是一个对话框?):
var dlg = new Gtk.Dialog( "Demo", this, Gtk.DialogFlags.Modal );
var swScroll = new Gtk.ScrolledWindow();
MyWidget widget = new MyWidget( 512, 512 );
swScroll.AddWithViewport( widget );
dlg.VBox.PackStart( swScroll, true, true, 5 );
dlg.AddButton( Gtk.Stock.Close, Gtk.ResponseType.Close );
dlg.ShowAll();
dlg.Run();
我保留了各种Gtk#简单演示的仓库,其中之一是一个非常基本的Chart类,使用Cairo来绘制图形:
http://github.com/baltasarq/GtkSharpDemo
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.