首页 > 解决方案 > 如何将整个 tkinter 画布截图为 png 或 pdf

问题描述

我正在创建一个经过设计的程序......它旨在让 D&D 老实说,角色构建更容易。(我是一名 DM,当我知道自己想要什么的时候,我花了很长时间把表格放在一起,这应该是一个简单的过程,这段代码最终将成为一个大型程序的一部分,将过程从几小时简化到几分钟。对我来说,非常值得。)所有的角色创建部分都在一个单独的代码中,但我一直在做的是能够打开一个角色表,把所有问题的答案都放进去,然后保存输出以备后用印刷。请注意我在 python3 上,使用 Windows 8,并且我的所有模块实际上都安装了 pip 是的。

我想要 :

  1. 打开 png 图像(或 PDF)

  2. 在上面写入新信息

  3. 将输出另存为新文件。

< 请注意,我根本不想在其中使用类或函数。我想要所有简单的东西。>

我已经可以做的:

  1. 打开一个 PNG(但不是原始的 PDF。我必须先转换它,原因有很多,我不会在这里介绍。)

  2. 在图像的画布窗口中显示我想要的信息。

不幸的是,我似乎无法保存整个画布。到目前为止,我得到的最接近的是 ImageGrab,它实际上截取了我的整个计算机显示器。因此,我的画布(顶角)只有大约 500*250 像素。

我需要弄清楚我在这里做错了什么。我将一些代码离线以使滚动条正常工作,我根本不认为这是我自己的。将输出保存为我可以查看的任何内容时遇到问题。我得到了一个附言文件,当我把它放回一个可视图像时,仍然只是整个画布的一部分快照。我需要一些东西来显示你需要滚动的部分。

当前代码在 Tkinter 包中以某种方式引发了异常,在其他情况下,我在网上只发现了大约 27 次,没有一个答案实际上适用于我的错误。我看了又看,非常感谢有关如何解决这个问题的帮助。

from tkinter import *
import tkinter.ttk as ttk
import PIL.Image as Image
import PIL.ImageTk as ImageTk
import PIL.ImageGrab as ImageGrab
import os
#I imported all these PIL sections seperate because importing the whole 
#thing as one, or alltogether on one line caused so many errors in calling     
#the functions. my pc for some reason HATES functions, ive NEVER had much 
#success with them. hence trying to create programs without them.
def on_vertical(event):
    canvas.yview_scroll(-1 * event.delta, 'units')

def on_horizontal(event):
    canvas.xview_scroll(-1 * event.delta, 'units')

root = Tk()
root.title('Your Character Here')
h = Scrollbar(root, orient=HORIZONTAL)
v = Scrollbar(root, orient=VERTICAL)
canvas = Canvas(root, scrollregion=(0, 0, 1275, 4960),
     yscrollcommand=v.set, 
     xscrollcommand=h.set)
h['command'] = canvas.xview
v['command'] = canvas.yview
output = ImageTk.PhotoImage(Image.open('charpg4.png'))
canvas.create_image(0,0,image=output, anchor='nw')
canvas.grid(column=0, row=0, sticky=(N,W,E,S))

canvas.bind_all('<MouseWheel>', on_vertical)
canvas.bind_all('<Shift-MouseWheel>', on_horizontal)

h.grid(column=0, row=1, sticky=(W,E))
v.grid(column=1, row=0, sticky=(N,S))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)

testing=("one", "two", "three", "testing")
canvas.create_text(210,155,fill='black',font='Helvetica 10',
                   text=testing)

canvas.update()
grabcanvas=ImageGrab.grab(bbox=canvas).save("test.png")
ttk.grabcanvas.save("test.png")
#the following code works but apparently takes only a direct screenshot
#ImageGrab.grab().save("test.jpg") 
#--these others have been tried but dont work for me??
#causes an error with bbox and ImageGrab
#self.grabcanvas = ImageGrab.grab(bbox=canvas)
#Causes the save error, says no such option
#ImageGrab.grab(bbox=canvas).save("test.jpg")
#froze and crashed the game, didnt do anything in the end.
#canvas.postscript(file='test.ps', size =(1275, 4960), colormode='gray')
root.mainloop()

这是引发的代码错误。

    Traceback (most recent call last):
  File "C:/Users/Autumn/Documents/programs/tests/dnd game/saving 
output/windowsize 3.py", line 42, in <module>
    grabcanvas=ImageGrab.grab(bbox=canvas).save("test.png")
  File "C:\Program Files (x86)\Python36-32\lib\site- 
   packages\PIL\ImageGrab.py", 
    line 48, in grab
        im = im.crop(bbox)
   File "C:\Program Files (x86)\Python36-32\lib\site- 
 packages\PIL\Image.py", 
    line 1078, in crop
        return self._new(self._crop(self.im, box))
      File "C:\Program Files (x86)\Python36-32\lib\site- 
   packages\PIL\Image.py", 
    line 1092, in _crop
    x0, y0, x1, y1 = map(int, map(round, box))
       File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", 
line 1486, in cget
        return self.tk.call(self._w, 'cget', '-' + key)
    TypeError: must be str, not int

通常我会找出我的代码有什么问题,但我不能,基于我在网上找到的所有内容,Image.Save 或 ImageGrab.save 或 Image.write ......这些应该在 tk 中工作。...它似乎是指 tkinter 中的一个函数,它不调用'cget'或某种字符串。因为我从来没有在它所指的行中放入一个整数,而且我从来没有裁剪,因为错误是指.

标签: python-3.xcanvastkintersaveruntime-error

解决方案


您遇到的问题是您传递canvasbbox. grab()需要获取一组坐标,而不是像画布这样的对象。

试试这个:

通话后删除update()

grabcanvas=ImageGrab.grab(bbox=canvas).save("test.png")
ttk.grabcanvas.save("test.png")

然后在update()调用后添加:

def save_canvas():
    x = root.winfo_rootx() + canvas.winfo_x()
    y = root.winfo_rooty() + canvas.winfo_y()
    xx = x + canvas.winfo_width()
    yy = y + canvas.winfo_height()
    ImageGrab.grab(bbox=(x, y, xx, yy)).save("test.gif")
root.after(1000, save_canvas)

推荐阅读