Segfault when creating smartpointer on CairoContext - c++

I got some problems when creating a Cairo::RefPtr on a Cairo-Context.
I really can't imagine why this segfaults, except the pointer ist pointing on something completely wrong.
This is my code.
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);
}
And this is what GDB says:
Starting program: /home/marian/Desktop/C++/Langton/Langton [Thread
debugging using libthread_db enabled]
Program received signal SIGSEGV, Segmentation fault. 0xb7be852e in
Gdk::Window::create_cairo_context() () from /usr/lib/libgdkmm-3.0.so.1
I compiled this with gcc (GCC) 4.6.1 20110819 (prerelease).
Thanks in advance

Gtk::Widget::get_window() returns a null Glib::RefPtr, since the widget has not been realized just yet.
Based on the GtkDrawingArea documentation, you need to hook onto the "draw" signal to handle drawing, where your Cairo context is already created and handed to you. Going back to the Gtkmm reference, you would use Gtk::Widget::signal_draw() to hook onto that, or you could overload the virtual on_draw() function to handle your drawing.
Additionally, you also need to call .show() on each widget, i.e. your DrawingArea and your Window, and call ccontext->stroke() to get the line actually drawn.
The result would look something like:
#include <gtkmm.h>
bool draw (const Cairo::RefPtr<Cairo::Context> &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 (&draw),
&drawarea));
window.add(drawarea);
window.show_all ();
Gtk::Main::run(window);
return 0;
}
or alternatively:
#include <gtkmm.h>
class LineBox : public Gtk::DrawingArea
{
protected:
virtual bool on_draw (const Cairo::RefPtr<Cairo::Context> &ccontext);
};
bool LineBox::on_draw (const Cairo::RefPtr<Cairo::Context> &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;
}

Related

How to make a point appear using fltk?

After creating a window and drawing some shapes in it, I realized I cant make a point and just appear it on the window. I've searched the manual but I cant make anything out of it. Im using the fltk 1.3.0. How can I do it ?
Fltk comes with a bunch of example projects that are helpful. If you look at the line_style example you can easily reduce it to something drawing points like this:
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
class TestWindow : public Fl_Window {
void draw()
{
fl_color(255, 0, 0);
fl_begin_points();
fl_point(50, 50);
fl_point(51, 51);
fl_end_points();
}
public:
TestWindow(int w, int h, const char *l = 0)
: Fl_Window(w, h, l) {}
};
int main(int argc, char ** argv) {
Fl_Window *window = new TestWindow(200, 200);
window->end();
window->show(argc, argv);
return Fl::run();
}
But just as a word of advice, drawing single points directly onto the window is rarely the smart thing to do. Drawing into images/buffers and then displaying them is the better alternative most of the time.
edit:
here's is an example of putting the drawing code in the main function.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_draw.H>
class TestWindow : public Fl_Window {
void draw() {}
public:
TestWindow(int w, int h, const char *l = 0) : Fl_Window(w, h, l) {}
};
int main(int argc, char ** argv) {
Fl_Window *window = new TestWindow(200, 200);
window->end();
window->show(argc, argv);
window->make_current();
fl_color(255, 0, 0);
fl_begin_points();
fl_point(50, 50);
fl_point(51, 51);
fl_end_points();
return Fl::run();
}
You should take notice of the disclaimer for make_current in the manual
Danger: incremental update is very hard to debug and maintain!
None of this is good practise beyond using it for simple exercises.
Based on the previous answer to this question, I found this in the documentation:
fl_begin_points()
Starts drawing a list of points.
Points are added to the list with fl_vertex()
So this is some code that shows some points (I added more to really see the points):
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
class Drawing : public Fl_Window {
void draw(){
fl_begin_points();
//adding cushion to points to be able to see them.
//center at 10,10
fl_vertex(9,9);
fl_vertex(9,10);
fl_vertex(9,11);
fl_vertex(10,9);
fl_vertex(10,10);
fl_vertex(10,11);
fl_vertex(11,9);
fl_vertex(11,10);
fl_vertex(11,11);
fl_end_points();
fl_color(FL_BLACK);
}
public:
Drawing(int w, int h, const char *l = 0) : Fl_Window(w, h, l){}
};
int main(int argc, char **argv){
Fl_Window *window = new Drawing(340,180);
window->end();
window->show(argc, argv);
return Fl::run();
}

How can I get cursor position with Gtkmm?

Which Gtkmm functions can help me get the position(x,y) of the cursor. According to this, C# has
Gdk.Display.Default.WarpPointer(Gdk.Display.DefaultScreen, 20, 20);
Windows has
GetCursorPos
Qt has
QCursor::pos()
Gtkmm has what?
Here you are.
#include <stdio.h>
#include <gtkmm.h>
int main(int argc, char* argv[]) {
Gtk::Main gtkm(argc, argv);
Glib::RefPtr<Gdk::Display> disp = Gdk::Display::get_default();
Glib::RefPtr<Gdk::Screen> scrn = disp->get_default_screen();
Gdk::ModifierType mods;
int xpos, ypos;
disp->get_pointer(scrn, xpos, ypos, mods);
printf("xpos = %d, ypos = %d\n", xpos, ypos);
return 0;
}

Fl_Window subclass doesn't work

As titled above, i'm trying to get an extremely simple FLTK 1.3.3 application working.
But, even with only a simple Fl_Window and 1 Fl_Button, nothing seems to work. Can anyone help?
class MainEditorWindow : public Fl_Window
{
public:
MainEditorWindow(int _width, int _height, std::string _title);
~MainEditorWindow();
virtual void draw();
virtual int handle(int _event);
private:
Fl_Button* m_btnExit;
};
And here is the Implementation
MainEditorWindow::~MainEditorWindow()
{
}
int MainEditorWindow::handle(int _event)
{
return 1;
}
void MainEditorWindow::draw()
{
m_btnExit->redraw();
}
MainEditorWindow::MainEditorWindow(int _width, int _height, std::string _title) : Fl_Window(_width, _height, _title.c_str())
{
this->begin();
m_btnExit = new Fl_Button(0, 0, 40, 40, "EXIT");
m_btnExit->color(FL_RED);
this->color(FL_WHITE);
this->end();
}
But when simply running the application like this:
int main(int argc, char** argv)
{
MainEditorWindow* mw = new MainEditorWindow(800, 600, "SHIP Editor");
mw->show(argc,argv);
return Fl::run();
}
The window shows up fine, its resizable movable etc, the draw() - function is being called and all that. But the window itself is just blank. It simply shows nothing, especially not the Fl_Button. Can anybody tell me why this occurs? As far as i can tell, there should be nothing particularily wrong with my code.
You need to call Fl_Window::draw()
void MainEditorWindow::draw()
{
m_btnExit->redraw();
Fl_Window::draw();
}
And maybe you want the button is clickable too
int MainEditorWindow::handle(int _event)
{
//return 1;
return(Fl_Window::handle(_event));
}
Try this in your MainEditorWindow constructor:
MainEditorWindow(int _width, int _height, const std::string& _title)
: Fl_Window(_width, _height, _title.c_str()) {
// begin grouped GUI object creation
Fl_Group::begin();
// alter x,y coords of button as necessary
m_btnExit = new Fl_Button(0,0,40,40,"EXIT");
m_btnExit->color(FL_RED);
// end grouped GUI object creation
Fl_Group::end();
// defines resizable widget for group
Fl_Group::resizable(this);
this->color(FL_WHITE);
// display window
Fl_Window::show();
}
Then in main:
int main(int argc, char** argv) {
MainEditorWindow mw(800, 600, "SHIP Editor");
return Fl::run();
}
Here we have added the button to a group and then invoked Fl_Window::show() inside the constructor to display it.
Note there is no need to make mw a pointer to MainEditorWindow in main.

passing argument/arguments signal to callback on GTK+ in C

Here is my code:
#include <gtk/gtk.h>
G_MODULE_EXPORT void waka(GtkWidget *button, GtkWidget* entry1)
{
printf("%s",gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(waka),entry);
entry = gtk_entry_new();
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE,2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
When I launch it, and try to fill in some string in the entry box, and then click the button, it said 'segmentation fault'. What is going on?
Also, the callback only works with one user data argument. How about if I want two or more arguments, what must I do in the callback function, and in the call to g_signal_connect()?
the problem is that you're trying to use pointer to entry before initializing it. I've changed a bit your code to fix this, see if it will work for you:
#include <gtk/gtk.h>
void waka(GtkWidget *button, GtkWidget* entry1)
{
g_print("entry: %s\n", gtk_entry_get_text(GTK_ENTRY(entry1)));
}
int main(int argc, char * argv[])
{
GtkWidget *window, *button, *entry, *vbox;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label("hha");
entry = gtk_entry_new();
vbox = gtk_vbox_new(FALSE, 2);
gtk_box_pack_start_defaults(GTK_BOX(vbox),button);
gtk_box_pack_start_defaults(GTK_BOX(vbox),entry);
gtk_container_add(GTK_CONTAINER(window),vbox);
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(waka), entry);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
hope this helps, regards

Drawing any rectangle to a GTK+ DrawingArea fills the whole DrawingArea

I have a GTK+ DrawingArea that should display a rectangle in the top left corner. When I draw the rectangle using Cairo, the whole drawing area is filled with the color of the rectangle. How can I prevent that? Why does Cairo do that? What am I doing wrong?
#include <gtkmm.h>
class Window : public Gtk::Window
{
private:
Gtk::DrawingArea area;
bool on_area_expose(GdkEventExpose* event)
{
Gtk::Allocation allocation = area.get_allocation();
Cairo::RefPtr<Cairo::Context> context =
area.get_window()->create_cairo_context();
int width = allocation.get_width();
int height = allocation.get_height();
context->set_source_rgba(0, 0, 0, 1);
context->rectangle(0, 0, double(width)/10, double(height)/10);
context->paint();
return true;
}
public:
Window() : Gtk::Window()
{
area.signal_expose_event().connect(
sigc::mem_fun(*this, &Window::on_area_expose));
add(area);
}
};
int main(int argc, char* argv[])
{
Gtk::Main app(argc, argv);
Window window;
window.show_all();
Gtk::Main::run(window);
return 0;
}
I compiled the code using
g++ gtktest.cpp `pkg-config --libs --cflags gtkmm-2.4` -o gtktest
context->paint() paints the current source everywhere within the current clip region. The proper method to call is Gtk::Context::fill.