Main Window Operation In Matplotlib

Matplotlib is a MATLAB-like library that allows Python programmers to create images and animations. For example, you can easily draw a graphic representation of functions with Y (and maybe Z) values generated by numpy and scipy functions.
Matplotlib can also be interactive and handle events. The command mpl_connect is used for connecting an event with a callback function.

The Backend Layer

Someone on the IRC has challenged me with questions on how to perform some operations when the window is closed. In addition, I want the window title to be other than the default, “Figure 1”.
enter image description here

Well, the layer that handles the main window is the backend layer,
To find what backend Matplotlib uses, you can add the line
print type(fig.canvas)
The result may be something like:
<class 'matplotlib.backends.backend_gtkagg.FigureCanvasGTKAgg'>
This means that the backend used is ‘GtkAgg’.
With the function ‘dir’, I’ve found that the canvass has a function named get_toplevel, and the returned value of fig.canvass.get_toplevel() is an object of type gtk.Window.
This object has the methods of a GTK window. So you can change its title with the ‘set_titlemethod. For example:
fig.canvas.get_toplevel().set_title(‘Rubic Cube’)
You can tell your application what to do when the user closes the window, by calling its 'connect' method, with 'destroy' for first arguments.
For example:
fig.canvas.get_toplevel().connect(‘destroy’, destroyFunc, ‘Goodbye, cruel world!’)
destroyFunc` is a function that accept 2 arguments (3 if a class member): the widget where the event has occurred and additional user defined data.
More about Python FTK can be found at http://www.pygtk.org/pygtk2tutorial/index.html

Last but not least, you can specify the backend Matplotlib will use, by calling the ‘use’ method of matplotlib.
For example:
matplotlib.use('GTKAgg')

Note: This method should be called before importing ‘pyplot’.

Written with StackEdit.

Advertisements

Creating Custom Cursors With GDK-Pixbuf-2 And Cairo

Wait! Why use GDK-2 when there ate later stable versions you can download for free? Sometimes you use a tool – such as OpenCV – that integrates with GTK-2, and GDK-2.

Your operating system may allow you to create custom cursor, or mouse pointers, of your own with colors and an alpha channel (opacity). GDK allows you to create a cursor from a pixel buffer (pixbuf), using the function ‘gdk_cursor_new_from_pixbuf‘.  OK, but first let’s make a pixel buffer. In the documentation of GDK 3, I found 2 functions to create a pixbuf: gdk_pixbuf_get_from_window and gdk_pixbuf_get_from_surface. The latter does not exist in GDK-2. However, there is one method, I haven’t found documented` It’s called gdk_pixbuf_new_from_data.  You can get the data from Cairo after you’ve drawn your image using Cairo.

Using Cairo might be a bit confusing because::

  • Cairo uses two data types for color channels: double-precision floating-point numbers and unsigned 8-bit integers.
  • The color of the cursor is not as intended when calling ‘cairo_set_source_rgba’.

The following function in C will demonstrate what I mean:

Here, when the cursor is created its color is yellow, but if you save your created image to a file it will be cyan.

Yellow cursor over the red square.
Yellow cursor over the red square.

The image when saved to a PNG file

The image when saved to a PNG file

void createCursor(){
    double arcEnd=2*M_PI;
    GdkPixbuf *pixbuf;
    int stride=cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, 10); // Will be used later, when we'll create the pixbuf.
    cairo_surface_t *surf=cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 10, 10); // A canvas of width 10 and height 10.
    cairo_t *cairo_ctx = cairo_create(surf);
    cairo_set_source_rgba(cairo_ctx, 0., 1., 1., 1.); // Double precision values for Red, Green, Blue and Alpha channels between 0 and 1.

    cairo_arc(cairo_ctx,5,5,4,0,arcEnd); // Draw a circle or an arc of a circle whose center is at (5,5) and whose radius is 4
                                         // The arc begins at angle 0 and ends in angle 2Π
    cairo_fill(cairo_ctx); // Fill the circle with cyan, though we've intended to create a yellow one.

    // Create an example image for the blog
    cairo_surface_write_to_png(surf, "/tmp/fortheblog.png");

    guchar *data = cairo_image_surface_get_data(surf); // The data is in BGR, reverse order of RGB !!!

    pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, true, 8, 10, 10, stride, NULL, NULL); // Stride is the difference in bytes between two
                                                                                                      // consecutive rows.
    cursor=gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, 5, 5);

}

“cursor” in this function is a global variable of type “GdkCursor *”.Now, to add the cursor to a window, use gdk_window_set_cursor.

The “gtk_pixbuf_new_from_data” Function.

This function uses the data returned from the function “cairo_image_surface_get_data”. The data is a pointer to a character. The function receiving the data doesn’t know how many characters are referred to, and how to split it into rows and columns. Following is its prototype:

GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data,
                     GdkColorspace colorspace,
                     gboolean has_alpha,
                     int bits_per_sample,
                     int width, int height,
                     int rowstride,
                     GdkPixbufDestroyNotify destroy_fn,
                     gpointer destroy_fn_data);