将画布从tkinter保存到文件

时间:2017-01-30 16:35:17

标签: python canvas tkinter tkinter-canvas

所以我跟着这篇文章: How can I convert canvas content to an image?

当我按照上一个建议中提到的那样做时,我遇到了以下问题:

当我这样称呼它时,图像/屏幕截图拍摄得太早,因此无法拍摄所需的图像。这是代码:

from tkinter import *
from PIL import ImageGrab
root = Tk()
cv = Canvas(root)

cv.pack()

cv.create_rectangle(10,10,50,50)
#cv.create_line([0, 10, 10, 10], fill='green')


cv.update()


#print(root.winfo_width())

def getter(widget):
    x=root.winfo_rootx()+widget.winfo_x()
    print(x)
    y=root.winfo_rooty()+widget.winfo_y()
    print(y)
    x1=x+widget.winfo_width()
    print(x1)
    y1=y+widget.winfo_height()
    print(y1)
    ImageGrab.grab().crop((x,y,x1,y1)).save("em.jpg")

getter(cv)
root.mainloop()

顺便说一句,如果有一个更简单的解决方案,我将不胜感激! 问题是保存部分将在以后动态添加到代码中,因此解决方案应尽可能轻。

提前致谢!

PS:也许甚至可以保存画布而不事先显示它?只是通过代码?

2 个答案:

答案 0 :(得分:1)

以下是仅截取tkinter画布的截图的代码。 self._grabtofile模块在​​Linux中不起作用;将其替换为pyscreenshot。在Ubuntu 16.04中测试了这段代码。您可能必须检查它是否在Windows / OSx中运行。请注意函数#!/usr/bin/python3 # -*- coding: utf-8 -*- try: import tkinter as tk # Python 3 tkinter modules except ImportError: import Tkinter as tk # Python 2 tkinter modules from PIL import Image, ImageTk #from PIL import Image, ImageTk, ImageGrab # For Windows & OSx import pyscreenshot as ImageGrab # For Linux class App(tk.Frame): def __init__(self, parent): tk.Frame.__init__(self, parent) self.parent=parent file = 'images.jpg' self.img = Image.open(file) #self.img.show() #Check to proof image can be read in and displayed correctly. self.photo = ImageTk.PhotoImage(self.img) print('size of self.img =', self.img.size) centerx= self.img.size[0]//2 centery= self.img.size[1]//2 print ('center of self.img = ', centerx, centery) self.cv = tk.Canvas(self) self.cv.create_image(centerx, centery, image=self.photo) self.cv.create_rectangle(centerx*0.5,centery*0.5,centerx*1.5,centery*1.5, outline='blue') self.cv.grid(row=0, column=0, columnspan=3, sticky='nsew') self.snappic=tk.Button(self, text='SNAP', command=self._snapCanvas) self.snappic.grid(row=1, column=0, sticky='nsew') self.savepic=tk.Button(self, text='SAVE', command=self._save) self.savepic.grid(row=1, column=1, sticky='nsew') self.directsavepic=tk.Button(self, text='Grab_to_File', command=self._grabtofile) self.directsavepic.grid(row=1, column=2, sticky='nsew') self.snapsave=tk.Button(self, text='SNAP & SAVE', command=self._snapsaveCanvas) self.snapsave.grid(row=2, column=0, columnspan=2, sticky='nsew') def _snapCanvas(self): print('\n def _snapCanvas(self):') canvas = self._canvas() # Get Window Coordinates of Canvas self.grabcanvas = ImageGrab.grab(bbox=canvas) self.grabcanvas.show() def _save(self): self.grabcanvas.save("out.jpg") print('Screenshoot of tkinter.Canvas saved in "out.jpg"') def _grabtofile(self): '''Remark: The intension was to directly save a screenshoot of the canvas in "out_grabtofile.png". Issue 1: Only a full screenshot was save. Issue 2: Saved image format defaults to .png. Other format gave errors. Issue 3: "ImageGrab.grab_to_file" only able to return full screenshoot and not just the canvas. ''' print('\n def _grabtofile(self):') canvas = self._canvas() # Get Window Coordinates of Canvas print('canvas = ', canvas) ImageGrab.grab_to_file("out_grabtofile.png", ImageGrab.grab(bbox=canvas)) print('Screenshoot of tkinter.Canvas directly saved in "out_grabtofile.png"') def _snapsaveCanvas(self): print('\n def _snapsaveCanvas(self):') canvas = self._canvas() # Get Window Coordinates of Canvas self.grabcanvas = ImageGrab.grab(bbox=canvas).save("out_snapsave.jpg") print('Screencshot tkinter canvas and saved as "out_snapsave.jpg w/o displaying screenshoot."') def _canvas(self): print(' def _canvas(self):') print('self.cv.winfo_rootx() = ', self.cv.winfo_rootx()) print('self.cv.winfo_rooty() = ', self.cv.winfo_rooty()) print('self.cv.winfo_x() =', self.cv.winfo_x()) print('self.cv.winfo_y() =', self.cv.winfo_y()) print('self.cv.winfo_width() =', self.cv.winfo_width()) print('self.cv.winfo_height() =', self.cv.winfo_height()) x=self.cv.winfo_rootx()+self.cv.winfo_x() y=self.cv.winfo_rooty()+self.cv.winfo_y() x1=x+self.cv.winfo_width() y1=y+self.cv.winfo_height() box=(x,y,x1,y1) print('box = ', box) return box if __name__ == '__main__': root = tk.Tk() root.title('App'), root.geometry('300x300') app = App(root) app.grid(row=0, column=0, sticky='nsew') root.rowconfigure(0, weight=1) root.columnconfigure(0, weight=1) app.rowconfigure(0, weight=10) app.rowconfigure(1, weight=1) app.columnconfigure(0, weight=1) app.columnconfigure(1, weight=1) app.columnconfigure(2, weight=1) app.mainloop() 中的备注。

备注:在Ubuntu中,此脚本必须直接在命令行/终端上执行才能工作。从IDLE for python3执行时它不起作用。

摘要:

  1. 能够显示tkinter画布的画面,并将其保存到文件a 使用两个事件。
  2. 能够截取tkinter画布(没有显示它)并将其保存到 文件使用一个事件。
  3. 工作代码:

    find()

    GUI的屏幕截图: GUI by tkinter

    图形用户界面的屏幕截图: tk.Canvas

答案 1 :(得分:0)

我知道这是一篇过时的文章,但我只想分享对我有用的内容,希望它将对遇到类似问题的人有所帮助。

import tkinter as tk
from PIL import Image
import io
import os
import subprocess

root = Tk()

cv = Canvas(root)
cv.pack()

cv.create_rectangle(10,10,50,50)

ps = cv.postscript(colormode='color')
img = Image.open(io.BytesIO(ps.encode('utf-8')))
img.save('filename.jpg', 'jpeg')

root.mainloop()

在此解决方案中,您必须安装了ghostscript和Pillow。 对于MacOS,请通过以下方式安装ghostscript:

brew install ghostscript

和枕头 pip install Pillow