如何使用GTK3和PyGObject绘制GdkPixbuf [英] How to draw a GdkPixbuf using GTK3 and PyGObject

查看:142
本文介绍了如何使用GTK3和PyGObject绘制GdkPixbuf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小型应用程序,它使用DrawingArea使用PyGObjectGTK3绘制简单的地图.

I have a small application that uses a DrawingArea to draw a simple map using PyGObject and GTK3.

我使用

from gi.repository import Gtk, GdkPixbuf
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size("logo.png", 25, 25)

,然后尝试在DrawingArea的绘制事件信号中绘制它

and then try to draw it in the DrawingArea's draw event signal

def draw(self, widget, context):
    window = widget.get_window()
    ctx = window.cairo_create()
    ctx.set_source_pixbuf(pixbuf, 0, 0)

但我收到错误消息

"AttributeError: 'cairo.Context' object has no attribute 'set_source_pixbuf'"

如果我正在阅读 Gtk2, gtk3迁移指南正确,这应该可以正常工作. 我在做什么错了?

If I'm reading the Gtk2 to Gtk3 migration guide correctly, this should work. What am I doing wrong?

推荐答案

新的 draw 信号使用已将cairo上下文作为参数传递的回调,您无需执行诸如就像您在PyGtk中所做的那样,window = widget.get_window()在参加 expose-event 信号时获取开罗上下文.在PYGObject中更简单:

The new draw signal uses a callback that already passes the cairo context as a parameter, you don't need to do stuff like window = widget.get_window() like you did in PyGtk to get the cairo context while attending the expose-event signal. In PYGObject is simpler:

import cairo

class Foo(object):
    def __init__(self):

       (...)
        self.image = cairo.ImageSurface.create_from_png('logo.png')
       (...)

    def draw(self, widget, context):
        if self.image is not None:
            context.set_source_surface(self.image, 0.0, 0.0)
            context.paint()
        else:
            print('Invalid image')
        return False

那是如果您不需要PixBuf,但是如果您需要它来做其他事情,则可以有几种选择:

That is if you don't need the PixBuf, but if you need it for something else you have several options:

  1. 将两个对象都存储在内存中.如果两者都是从PNG加载的,那么除了浪费内存外,应该没有什么其他问题.
  2. 将GdkPixbuf转换为PIL图像,然后将PIL图像转换为数据阵列,然后使用create_for_data()从该数据阵列创建Cairo ImageSurface. k牛:S我不太清楚,对不起:S
  3. 使用hock建议的 Gdk.cairo_set_source_pixbuf().这似乎是在ImageSurface中绘制Pixbuf的正确方法,但这是完全不合Python的(这就是为什么我讨厌这种自省的东西,它们看起来都像C,就像一个坏的C端口).
  1. To have both objects in memory. If both are loaded from a PNG there should not be much problems other than the waste of memory.
  2. Convert GdkPixbuf to PIL Image, then PIL Image to data array and then create a Cairo ImageSurface from that data array using create_for_data(). Yak :S I don't know better, sorry :S
  3. Use Gdk.cairo_set_source_pixbuf() proposed by hock. This seems to be the correct way to draw a Pixbuf in a ImageSurface, but it is totally unpythonic (and that's why I hate this Introspection stuff, all looks like C, like a bad C port).

如果您选择糟糕的第二个选项,请按以下步骤操作:

If you choose the awful second option here is how:

import Image
import array
from gi.repository import Gtk, GdkPixbuf

width = 25
height = 25
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size('logo.png', width, height)
pil_image = Image.fromstring('RGBA', (width, height), pixbuf.get_pixels())
byte_array = array.array('B', pil_image.tostring())
cairo_surface = cairo.ImageSurface.create_for_data(byte_array, cairo.FORMAT_ARGB32, width, height, width * 4)

请注意, create_for_data()如果这是您要达到的目的,还请检查我有关如何在PyGObject中使用双缓冲区的答案:

Check also my answer on how to use a double buffer in PyGObject if this is what you're trying to achieve: Drawing in PyGobject (python3)

亲切的问候

这篇关于如何使用GTK3和PyGObject绘制GdkPixbuf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆