如何在 Gtk+ 中使用 Cairo 进行离屏绘图?

发布于 2024-10-04 06:58:09 字数 166 浏览 0 评论 0原文

我正在尝试在开罗图像上下文中进行绘画工作。有没有办法在暴露事件时将图像上下文的内容加载到开罗上下文?

例如,我想根据绘图区域上的光标移动绘制一系列点,如果我想保留所有点,我应该使用离屏缓冲区,所以我使用图像上下文,但我找不到方法在暴露事件上将其绘制到开罗上下文...

有什么解决方案吗?

I'm trying to do my drawing stuff in an Cairo Image Context. Is there a way to load the content of the Image context to a Cairo Context on expose event?

For example I want to draw a series of dots based on cursor movements over a drawing area, If I want to keep all the dots I should use an off-screen buffer, so I use an Image Context, but I cannot find a way to draw it to the Cairo Context on expose event...

any solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

醉南桥 2024-10-11 06:58:09

我自己找到了解决方案!

这里是:

using Cairo; 
using Gtk;

public class Canvas : Gtk.DrawingArea{
public Canvas(MainWindow mw){
    stdout.printf("-> Canvas\n");

    main_window = mw;
    is_pressed_down = false;

    add_events(Gdk.EventMask.BUTTON_PRESS_MASK |
              Gdk.EventMask.BUTTON_RELEASE_MASK |
                      Gdk.EventMask.POINTER_MOTION_MASK);

            set_size_request(400, 300);
}

~Canvas(){
    stdout.printf("<- Canvas\n");
}

public override void realize(){
    base.realize();
    stdout.printf("realize\n");
}

protected override bool configure_event(Gdk.EventConfigure event){
    int x, y;

    window.get_size(out x, out y);
    offscreen_surface = new Cairo.ImageSurface(Cairo.Format.RGB24, x, y);
    gc = new Cairo.Context(offscreen_surface);
    gc.set_antialias(Antialias.NONE);
    gc.set_line_width(1);
    gc.set_source_rgb(1, 1, 1);
    gc.paint(); // it will make trouble if user resize the window

    string msg = "x: " + x.to_string() + ", y: " + y.to_string();
    main_window.set_statusbar(msg);

    return true;
}

protected override bool expose_event(Gdk.EventExpose event){

    var tgc = Gdk.cairo_create(window); //!!!
    tgc.set_source_rgb(1, 1, 1);
    tgc.paint();

    tgc.set_source_surface(offscreen_surface, 0, 0);
    tgc.paint();

    return true;
}

public override bool motion_notify_event(Gdk.EventMotion event)
{
    string msg = "x: " + event.x.to_string() + ", y: " + event.y.to_string();
    main_window.set_statusbar(msg);

    if(is_pressed_down){
        //gc.set_source_rgb(1, 1, 1);
        //gc.paint();
        gc.set_source_rgb(1, 0.5, 0);

        //gc.move_to(event.x, event.x);
        gc.arc(event.x, event.y, 1, 0, 360);        
        gc.stroke();

        weak Gdk.Region region = this.window.get_clip_region();
        this.window.invalidate_region(region, true);
        this.window.process_updates(true);
    }

    return true;
}

public override bool button_press_event(Gdk.EventButton event)
{
    stdout.printf("Canvas.button_press_event\n");
    is_pressed_down = true;
    return true;
}

public override bool button_release_event(Gdk.EventButton event)
{
    stdout.printf("Canvas.button_release_event\n");
    is_pressed_down = false;
    return true;
}

public Cairo.Context    get_context(){
    return gc;
}

private Cairo.Context       gc;
private weak MainWindow main_window;
private Cairo.ImageSurface  offscreen_surface;
private bool                is_pressed_down;
}

I found the solution myself!

here it is:

using Cairo; 
using Gtk;

public class Canvas : Gtk.DrawingArea{
public Canvas(MainWindow mw){
    stdout.printf("-> Canvas\n");

    main_window = mw;
    is_pressed_down = false;

    add_events(Gdk.EventMask.BUTTON_PRESS_MASK |
              Gdk.EventMask.BUTTON_RELEASE_MASK |
                      Gdk.EventMask.POINTER_MOTION_MASK);

            set_size_request(400, 300);
}

~Canvas(){
    stdout.printf("<- Canvas\n");
}

public override void realize(){
    base.realize();
    stdout.printf("realize\n");
}

protected override bool configure_event(Gdk.EventConfigure event){
    int x, y;

    window.get_size(out x, out y);
    offscreen_surface = new Cairo.ImageSurface(Cairo.Format.RGB24, x, y);
    gc = new Cairo.Context(offscreen_surface);
    gc.set_antialias(Antialias.NONE);
    gc.set_line_width(1);
    gc.set_source_rgb(1, 1, 1);
    gc.paint(); // it will make trouble if user resize the window

    string msg = "x: " + x.to_string() + ", y: " + y.to_string();
    main_window.set_statusbar(msg);

    return true;
}

protected override bool expose_event(Gdk.EventExpose event){

    var tgc = Gdk.cairo_create(window); //!!!
    tgc.set_source_rgb(1, 1, 1);
    tgc.paint();

    tgc.set_source_surface(offscreen_surface, 0, 0);
    tgc.paint();

    return true;
}

public override bool motion_notify_event(Gdk.EventMotion event)
{
    string msg = "x: " + event.x.to_string() + ", y: " + event.y.to_string();
    main_window.set_statusbar(msg);

    if(is_pressed_down){
        //gc.set_source_rgb(1, 1, 1);
        //gc.paint();
        gc.set_source_rgb(1, 0.5, 0);

        //gc.move_to(event.x, event.x);
        gc.arc(event.x, event.y, 1, 0, 360);        
        gc.stroke();

        weak Gdk.Region region = this.window.get_clip_region();
        this.window.invalidate_region(region, true);
        this.window.process_updates(true);
    }

    return true;
}

public override bool button_press_event(Gdk.EventButton event)
{
    stdout.printf("Canvas.button_press_event\n");
    is_pressed_down = true;
    return true;
}

public override bool button_release_event(Gdk.EventButton event)
{
    stdout.printf("Canvas.button_release_event\n");
    is_pressed_down = false;
    return true;
}

public Cairo.Context    get_context(){
    return gc;
}

private Cairo.Context       gc;
private weak MainWindow main_window;
private Cairo.ImageSurface  offscreen_surface;
private bool                is_pressed_down;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文