0

I would like to create a zoom button. On clicking on that zoom button, the image would be zoomed in by a factor represented by an integer (1,2,3,4,5...). With this piece of code, by clicking on the zoom button, another panel is created underneath the already loaded picture. Inside it is blank. What would be needed is to: 1. kill the first (non-zoomed window) and 2. load the zoomed image on the updated panel

from tkinter import *
from tkinter.filedialog import askopenfilename
import tkinter as tk

event2canvas = lambda e, c: (c.canvasx(e.x), c.canvasy(e.y))

root = Tk()

#setting up a tkinter canvas with scrollbars
frame = Frame(root, bd=2, relief=SUNKEN)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)
xscroll = Scrollbar(frame, orient=HORIZONTAL)
xscroll.grid(row=1, column=0, sticky=E+W)
yscroll = Scrollbar(frame)
yscroll.grid(row=0, column=1, sticky=N+S)
canvas = Canvas(frame, bd=0, xscrollcommand=xscroll.set,yscrollcommand=yscroll.set)
canvas.grid(row=0, column=0, sticky=N+S+E+W)
xscroll.config(command=canvas.xview)
yscroll.config(command=canvas.yview)
frame.pack(fill=BOTH,expand=1)

#adding the image
image_str="image.png"
image = tk.PhotoImage(file=image_str)
image = image.zoom(1,1)
canvas.create_image(0,0,image=image,anchor="nw")
canvas.config(scrollregion=canvas.bbox(ALL))

def zoomin():
   root = Tk()
   frame = Frame(root, bd=2, relief=SUNKEN)
   frame.grid_rowconfigure(0, weight=1)
   frame.grid_columnconfigure(0, weight=1)
   xscroll = Scrollbar(frame, orient=HORIZONTAL)
   xscroll.grid(row=1, column=0, sticky=E+W)
   yscroll = Scrollbar(frame)
   yscroll.grid(row=0, column=1, sticky=N+S)
   canvas = Canvas(frame, bd=0, xscrollcommand = xscroll.set, yscrollcommand = yscroll.set)
   canvas.grid(row=0, column=0, sticky=N+S+E+W)
   xscroll.config(command=canvas.xview)
   yscroll.config(command=canvas.yview)
   frame.pack(fill=BOTH,expand=1)

image = tk.PhotoImage(file=image_str)
image = image.zoom(1,1)
canvas.create_image(0,0,image=large_img,anchor="nw")
canvas.config(scrollregion=canvas.bbox(ALL))   

toolbar = Frame(root, bg="blue")

insertButt = Button(toolbar, text="zoomin", command=lambda:zoomin())
insertButt.pack(side = LEFT, padx=2, pady=2)

toolbar.pack(side=TOP, fill = X)

#function to be called when mouse is clicked
def printcoords(event):
    #outputting x and y coords to console
    print (event.x,event.y)
#mouseclick event
canvas.bind("<Button 1>",printcoords)

#mouseclick event
canvas.bind("<ButtonPress-1>",printcoords)
canvas.bind("<ButtonRelease-1>",printcoords)

root.mainloop()

I would like to thank @Symon for his stackoverflow question. I largely inspired myself from his code

ecjb
  • 5,169
  • 12
  • 43
  • 79

1 Answers1

0

Well, the reason that the function zoomin(img) does not work properly is that it returns in the first line:

def zoomin(img):
    return     # Function returns here
    ... rest of code is never executed

I suspect this is due to the function being run when you create the button, not when you press it. Try cretating the button in this way instead:

insertButt = Button(toolbar, text="zoomin", command=lambda:zoomin(img))

Now the button will call zoomin(img) when it's pressed and not when the button is created.

Zooming with Tkinter

PhotoImage zoom only allows integer values, wich makes it a bit limited. But here's an example:

from tkinter import *

root = Tk()
root.geometry('300x200')

field = Canvas(root, bg='tan1', highlightthickness=0)
field.grid(sticky='news')
photo = PhotoImage(file='test.gif')
field.create_image(0, 0, image=photo, anchor='nw')
scale = 1

def zoom(event=None):
    global scale, photo
    scale = scale * 2
    field.delete('all')
    photo = photo.zoom(x=scale, y=scale)
    field.create_image(0, 0, image=photo, anchor='nw')
    field.image = photo

root.bind('z', zoom)    # Bind "z" to zoom function
root.mainloop()

If you want to zoom by float you'll have to import a module for that. Pillow seems popular. But I haven't worked with any of them so you'll have to research them yourself.

figbeam
  • 7,001
  • 2
  • 12
  • 18
  • Thanks @figbeam I replace my line `insertButt =` with yours but got: `Exception in Tkinter callback Traceback (most recent call last): File "/anaconda3/lib/python3.5/tkinter/__init__.py", line 1558, in __call__ return self.func(*args) File "", line 38, in insertButt = Button(toolbar, text="zoomin", command=lambda:zoomin(img)) TypeError: zoomin() takes 0 positional arguments but 1 was given` – ecjb May 04 '18 at 13:19
  • Are you sure we are running the same code? The way `zoomin` is defined in your code it should take exactly one argument. – figbeam May 04 '18 at 15:22
  • Thanks @figbeam. Yes. So again what I did is I replaced my `insertButt` lines by yours. But then It was not clear for me what I should do with my `def zoomin(img):`. So I didn't change anything – ecjb May 05 '18 at 11:20
  • Zooming seems to be a bit complicated. I've never tried it myself but it's not hard to find examples; [Adding Zooming in and out with a Tkinter Canvas Widget?](https://stackoverflow.com/questions/5436810/adding-zooming-in-and-out-with-a-tkinter-canvas-widget) or perhaps easier by importing a custom module: [To zoom an image in tkinter](https://www.daniweb.com/programming/software-development/threads/427505/to-zoom-an-image-in-tkinter). – figbeam May 05 '18 at 11:40
  • Thanks @figbeam. I already saw those 2 posts. The first one seems to be written in python2. I tried to use then, but I guess I'll have to keep trying and harder... – ecjb May 05 '18 at 12:36
  • I edited a bit the code, now the zoom button works in some way but doesn't do the task I want – ecjb May 05 '18 at 13:45
  • Added an example. – figbeam May 05 '18 at 14:17
  • Many thanks again @figbeam. I ran your code: but instead, it crops the upper left part of the image – ecjb May 05 '18 at 15:24
  • Are you sure you didn't for get the `anchor='nw'` bit, because if you do it will crop the upper left of your image. Otherwise, please post the exact code that you run. – figbeam May 06 '18 at 23:37