Cairo with tkinter?

Is it possible to paint on the surface of Cairo and then render that as tkinter.PhotoImage? Can anyone provide an example or at least a description of how this can be done?

+3


source to share


1 answer


There are quite a few ways to achieve what you want, and tkinter.PhotoImage is definitely not the best if you really shouldn't be using it. The easiest way is to use the ImageTK module from the Pillow library :

from tkinter import Tk, Label
from PIL import Image, ImageTk
from cairo import ImageSurface, Context, FORMAT_ARGB32


class ExampleGui(Tk):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        w, h = 800, 600

        self.geometry("{}x{}".format(w, h))

        self.surface = ImageSurface(FORMAT_ARGB32, w, h)
        self.context = Context(self.surface)

        # Draw something
        self.context.scale(w, h)
        self.context.rectangle(0, 0, 1, 1)
        self.context.set_source_rgba(1, 0, 0, 0.8)
        self.context.fill()

        self._image_ref = ImageTk.PhotoImage(Image.frombuffer("RGBA", (w, h), self.surface.get_data(), "raw", "BGRA", 0, 1))

        self.label = Label(self, image=self._image_ref)
        self.label.pack(expand=True, fill="both")

        self.mainloop()


if __name__ == "__main__":
    ExampleGui()

      

Otherwise, you can do this by converting the Cairo surface to a base64-encoded GIF (either with Pillow or manually, which will be a bit tedious) and passing the result as "data" arg to the tkinter.PhotoImage constructor ( untested! ):



    from io import BytesIO 
    from PIL import Image
    from cairo import ImageSurface, Context, FORMAT_ARGB32


    w, h = 800, 600

    surface = ImageSurface(FORMAT_ARGB32, w, h)
    context = Context(surface)

    output = io.BytesIO()
    image = Image.frombuffer("RGBA", (w, h), self.surface.get_data(), "raw", "BGRA", 0, 1)
    image.save(output, format="gif")
    b64 = base64.b64encode(output.read())

      

Note. ... On systems with large terms ARGB should be used for source data AFAIK.

+1


source







All Articles