我正在尝试制作简单的方块,您可以用鼠标绘画。问题是,每当绘制信号发生时,cairo表面似乎完全被清除。我理解这一点是因为在第一个queue_draw()
白色背景消失后我看到了我的GTK主题颜色(灰色)。
我以为我可以保存表面或上下文,但你不能在cairo中创建空表面,我无法使用this->get_window()->create_cairo_surface()
创建它(其中this
是对象继承自Gtk::DrawingArea
)的类,因为当调用构造函数时,窗口小部件尚未附加到任何窗口,因此它是一个空指针。我的意思是,我可以创建一些名为you_are_added_to_window_create_cairo_surface()
的公共函数,但我真的不喜欢这样做。
所以我真的不知道该做什么以及我对cairo不了解。
如何保存或保存画布'当前状态,所以实际绘制的内容只适用于现有绘图?
这是我班级的回调函数:
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;
}
答案 0 :(得分:1)
删除dots_queue.pop()
而不是dots_queue
,只需遍历draw
并重新绘制所有这些内容。
{{1}}功能不适用于&#34;我想添加一些绘图&#34;。相反,它是&#34;嘿,窗口系统不知道应该在这里绘制什么,请填写内容&#34;。这就是清除cairo表面的原因。
答案 1 :(得分:0)
因此,虽然存储所有操作都有效,但如果您尝试让程序保存图形,则确实不行,您将不得不使用第二个表面来保存所有内容。
我的解决方案结合了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),或者将其保存到文件中。