Cairo with tkinter?
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 to share