在TKINTER CANVAS上显示所有项目

发布于 2025-01-20 10:36:34 字数 3846 浏览 0 评论 0原文

我在TKINTER中有一个简单的程序,允许缩放/输出并铺上画布。我正在尝试定义一个按钮,这将使我能够在画布上显示所有物品。 代码如下:

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

我要实现的是,在pan的任何缩放或位置,按钮显示所有可以在画布上显示所有项目。没有Maincanvas.delete('all')或 maincanvas.destroy()方法将是很棒的。

I have a simple program in tkinter that allow to zoom in/out and pan the canvas. I am trying to define a button that will enable me to show all the items on the canvas.
The code is below:

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

What I am trying to achieve is that at any level of zoom or location of pan, the button Show all can show all the items on the canvas. It would be great to achieve this without mainCanvas.delete('all') or mainCanvas.destroy() methods.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

薄荷梦 2025-01-27 10:36:34

You have to get size of bbox('all') with items, and size of widget Canvas to calculate scale and scale it

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

Full working code:

I had to add button-4button-5和更改wheel()在linux上运行鼠标轮>

我更改了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()

You have to get size of bbox('all') with items, and size of widget Canvas to calculate scale and scale it

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

Full working code:

I had to add Button-4, Button-5 and change wheel() to run mousewheel on Linux.

And I changed mainFrame because you assigned None to this variable.

##### 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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文