【发布时间】:2021-08-01 18:03:24
【问题描述】:
我写了一个代码来创建画布并让你加载图片。您还可以在此图片中添加徽标和文本并拖动。 (类似于照片水印应用程序)毕竟,您可以将所有工作保存为 PNG。格式。 我想要做的是,我想将所有数据保存为画布对象,然后我可以加载这个画布对象并继续工作。也许我想更改加载的对象/画布上的文本或徽标坐标。
我不知道将它保存为画布对象是对的。如果您在这个主题上帮助我,我将不胜感激。
这是我的代码。
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename, asksaveasfile
def buttonpress(function, *args):
value = function(*args)
print(type(value))
def open_file():
img_path = askopenfilename(title="Select A File", filetype=(("jpeg files", "*.jpg"), ("all files", "*.*")))
if img_path:
canvas.imageList = [] # To get rid of garbage collector, empty list is added
img = Image.open(img_path)
img = img.resize((750, 500), Image.ANTIALIAS)
image = ImageTk.PhotoImage(img)
created_image_id = canvas.create_image(450, 250, image=image)
canvas.imageList.append(image)
# Change button displays
browse_button.grid_forget()
logo_button.grid(column=1, row=5)
text_button.grid(column=4, row=5)
save_button.grid(column=7, row=5)
return created_image_id
def add_logo():
logo_path = askopenfilename(title="Select A File", filetype=(("jpeg files", "*.jpg"), ("all files", "*.*")))
if logo_path:
canvas.logoList = [] # To get rid of garbage collector, empty list is added
logo = Image.open(logo_path)
logo = logo.resize((200, 200), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(logo)
canvas.create_image(450, 250, image=logo)
canvas.logoList.append(logo)
# Change button displays
logo_button.grid_forget()
text_button.grid(column=3, row=5)
save_button.grid(column=6, row=5)
def on_drag(event):
if canvas.selected != 1:
# Calculate distance moved from last position
dx, dy = event.x - canvas.startxy[0], event.y - canvas.startxy[1]
# Move the selected item
canvas.move(canvas.selected, dx, dy)
# Update last position
canvas.startxy = (event.x, event.y)
def on_click(event):
selected = canvas.find_overlapping(event.x - 10, event.y - 10, event.x + 10,
event.y + 10) # List of selected items with mouse
canvas.startxy = (event.x, event.y) # Define "startxy" variable in canvas class
if selected:
canvas.selected = selected[-1] # Select the top-most item #define "selected" variable in canvas class
else:
canvas.selected = None
def add_text():
canvas.create_text(100, 10, fill="darkblue", font="Times 20 italic bold",
text="Click the bubbles that are multiples of two.")
def save_pic(widget):
file = asksaveasfilename(filetypes=[('Portable Network Graphics', '*.png')])
x = root.winfo_rootx() + 75
y = root.winfo_rooty()
x1 = x + widget.winfo_width() - 175
y1 = y + widget.winfo_height()
ImageGrab.grab().crop((x, y, x1, y1)).save(file + ".png")
root = tk.Tk()
root.geometry("900x600")
root.resizable(0, 0)
root.title("Photo Watermark Application")
canvas = tk.Canvas(root, width=900, height=500)
canvas.grid(column=0, row=0, columnspan=9, rowspan=5)
# Browse button
browse_text = tk.StringVar()
browse_button = tk.Button(root, command=lambda: buttonpress(open_file), textvariable=browse_text, font="Ariel",
bg="black",
fg="white",
height=2, width=10)
browse_text.set("Browse")
browse_button.grid(column=4, row=5)
# Add logo button
add_logo_text = tk.StringVar()
logo_button = tk.Button(root, command=add_logo, textvariable=add_logo_text, font="Ariel", bg="black", fg="white",
height=2, width=10)
add_logo_text.set("Add Logo")
# Add text button
add_text_text = tk.StringVar()
text_button = tk.Button(root, command=add_text, textvariable=add_text_text, font="Ariel", bg="black", fg="white",
height=2, width=10)
add_text_text.set("Add Text")
# Add save picture button
save_text_text = tk.StringVar()
save_button = tk.Button(root, command=lambda: save_pic(canvas), textvariable=save_text_text, font="Ariel", bg="black",
fg="white",
height=2, width=10)
save_text_text.set("Save Picture")
root.bind("<B1-Motion>", on_drag) # B1-MOTION = Dragging items using mouse
root.bind("<Button-1>", on_click) # BUTTON-1 = Left click with mouse
root.mainloop()
【问题讨论】:
-
您可以使用字典并将对象及其坐标保存在其中,并且在读取文件时只需将对象放在它们的坐标处
-
我不会尝试保存 Canvas 对象本身,而是会保存创建每个对象所需的信息(以您喜欢的任何格式)。一种方法是定义您自己的
Canvas子类,该子类记录了在其上绘制的所有对象。在@Bryan Oakley 对问题Tkinter - making a second canvas display the contents of another 的回答中有一个子类化示例(用于不同目的)。 -
@Matiiss 感谢您的回复。你能给我一个代码示例吗?我很困惑,因为应该保存对象的位置和大小以及图片以供加载。
-
@martineau 感谢您的回复,但我无法将您提供的解决方案与我的问题进行类比。我想将我当前的工作保存在画布上,然后我希望它可以加载和修改。我被困住了。你能给我一个代码示例吗?
-
@martineau 已经给出了一个很好的例子来说明如何做到这一点,我没有提到,但你可以使用
pickle并以这种方式将对象存储在文件中,但这样会很棒使用类。您也可以在文件中保存一些坐标和大小以及对象的类型,并在读取时循环检查类型,将类型放置在正确的位置并为类型提供正确的大小
标签: python tkinter canvas save load