A simple setup for Python + Cairo + GTK/GDK pixel buffer - python

For my own benefit and possibly for educational use, I would like to make a pygame-like API for Python and Cairo. But I don't want it to be exactly pygame. I would instead like to make it a semi-static drawing platform that display one or more images using GTK/GDK, and I would like to imitate the excellent API principles of TiKZ (the latex package). The PyGame API is not bad, but I'm not satisfied with it. One particular issue is that I would like the package to handle window refresh by drawing everything into a pixbuf (with Cairo), and automatically redraw the pixbuf when the window is uncovered. That way the end programmer doesn't have to worry about window refresh. In fact, the end programmer shouldn't have to write a single class or function or any more than a straight sequence of lines of code to draw a smiley face (say). The graphics library also doesn't have to maintain an ever-longer list of stored shape objects as is the case in TkInter. (At least, I hope that Cairo doesn't do that against my intentions.)
I succeeded in drawing various things in pycairo with output to ImageMagick and Postscript. So I'm okay with pycairo itself.
Unfortunately, the cairo/gtk/pycairo/pygtk documentation that I found --- I don't know who it's written for, but not for me. At the moment, I am a Project Euler type of programmer, not a "5 bleeding edge ultra-object-oriented APIs" type of programmer. I'd like to see a clear explanation of what to do, and/or a clear example.
Okay, I accepted the one answer that was posted because it was at least a little helpful. But here in a nutshell is the real point. The point is that GDK make a temporary double buffer when you draw things in GDK, including using Cairo. It is expected that when you handle an expose event, you will just redraw everything. But if you have a very complicated image, this is a slow process, especially in Python. So it would be much nicer if Cairo could write to a permanent double buffer rather than a temporary one, and then that permanent double buffer would be exposed with GDK. Several developers have wanted a solution to this problem. One of the projects that seems to have some kind of solution is Google Chromium --- have you ever noticed how great window exposure is in Google Chrome, for instance in Linux? So I will look at the Chromium source code to see if I can do this easily.
Addendum: I see that I did confuse the issue by referring specifically to "pixbufs". I don't really care about pixbufs (and I changed the question title again). What I really care about is creating a permanent double buffer pixel array between Cairo and GTK/GDK, instead of a temporary double buffer pixel array. It seems that the easiest way to do that is to make the GTK window a Cairo surface and make the double buffer another Cairo surface. Since I asked for an sample in my question, here is some:
class Canvas(gtk.DrawingArea):
def __init__(self):
super(Canvas, self).__init__()
self.connect("expose_event", self.expose)
self.set_size_request(width,height)
def expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_surface(mybuffer,0,0)
cr.paint()
Another tricky issue that quickly arose is that I wanted this to be a WYSISWYG drawing environment that immediately draws what Python asks it to draw --- and that can be extended to animations. However, most GTK examples aren't set up that way: event handling is postponed until I either call gtk.main(). (Or in Python, I was surprised to discover that raw_input() also somehow flushes the GTK event queue.) I found a nice explanation, with Python examples, of alternatives to giving away event control to GTK. The simplest solution and possibly the one that I will adopt is to use this to flush the event buffer whenever you want to do that:
while gtk.events_pending(): gtk.main_iteration(False)
There is one final thing that I will need, to flush the pixel buffer as well as the event buffer. It looks like one way to do that is window.queue_draw()

As this was too big for a comment I have added this as a response.
The question is not quite clear. Do you mean to ask how to use cairo drawing to draw onto Gtk Widgets? Firstly, there is nothing called GTK Pixbuf, I think you are referring to GDK Pixbuf. Most the drawing stuff in GTK is done at GDK layer. If you want to find out about windowing, drawing mechanism or image manipulation you should look into GDK for more details. These links will hopefully help you get some insight about cairo-gdk interaction. Although my experience with python bindings for GTK, GDK & Cairo is nil, but I think that Google will provide you with some good resources if you look up gdk-cairo sample.
Hope this helps at least a bit!

Related

VTK Render Mouse Interaction (Python)

I want to visualize one or more STL file(s) using a vtk render viewport inside my application. I was able to get it all running with this example here: https://kitware.github.io/vtk-examples/site/Python/IO/ReadSTL/
My question is as follows: I have a mouse to control it and it is just unbelievable how bad default the controls of the camera are. It is almost impossible to get the model rotated intentionally or focus on a certain part. I am confused as I could not find any topic here or elsewhere discussing this. Normally I would read through other threads to find an answer, but there doesn't seem to be any. So, maybe you can point me to an approach or even certain functions of how I can change these settings, that would be really great! Basically I want to mimic the camera behavior of say, Paraview or a common CAD tool. Like zooming with mouse wheel, rotating with RMB and holding down the wheel to pan.
Some background on my project: I have written a python program and created a quite ok UI using tkinter. However, recently I was thinking of rewriting some basic parts of it and also upgrading everything visually and in terms of handling. So, I want to move to Qt widgets and, there shall be a VTK rendering viewport inside my application to show some of the stuff that can be interacted with.
I was able to find a solution in the tutorials. By explicitly defining the vtkInteractorStyle with
style = vtk.vtkInteractorStyleTrackballCamera()
The handling is just as I wanted it to be.

Get a reference to Gtk.OffscreenWindow cairo surface

I am using Gtk and WebKit from gi.repository using python on X11 server (on raspbian).
I have a Gtk.OffscreenWindow with a WebKit.WebView widget in it and I am looking for a way to get a reference to the actual surface data of the OffscreenWindow.
Gtk.OffscreenWindow.get_surface returns a cairo.XlibSurface object but it doesn't seem there is a way to access pixel data of the surface (get_drawable is missing).
Gtk.OffscreenWindow.get_pixbuf returns a pixel buffer but to my understanding this is a copy of the actual surface data.
I used get_snapshot method of the WebKit.WebView but it creates a new cairo.ImageSurface.
My final goal is to use the reference to draw the surface using pi3d and get any surface updates without having to get a new snapshot of the OffscreenWindow (which is quite slow).
From the GTK3 developer reference,
GtkOffscreenWindow derives from GtkWindow only as an implementation detail. Applications should not use any API specific to GtkWindow to operate on this object.
GTKOffscreenWindows cannot or should not be operated on as windows, thus Cairo cannot be used on them.
#kapetanos, You are probably familiar with the pi3d.groups conversation here https://groups.google.com/forum/#!topic/pi3d/4x0fPerYKRU
and the subsequent integration into pi3d
https://github.com/pi3d/pi3d_demos/blob/master/GtkCube.py and https://github.com/pi3d/pi3d_demos/blob/master/PyQtCube.py
I realize this is too late for your original question but it might help someone arriving here from a google search!
I still don't understand why the X11 drawing surface system that works on other linux implementations doesn't work on the Raspberry Pi but other developers seem to resort to using libbcm_host.so

How Can i open a subwindow with pygame?

I need to make a sub window using The pygame package, I want to do two type of subwindow, the first fixed in of the window and the second type completely independent of the window.
While approaching this problem, be aware that two windows is pretty much impossible for Pygame, since it is dependent on SDL and SDL is limited to 1 screen.
Maayyybbe, you could run two different programs that have different windows and can interact with each other via some networking you set up. But at this point, you'd probably be better off coding in something else.
Making a sort of subwindow is doable by splitting up your screen, and to use parts of it for one thing, and others for something else. For example, you can blit images to this separate "window" that have totally different things going on than the stuff outside of it.
Also, please google before posting a question, a quick google search revealed Pygame with Multiple Windows, which answers half of your question.

GUI-embeddable Python drawing widget with anti-aliasing

I am writing a small diagram drawing application (similar to Graphviz in spirit), and need a GUI library that would allow me to embed a canvas capable of drawing anti-aliased lines and text. I want to have a text editor in one half of the window to edit the diagram code and a (perhaps live) preview pane in the other.
Right now I have the text editor in a tkinter window and the rendered diagram in a separate pygame one. This technically works, but it's messy (e.g. having two event loops), and in general I would much prefer having both parts in one window. I have searched for ways of integrating the two, but haven't been able to find anything cross-platform, and pygame explicitly suggests not trying to do it.
An alternative would be to have pygame export the image into a file and load it back into tkinter, but tkinter can read only GIF/PPM without PIL (and I use Python 3, which PIL doesn't support) and pygame can't write GIF/PPM. I could backport to Python 2, since it's a tiny app, but even then, having a large extra library for a simple image conversion doesn't seem right, and the round-trip to a file will probably be too slow for live preview (not to mention ugly).
Finally, a simple tkinter canvas is almost what I want, except it can't draw anti-aliased lines, and for a program whose main purpose is to draw line figures, that is not acceptable.
I'm using Python 3 so libraries that support it are preferred, but if there's no way to do that whatsoever Python 2 libs are Ok as well. The library needs to be cross-platform, and of course, the fewer external packages are required, the better.
If you don't mind the way GTK looks, pygtk has an option for antialising in their canvas widget (see this) and is considered by many to be as powerful as Tkinter, though it is not included in standard Python installs.
Also, it's Python 3.x compatible, which can't be said of most non-standard library modules and packages.
Screwing around with Tkinter+pygame is silly. I would use wxPython. In fact, I've done a diagramming widget using wxPython, and it has anti-aliasing:
Unfortunately it was for work, so I can't distribute the code.
The wxPython classes you want to look at for anti-aliasing are wx.GCDC and/or wx.GraphicsContext.
After a thorough search I ended up using PyQt4. It does fit all my requirements (Python 3, cross-platform, anti-aliasing), and now that I've gotten through the basics, it's also quite intuitive and easy to use.
Posting this as an answer to my own question and accepting it for future reference.

2D animation in Python

I'm writing a simulator in Python, and am curious about options and opinions regarding basic 2D animations. By animation, I'm referring to rendering on the fly, not displaying prerendered images.
I'm currently using matplotlib (Wxagg backend), and it's possible that I'll be able to continue using it, but I suspect it won't be able to sufficiently scale in terms of performance or capabilities.
Requirements are:
Cross-platform (Linux, MacOS X,
Windows)
Low complexity overhead
Plays well with wxpython (at least won't step on each other's toes unduly)
Interactivity. Detect when objects are clicked on, moused over, etc.
Note that high performance isn't on the list, but the ability to handle ~100 bitmap objects on the screen would be good.
Your thoughts?
I am a fan of pyglet which is a completely self contained library for doing graphical work under win32, linux, and OS X.
It has very low overhead, and you can see this for yourself from the tutorial on the website. It should play well with wxpython, or at least I seem to recall posts to the mailing list about wxpython and pyglet being used together.
It however does not offer selection of objects via mouse clicks - this you will have to handle yourself. Generally speaking for a 2D application this is not too difficult to do.
mactorii is an OS X application of mine written in pure python+pyglet, and has some basic animation (scrolling) and click detection. It doesn't use wxpython, but perhaps it will give you an idea of what is involved. Note however mactorii is using the old pyglet api, so the run loop I have in there is obsolete. I will get around to updating it one day... :P
You can try pygame, its very easy to handle and similar to SDL under c++
Arcade works on any platform with OpenGL 3.3+ (i.e. not the Raspberry Pi, but most other platforms). Although it's intended for simple games, Arcade offers great bitmap and sprite handling, as well as simple graphics primitives such as rectangles, arcs and circles.

Categories

Resources