在绘制信号上保留绘图区域"图像"

Preserve DrawingArea 'image' on draw signal

本文关键字:区域 图像 绘图 保留 绘制 信号      更新时间:2023-10-16

我试图在可以用鼠标绘画的地方制作简单的正方形。问题是,每当发生拉动信号时,开罗表面似乎已完全清除。我了解这一点,因为第一次queue_draw()白色背景消失了,我看到了我的GTK主题颜色(灰色(。

我以为我可以保存表面或上下文,但是您不能只在开罗中创建空表面,也不能使用this->get_window()->create_cairo_surface()创建它(其中this是从Gtk::DrawingArea继承的类的对象(,因为当调用构造函数时,窗口小部件尚未连接到任何窗口上,因此它是一个空指针。我的意思是,我可以创建一些称为you_are_added_to_window_create_cairo_surface()的公共功能,但我真的很想不这样做。

所以我真的不知道该怎么做,我对开罗不了解。

我如何保存或保存"帆布"的当前状态,因此实际绘制的内容仅应用于现有图纸上?

这是我班级的回调函数:

bool MyDrawingArea::on_draw(const Cairo::RefPtr<Cairo::Context> & cr) {
    /* clear and fill background with white in the beginning */
    if (first_draw) {
        cr->save();
        cr->set_source_rgb(255.0, 255.0, 255.0);
        cr->paint();
        cr->restore();
        first_draw = false;
    }
    cr->save();
    cr->set_source_rgb(0.0, 0.0, 0.0);
    cr->begin_new_path();
    while (!dots_queue.empty()) {
        auto dot = dots_queue.front();
        cr->line_to(dot.first, dot.second);
        dots_queue.pop();
    }
    cr->close_path();
    cr->stroke();
    cr->restore();
    return false;
}

删除first_draw,而不是dots_queue.pop(),只是在dots_queue上迭代,并每次重新绘制全部。

draw函数不适合"我想添加一些图纸"。取而代之的是,"嘿,窗口系统不知道应该在这里绘制什么,请用内容填充此内容"。这就是为什么开罗表面被清除。

因此,在存储所有操作有效的同时,如果您试图让程序保存图纸,则实际上是不对的,您将必须使用第二表面来保存所有内容。

我的解决方案结合了Uli Schlachter的两个答案。

首先,我有结构,自上次按钮以来,我在其中存储最后一个绘图动作,直到按钮释放为止。这使我可以实时显示诸如线路之类的东西,同时保持画布清洁。

第二,我将所有绘制的所有东西都存储在表面上,这是这样创建的:

// this - is object of class, derived from DrawingArea
auto allocation = this->get_allocation(); 
this->surface = Cairo::ImageSurface::create(
    Cairo::Format::FORMAT_ARGB32,
    allocation.get_width(),
    allocation.get_height()
);

然后,在每个draw信号上,我像这样还原:

cr->save();
cr->set_source(surface, 0.0, 0.0);
cr->paint();
cr->restore();

每当我想保存表面,即应用于画布时,我会执行以下操作:

Cairo::RefPtr<Cairo::Context> t_context = Cairo::Context::create(surface);
t_context->set_source(cr->get_target(), -allocation.get_x(), -allocation.get_y());
t_context->paint();

这是重要的时刻。如果不调整分配坐标,您的画布将在每个表面上滑动并恢复。

这样,我可以轻松地将图纸放在画布上,从文件加载帆布(因为我使用imagesurface(或将其保存到文件中。