繁体   English   中英

如何使用Gtk Sharp和C#创建Cairo Context以在代码中进行绘制

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM