显示 tkinter 上的所有项目 canvas
Show all items on the tkinter canvas
我在 tkinter 中有一个简单的程序,允许缩放 in/out 和平移 canvas。我正在尝试定义一个按钮,使我能够显示 canvas 上的所有项目。
代码如下:
##### Imports #####
import tkinter as tk
from tkinter import ttk
###################################################################
# FUNCTIONS #
###################################################################
# Defining zoom function -----------------------------------------------------------------------------------------------
def wheel(mainCanvas, event, arg):
global x, y, delta, fontSize
scale = 1.0
if event.delta < 0:
scale *= delta
fontSize *=delta
if event.delta > 0:
scale /= delta
fontSize /=delta
# Rescaling canvas
x = mainCanvas.canvasx(event.x)
y = mainCanvas.canvasy(event.y)
mainCanvas.scale('all', x, y, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# Getting all the text item on the canvas
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
print(fontSize)
# Defining pan function ------------------------------------------------------------------------------------------------
def move_from(mainCanvas, event, arg):
global x, y
mainCanvas.scan_mark(event.x, event.y)
def move_to(mainCanvas, event, arg):
global x, y
mainCanvas.scan_dragto(event.x, event.y, gain=1)
###################################################################
# MAIN #
###################################################################
def main():
root = tk.Tk()
root.title('Scroll and zoom')
root.geometry("600x600")
mainFrame = ttk.Frame(root).grid()
vertBar = ttk.Scrollbar(root, orient='vertical')
horiBar = ttk.Scrollbar(root, orient='horizontal')
vertBar.grid(row=0, column=1, sticky='ns')
horiBar.grid(row=1, column=0, sticky='we')
mainCanvas = tk.Canvas(mainFrame, highlightthickness=0, xscrollcommand=horiBar.set, yscrollcommand=vertBar.set)
mainCanvas.grid(row=0, column=0, sticky='nswe')
# Binding scrollbars to the canvas and event binding to the canvas--------------------------------------------------
vertBar.configure(command=mainCanvas.yview)
horiBar.configure(command=mainCanvas.xview)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
global delta, fontSize
delta = 0.9
fontSize = 10
mainCanvas.bind('<ButtonPress-1>', lambda event, arg=mainCanvas: move_from(mainCanvas, event, arg))
mainCanvas.bind('<B1-Motion>', lambda event, arg=mainCanvas: move_to(mainCanvas, event, arg))
mainCanvas.bind('<MouseWheel>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
# Drawing on the canvas and configuring canvas ---------------------------------------------------------------------
x0 =100
y0 = 100
x1 = 200
y1 = 200
rect1 = mainCanvas.create_rectangle(x0, y0, x1, y1, outline='black', fill='grey', activefill='grey')
rect2 = mainCanvas.create_rectangle(-x0*2, -y0*2, -x1*2, -y1*2, outline='black', fill='grey', activefill='grey')
text = mainCanvas.create_text(100, 100, anchor='nw', text='Scroll to zoom', font=("Arial", int(fontSize)), tags='text', width=0)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
buttonShowAll = tk.Button(root, text='Show All')
buttonShowAll.grid()
root.mainloop()
###################################################################
# RUN #
###################################################################
def run():
print('\nStart script')
main()
print('Finished script')
run()
我想要实现的是,在任何级别的缩放或平移位置,按钮 Show all
都可以显示 canvas 上的所有项目。如果没有 mainCanvas.delete('all')
或 mainCanvas.destroy()
方法就可以实现这一目标。
您必须获得 bbox('all')
的项目大小和小部件的大小 Canvas
才能计算比例并缩放它
def show_all(mainCanvas):
region = mainCanvas.bbox('all')
old_width = region[2] - region[0]
old_height = region[3] - region[1]
print('old:', old_width, old_height)
new_width = mainCanvas.winfo_width()
new_height = mainCanvas.winfo_height()
print('new:', new_width, new_height)
scale = min(new_width/old_width, new_height/old_height)
print('scale:', scale)
centerx = (region[0] + region[2])/2
centery = (region[1] + region[3])/2
print('center:', centerx, centery)
# rescale objects
mainCanvas.scale('all', centerx, centery, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# rescale font and text
fontSize *= scale
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
#TODO: center objects on canvas
完整的工作代码:
我不得不在 Linux 上添加 Button-4
、Button-5
并将 wheel()
更改为 运行 mousewheel
。
我更改了 mainFrame
,因为您将 None
分配给了这个变量。
##### Imports #####
import tkinter as tk
from tkinter import ttk
###################################################################
# FUNCTIONS #
###################################################################
# Defining zoom function -----------------------------------------------------------------------------------------------
def wheel(mainCanvas, event, arg):
global fontSize
print('wheel', event, arg)
scale = 1.0
if event.num == 5 or event.delta < 0:
scale *= delta
fontSize *=delta
if event.num == 4 or event.delta > 0:
scale /= delta
fontSize /=delta
# Rescaling canvas
x = mainCanvas.canvasx(event.x)
y = mainCanvas.canvasy(event.y)
mainCanvas.scale('all', x, y, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# Getting all the text item on the canvas
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
# print(fontSize)
# Defining pan function ------------------------------------------------------------------------------------------------
def move_from(mainCanvas, event, arg):
print('move_from')
mainCanvas.scan_mark(event.x, event.y)
def move_to(mainCanvas, event, arg):
print('move_to')
mainCanvas.scan_dragto(event.x, event.y, gain=1)
def show_all(mainCanvas):
global fontSize
region = mainCanvas.bbox('all')
old_width = region[2] - region[0]
old_height = region[3] - region[1]
print('old:', old_width, old_height)
new_width = mainCanvas.winfo_width()
new_height = mainCanvas.winfo_height()
print('new:', new_width, new_height)
scale = min(new_width/old_width, new_height/old_height)
print('scale:', scale)
centerx = (region[0] + region[2])/2
centery = (region[1] + region[3])/2
print('center:', centerx, centery)
# rescale objects
mainCanvas.scale('all', centerx, centery, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# rescale font and text
fontSize *= scale
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
#TODO: center objects on canvas
###################################################################
# MAIN #
###################################################################
def main():
global delta, fontSize
root = tk.Tk()
root.title('Scroll and zoom')
root.geometry("600x600")
mainFrame = ttk.Frame(root)
mainFrame.grid(row=0, column=0, sticky='news')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
vertBar = ttk.Scrollbar(root, orient='vertical')
horiBar = ttk.Scrollbar(root, orient='horizontal')
vertBar.grid(row=0, column=1, sticky='ns')
horiBar.grid(row=1, column=0, sticky='we')
mainCanvas = tk.Canvas(mainFrame, highlightthickness=0, xscrollcommand=horiBar.set, yscrollcommand=vertBar.set)
mainCanvas.pack(fill='both', expand=True)
# Binding scrollbars to the canvas and event binding to the canvas--------------------------------------------------
vertBar.configure(command=mainCanvas.yview)
horiBar.configure(command=mainCanvas.xview)
delta = 0.9
fontSize = 10
mainCanvas.bind('<ButtonPress-1>', lambda event, arg=mainCanvas: move_from(mainCanvas, event, arg))
mainCanvas.bind('<B1-Motion>', lambda event, arg=mainCanvas: move_to(mainCanvas, event, arg))
mainCanvas.bind('<MouseWheel>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
mainCanvas.bind('<Button-5>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
mainCanvas.bind('<Button-4>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
# Drawing on the canvas and configuring canvas ---------------------------------------------------------------------
x0 =100
y0 = 100
x1 = 200
y1 = 200
rect1 = mainCanvas.create_rectangle(x0, y0, x1, y1, outline='black', fill='grey', activefill='grey')
rect2 = mainCanvas.create_rectangle(-x0*2, -y0*2, -x1*2, -y1*2, outline='black', fill='grey', activefill='grey')
text = mainCanvas.create_text(100, 100, anchor='nw', text='Scroll to zoom', font=("Arial", int(fontSize)), tags='text', width=0)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
buttonShowAll = tk.Button(root, text='Show All', command=lambda:show_all(mainCanvas))
buttonShowAll.grid()
root.mainloop()
###################################################################
# RUN #
###################################################################
def run():
print('\nStart script')
main()
print('Finished script')
run()
我在 tkinter 中有一个简单的程序,允许缩放 in/out 和平移 canvas。我正在尝试定义一个按钮,使我能够显示 canvas 上的所有项目。 代码如下:
##### Imports #####
import tkinter as tk
from tkinter import ttk
###################################################################
# FUNCTIONS #
###################################################################
# Defining zoom function -----------------------------------------------------------------------------------------------
def wheel(mainCanvas, event, arg):
global x, y, delta, fontSize
scale = 1.0
if event.delta < 0:
scale *= delta
fontSize *=delta
if event.delta > 0:
scale /= delta
fontSize /=delta
# Rescaling canvas
x = mainCanvas.canvasx(event.x)
y = mainCanvas.canvasy(event.y)
mainCanvas.scale('all', x, y, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# Getting all the text item on the canvas
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
print(fontSize)
# Defining pan function ------------------------------------------------------------------------------------------------
def move_from(mainCanvas, event, arg):
global x, y
mainCanvas.scan_mark(event.x, event.y)
def move_to(mainCanvas, event, arg):
global x, y
mainCanvas.scan_dragto(event.x, event.y, gain=1)
###################################################################
# MAIN #
###################################################################
def main():
root = tk.Tk()
root.title('Scroll and zoom')
root.geometry("600x600")
mainFrame = ttk.Frame(root).grid()
vertBar = ttk.Scrollbar(root, orient='vertical')
horiBar = ttk.Scrollbar(root, orient='horizontal')
vertBar.grid(row=0, column=1, sticky='ns')
horiBar.grid(row=1, column=0, sticky='we')
mainCanvas = tk.Canvas(mainFrame, highlightthickness=0, xscrollcommand=horiBar.set, yscrollcommand=vertBar.set)
mainCanvas.grid(row=0, column=0, sticky='nswe')
# Binding scrollbars to the canvas and event binding to the canvas--------------------------------------------------
vertBar.configure(command=mainCanvas.yview)
horiBar.configure(command=mainCanvas.xview)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
global delta, fontSize
delta = 0.9
fontSize = 10
mainCanvas.bind('<ButtonPress-1>', lambda event, arg=mainCanvas: move_from(mainCanvas, event, arg))
mainCanvas.bind('<B1-Motion>', lambda event, arg=mainCanvas: move_to(mainCanvas, event, arg))
mainCanvas.bind('<MouseWheel>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
# Drawing on the canvas and configuring canvas ---------------------------------------------------------------------
x0 =100
y0 = 100
x1 = 200
y1 = 200
rect1 = mainCanvas.create_rectangle(x0, y0, x1, y1, outline='black', fill='grey', activefill='grey')
rect2 = mainCanvas.create_rectangle(-x0*2, -y0*2, -x1*2, -y1*2, outline='black', fill='grey', activefill='grey')
text = mainCanvas.create_text(100, 100, anchor='nw', text='Scroll to zoom', font=("Arial", int(fontSize)), tags='text', width=0)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
buttonShowAll = tk.Button(root, text='Show All')
buttonShowAll.grid()
root.mainloop()
###################################################################
# RUN #
###################################################################
def run():
print('\nStart script')
main()
print('Finished script')
run()
我想要实现的是,在任何级别的缩放或平移位置,按钮 Show all
都可以显示 canvas 上的所有项目。如果没有 mainCanvas.delete('all')
或 mainCanvas.destroy()
方法就可以实现这一目标。
您必须获得 bbox('all')
的项目大小和小部件的大小 Canvas
才能计算比例并缩放它
def show_all(mainCanvas):
region = mainCanvas.bbox('all')
old_width = region[2] - region[0]
old_height = region[3] - region[1]
print('old:', old_width, old_height)
new_width = mainCanvas.winfo_width()
new_height = mainCanvas.winfo_height()
print('new:', new_width, new_height)
scale = min(new_width/old_width, new_height/old_height)
print('scale:', scale)
centerx = (region[0] + region[2])/2
centery = (region[1] + region[3])/2
print('center:', centerx, centery)
# rescale objects
mainCanvas.scale('all', centerx, centery, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# rescale font and text
fontSize *= scale
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
#TODO: center objects on canvas
完整的工作代码:
我不得不在 Linux 上添加 Button-4
、Button-5
并将 wheel()
更改为 运行 mousewheel
。
我更改了 mainFrame
,因为您将 None
分配给了这个变量。
##### Imports #####
import tkinter as tk
from tkinter import ttk
###################################################################
# FUNCTIONS #
###################################################################
# Defining zoom function -----------------------------------------------------------------------------------------------
def wheel(mainCanvas, event, arg):
global fontSize
print('wheel', event, arg)
scale = 1.0
if event.num == 5 or event.delta < 0:
scale *= delta
fontSize *=delta
if event.num == 4 or event.delta > 0:
scale /= delta
fontSize /=delta
# Rescaling canvas
x = mainCanvas.canvasx(event.x)
y = mainCanvas.canvasy(event.y)
mainCanvas.scale('all', x, y, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# Getting all the text item on the canvas
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
# print(fontSize)
# Defining pan function ------------------------------------------------------------------------------------------------
def move_from(mainCanvas, event, arg):
print('move_from')
mainCanvas.scan_mark(event.x, event.y)
def move_to(mainCanvas, event, arg):
print('move_to')
mainCanvas.scan_dragto(event.x, event.y, gain=1)
def show_all(mainCanvas):
global fontSize
region = mainCanvas.bbox('all')
old_width = region[2] - region[0]
old_height = region[3] - region[1]
print('old:', old_width, old_height)
new_width = mainCanvas.winfo_width()
new_height = mainCanvas.winfo_height()
print('new:', new_width, new_height)
scale = min(new_width/old_width, new_height/old_height)
print('scale:', scale)
centerx = (region[0] + region[2])/2
centery = (region[1] + region[3])/2
print('center:', centerx, centery)
# rescale objects
mainCanvas.scale('all', centerx, centery, scale, scale)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
# rescale font and text
fontSize *= scale
for i in mainCanvas.find_withtag("text"):
mainCanvas.itemconfigure(i, font=("Arial", int(fontSize)))
#TODO: center objects on canvas
###################################################################
# MAIN #
###################################################################
def main():
global delta, fontSize
root = tk.Tk()
root.title('Scroll and zoom')
root.geometry("600x600")
mainFrame = ttk.Frame(root)
mainFrame.grid(row=0, column=0, sticky='news')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
vertBar = ttk.Scrollbar(root, orient='vertical')
horiBar = ttk.Scrollbar(root, orient='horizontal')
vertBar.grid(row=0, column=1, sticky='ns')
horiBar.grid(row=1, column=0, sticky='we')
mainCanvas = tk.Canvas(mainFrame, highlightthickness=0, xscrollcommand=horiBar.set, yscrollcommand=vertBar.set)
mainCanvas.pack(fill='both', expand=True)
# Binding scrollbars to the canvas and event binding to the canvas--------------------------------------------------
vertBar.configure(command=mainCanvas.yview)
horiBar.configure(command=mainCanvas.xview)
delta = 0.9
fontSize = 10
mainCanvas.bind('<ButtonPress-1>', lambda event, arg=mainCanvas: move_from(mainCanvas, event, arg))
mainCanvas.bind('<B1-Motion>', lambda event, arg=mainCanvas: move_to(mainCanvas, event, arg))
mainCanvas.bind('<MouseWheel>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
mainCanvas.bind('<Button-5>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
mainCanvas.bind('<Button-4>', lambda event, arg=mainCanvas: wheel(mainCanvas, event, arg))
# Drawing on the canvas and configuring canvas ---------------------------------------------------------------------
x0 =100
y0 = 100
x1 = 200
y1 = 200
rect1 = mainCanvas.create_rectangle(x0, y0, x1, y1, outline='black', fill='grey', activefill='grey')
rect2 = mainCanvas.create_rectangle(-x0*2, -y0*2, -x1*2, -y1*2, outline='black', fill='grey', activefill='grey')
text = mainCanvas.create_text(100, 100, anchor='nw', text='Scroll to zoom', font=("Arial", int(fontSize)), tags='text', width=0)
mainCanvas.configure(scrollregion=mainCanvas.bbox('all'))
buttonShowAll = tk.Button(root, text='Show All', command=lambda:show_all(mainCanvas))
buttonShowAll.grid()
root.mainloop()
###################################################################
# RUN #
###################################################################
def run():
print('\nStart script')
main()
print('Finished script')
run()