#c #segmentation-fault #cairo #gtkmm
#c #ошибка сегментации #cairo #gtkmm
Вопрос:
У меня возникли некоторые проблемы при создании Cairo::RefPtr в контексте Cairo. Я действительно не могу себе представить, почему это ошибка segfaults, за исключением того, что указатель указывает на что-то совершенно неправильное.
Это мой код.
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
Gtk::DrawingArea drawarea;
window.add(drawarea);
Cairo::RefPtr<Cairo::Context> ccontext = drawarea.get_window()->create_cairo_context();
Gtk::Allocation allocation = drawarea.get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
Gtk::Main::run(window);
}
И это то, что говорит GDB:
Запуск программы: /home/marian/Desktop/C /Langton/Langton [Включена отладка потоков с использованием libthread_db]
Программа получила сигнал SIGSEGV, ошибка сегментации. 0xb7be852e в Gdk::Window::create_cairo_context() () из /usr/lib/libgdkmm-3.0.so.1
Я скомпилировал это с помощью gcc (GCC) 4.6.1 20110819 (предварительная версия).
Заранее спасибо
Комментарии:
1. Возможно, мне следует предоставить больше информации. Это более или менее напрямую из ссылки gtkmm, код должен быть правильным. Я скомпилировал его с помощью:
g main.cc -g -o Langton
pkg-config —cflags —libs cairomm-1.0 gtkmm-3.0` ` Это было скомпилировано в Arch Linux с установленным Gtkmm3.2.0-1 и Cairomm-1.10.0-1
Ответ №1:
Gtk::Widget::get_window() возвращает нулевое значение Glib::RefPtr, поскольку виджет еще не реализован.
Основываясь на документации GtkDrawingArea, вам необходимо подключить сигнал «рисовать» для обработки рисования, где ваш контекст Cairo уже создан и передан вам. Возвращаясь к ссылке Gtkmm, вы должны использовать Gtk::Widget::signal_draw(), чтобы подключиться к ней, или вы можете перегрузить виртуальную функцию on_draw() для обработки вашего чертежа.
Кроме того, вам также необходимо вызвать .show() для каждого виджета, то есть для вашей области рисования и вашего окна, и вызвать ccontext-> stroke(), чтобы получить фактически нарисованную линию.
Результат будет выглядеть примерно так:
#include <gtkmm.h>
bool draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext, Gtk::DrawingArea *drawarea)
{
Gtk::Allocation allocation = drawarea->get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
ccontext->stroke ();
return true;
}
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
Gtk::DrawingArea drawarea;
drawarea.signal_draw ().connect (sigc::bind (sigc::ptr_fun (amp;draw),
amp;drawarea));
window.add(drawarea);
window.show_all ();
Gtk::Main::run(window);
return 0;
}
или в качестве альтернативы:
#include <gtkmm.h>
class LineBox : public Gtk::DrawingArea
{
protected:
virtual bool on_draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext);
};
bool LineBox::on_draw (const Cairo::RefPtr<Cairo::Context> amp;ccontext)
{
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
ccontext->set_source_rgb(1.0, 0.0, 0.0);
ccontext->set_line_width(2.0);
ccontext->move_to(0,0);
ccontext->line_to(width, height);
ccontext->stroke ();
return true;
}
int main(int argc, char * argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window window;
LineBox drawarea;
window.add(drawarea);
window.show_all ();
Gtk::Main::run(window);
return 0;
}