How to create a PixBuf from file with Gdk3? - python

Environment: Python3
Libraries:
from gi.repository import Gtk, Gdk
import cairo
I want to create a 'pixbuf from file' but the method does not longer exist in Gdk3.
pb = Gdk.pixbuf_new_from_file('sunshine.png')
Gdk.cairo_set_source_pixbuf(cr, pb, 0, 0)
Result in: AttributeError: 'gi.repository.Gdk' object has no attribute 'pixbuf_new_from_file'
Does anybody know how to do this with Gdk3?
Seems that Gdk3 only support these methods:
gdk_pixbuf_get_from_window
gdk_pixbuf_get_from_surface
Update
Found it out myself:
image = Gtk.Image()
image.set_from_file('sunshine.png')
pixbuf = image.get_pixbuf()
Gdk.cairo_set_source_pixbuf(cr, pixbuf, 10, 10)

The question is old, but maybe it helps someone:
from gi.repository import GdkPixbuf
pixbuf = GdkPixbuf.Pixbuf.new_from_file('sunshine.png')
Tested on GdkPixbuf._version == '2.0'

I dont know much about python, but in general you should not using gtk image directly to load file. Use GdkPixbuf instead because of error handling. The reason there is no attribute (in python) "pixbuf new from file", is because for much of the GdkPixbuf handling, still using (in C) gdk-pixbuf-2.0. Why they haven't port or still keeping it, I have no idea. In python you have to find the "gdk pixbuf" module instead of using GDK3, as Schcriher pointed out.

Related

Type checking for PyGObject/GTK3

I'm new to GTK3 so I thought it would be a good idea to use type checking to have instant access to the docs. However I can't make it work. This is the code I'm using to test if it works.
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
mainBox: Gtk.Box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=1)
Box is defined inside Gtk.pyi and Pycharm says it is overriden by ToolbarGTK3 but when I run the above code the runtime type is gi.override.Gtk.Box and this is confusing to me. Thanks in advance!

Python PyGObject pixbuf memory leak

I'm retrieving a JPEG from gphoto2, creating a Gio stream from the data and then creating a Pixbuf from the stream:
import gphoto2 as gp
from gi.repository import Gio, GdkPixbuf
camera = gp.Camera()
context = gp.Context
camera.init(context)
file = gp.CameraFile()
camera.capture_preview(file, context)
data = memoryview(file.get_data_and_size())
stream = Gio.MemoryInputStream.new_from_data(data)
pixbuf = GtkPixbuf.Pixbuf.new_from_stream(stream)
# display pixbuf in GtkImage
The function doing this is attached to the Gtk idle event using GLib.idle_add(...). It works, but it leaks memory. The process's memory use climbs continually. It leaks even when the line constructing the pixbuf is commented out, but not when the line constructing the stream is also commented out, so it seems that it is the stream itself that is leaking. Adding stream.close() after constructing the pixbuf doesn't help.
What's the right way to release the memory here?
I wouldn't call it an answer as such, and if someone knows a direct answer to the question I'm happy to mark it as the right answer, but here's a workaround for anyone else in the same position:
import gphoto2 as gp
from gi.repository import Gio, GdkPixbuf
camera = gp.Camera()
context = gp.Context
camera.init(context)
file = gp.CameraFile()
camera.capture_preview(file, context)
data = memoryview(file.get_data_and_size())
loader = GdkPixbuf.PixbufLoader.new()
loader.write(data)
pixbuf = loader.get_pixbuf()
# use the pixbuf
loader.close()
This no longer leaks memory.

Python interpreter, Pygtk and GtkGrid

i've to use GtkGrid because i need to draw a rectangle for every item i have.
(i would add a Drawing area to every GtkGrid's cell and draw the rectangle by cairographics library)
But there was a problem: python 2.7 doesn't support GtkGrid, so i surfed the web and i simply changed the first line of my file (and installed python3.3).
#!/usr/bin/python3.3
try:
import pygtk
pygtk.require("2.0")
except:
print("PyGtk Not Availible")
sys.exit(1)
try:
import gtk
import gtk.glade
except:
print("GTK Not Availible")
sys.exit(1)
Now it cannot rescue anymore Pygtk or GTK libraries.. and with python2.7 all work fine..
Maybe the best solution would be to avoid newer python interpreters and change GtkGrid into something else..
Help me please
EDIT::
Just cut and pasted an example from Pygtk examples
#!/usr/bin/python3.3
# example drawingarea.py
import pygtk
pygtk.require('2.0')
import gtk
import operator
import time
import string
class DrawingAreaExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Drawing Area Example")
window.connect("destroy", lambda w: gtk.main_quit())
self.area = gtk.DrawingArea()
self.area.set_size_request(400, 300)
self.pangolayout = self.area.create_pango_layout("")
self.sw = gtk.ScrolledWindow()
...
With Python 2.7 it works, with Python 3.3: No module named 'pygtk'
Just to make this clear: You have to decide wether you want to use the gi.introspection bindings (which are up to date and mostly autogenerated) or the pygtk wrapper around gtk+-2.0 (hand crafted, as of now pygtk3 is still work in progress, correct me if I am wrong).
Mixing these will get you in trouble further or later.
Also your initial issue was, GtkGrid (part of gtk+-3.0) was part of the gi.introspection bindings which (usually) require Python 3.x.y, whereas you used pygtk2 with Python 2.7.x. Changing to Python 3.3 just made the bindings availiable to you.
In gtk2 GtkGrid was called GtkTable, see https://developer.gnome.org/gtk2/stable/GtkTable.html.
Try this:
#!/usr/bin/env python
# -*- coding: utf-8; -*-
from gi.repository import Gtk
grid = Gtk.Grid()
You need to use GTK+ 3, not python3.3 (in order to have a Gtk.Grid)... if i understand what you mean...
Edited.

Get GTK+ theme colors with python and GObject introspection

With introduction of GObject introspection the way to access theme colors through widget.get_style() method is gone. I am interested on how to get theme colors when GTK+ is used through GOBject introspection. The solution should preferably work with both versions (2 and 3) but a solution for each of these is acceptable as well.
I'm not sure how to get it from gtk+-2.0, unless your using a pure gtk+-2.0 environment, in which case I think the old GtkStyle methods work. for example, assuming your not running a Gtk-3.0 environment like gnome-shell
import gi
# make sure you use gtk+-2.0
gi.require_version('Gtk', '2.0')
from gi.repository import Gtk
window = Gtk.Window()
...
style = window.get_style()
print style.lookup_color('fg_color')
I think that should still work under a gtk+-2.0 environment. I don't know for sure as my system is running gnome-shell, and can't easily try this out.
However this method has been deprecated and replaced by GtkStyleContext. If I use the above code in a gtk+-3.0 environment like gnome-shell it will run, but does not give me the information I'm after. What I get is
(False, <Gdk.Color(red=0, green=0, blue=0)>)
EDIT: Looking back at this, I think the above is still giving the correct info. The colour for fg_color is not found, as indicated by the first entry in the tuple result, which is False. Also the window must be visible for the colours to be found.
If I want colour information I want to use the new GtkStyleContext, for example
import gi
# make sure you use gtk+-3.0
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
window = Gtk.Window()
...
style_context = window.get_style_context()
print style_context.lookup_color('fg_color')
this will give me some real data, which is telling me the 'fg_color' has been found, due to the first entry in the tuple is True.
(True, <Gdk.Color(red=0.000000, green=0.000000, blue=0.000000, alpha=1.000000)>)
I hope this answers your question.

How can I get a list of windows with Wnck, using PyGI?

I just started using PyGI (on Ubuntu Natty), although I have never used pygtk before.
I have used wnck in a wxPython program though, and it was easy enough to get a list of currently opened windows. From PyGI, the window list is always empty.
relevant code bits:
from gi.repository import Gtk, Wnck
while Gtk.events_pending():
Gtk.main_iteration()
#... in my app class...
screen = Wnck.Screen.get_default()
wins = screen.get_windows()
with that, wins == [].
Thanks!
You need to call screen.force_update() before screen.get_windows() returns list of windows. Unfortunately docs are lacking this part :(
In [1]: from gi.repository import Gtk, Wnck
In [2]: Gtk.main_iteration()
Out[2]: True
In [3]: screen = Wnck.Screen.get_default()
In [4]: screen.force_update()
In [5]: screen.get_windows()
Out[5]:
[<Window object at 0x167bd20 (WnckWindow at 0x195d0e0)>,
<Window object at 0x167bf00 (WnckWindow at 0x195d740)>,
<Window object at 0x167bf50 (WnckWindow at 0x195d850)>]
In your example you have to use: Gtk.main_iteration_do(False) instead of Gtk.main_iteration().

Categories

Resources