2017-01-30 4 views
0

Так я последовал за этот пост: How can I convert canvas content to an image?Сохранение холст из Tkinter в файл

И когда я пытался сделать, как указано в последнем предложении, я получаю следующую задачу:

Когда я называю это как это, изображение/снимок экрана принято слишком рано, и поэтому требуемое изображение не будет захвачено. Вот код:

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: Возможно, даже можно сохранить холст, не отображая его заранее? Просто по коду?

+1

использование 'root.after (миллисекунды, callback) 'для выполнения с задержкой. O используйте 'PIL' вместо' Tkinter', чтобы нарисовать его. 'PIL' имеет множество функций для рисования объектов. – furas

+0

Какой метод я должен вызывать с задержкой? root.after (3000, root.mainloop())? –

+1

'root.after (3000, getter)', но 'callback' означает" имя функции без '()' "- или вы должны использовать' lambda' для добавления аргументов 'root.after (3000, lambda: getter (cv)) ' – furas

ответ

1

Ниже приведен код для снятия скриншотов только с холстом tkinter. PIL.ImageGrab модуль не работает в Linux; заменил его на pyscreenshot. Протестировал этот код в Ubuntu 16.04. Возможно, вам придется проверить, работает ли он в Windows/OSx. Обратите внимание на замечания в функции self._grabtofile.

Примечание: В Ubuntu этот скрипт должен быть выполнен непосредственно на командной строке/терминале для работы. Это не сработало при выполнении из IDLE для python3.

Резюме:

  1. Возможность отображения screenschoot в виде TkInter холст и сохранить его в файл используя два события.
  2. Возможность скриншота холста tkinter (без его отображения) и сохранения его в файле с использованием одного события.

Рабочий код:

#!/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() 

Скриншот GUI:GUI by tkinter

Скриншот tk.Canvas ГИП:tk.Canvas

+0

Спасибо! Не могли бы вы также привести пример о том, как его использовать? Например, с моим кодом tkinter. –

+0

@EerikMuuli Простите меня, я не понимаю ваш вопрос.Пожалуйста, дополните. Если вы спрашиваете, как выполнить этот код, вы можете сохранить этот файл с именем файла «test.py», открыть терминал и ввести python3 test.py для его выполнения. Как если бы вы изучали код, он показывает, как применять то, что вы написали в своем коде (с некоторыми исправлениями или поправками), как скриншот вашего холста tkinter GUI. Я добавил множество заявлений и комментариев к печати, чтобы помочь вам изучить код. –

+0

Извините за то, что не уточнил. Я получил его для работы - он открывает экран с кнопками. Но возможно ли сохранить Canvas в файл изображения автоматически. Например, если у меня есть код (который рисует холст), и я хочу автоматически сохранить его в изображение. Так, например, если я добавлю «код рисования холста» в ваш код, тогда выполнение test.py из командной строки сохранит вывод canvas в файл. (Никакой пользовательский ввод в этом процессе). Надеюсь, это станет более ясным. –

Смежные вопросы