-1

At first I implemented this code which uses classes and worked fine:

from Tkinter import *
import numpy as np
from PIL import Image,ImageTk
import time

#----------------------------------------------------------------------

class MainWindow():

    #----------------

    def __init__(self,main,pix):

        # canvas for image
        self.canvas = Canvas(main, width=424, height=424)
        self.canvas.grid(row=0, column=0)

        # images
        self.im=Image.fromarray(pix.astype('uint8'))
        self.photo = ImageTk.PhotoImage(image=self.im)
        self.my_images = self.photo

        self.my_image_number = 0

        # set first image on canvas
        self.image_on_canvas = self.canvas.create_image(0, 0, anchor = NW, image = self.my_images )
        self.i=0
        self.j=0
        main.after(1,self.onButton,main,pix)# button to change image
        main.update()
    #----------------

    def onButton(self,main,pix):
        print self.i,self.j
        if self.j==100:
            return
        pix[self.i][self.j]=255-pix[self.i][self.j]
        self.i+=1
        if self.i==100:
            self.i=0
            self.j+=1
        self.im=Image.fromarray(pix.astype('uint8'))
        self.photo = ImageTk.PhotoImage(image=self.im)
        self.my_images = self.photo
        self.canvas.itemconfig(self.image_on_canvas, image = self.my_images)
        main.after(1,self.onButton,main,pix)
    else:
        main.after(0,self.onButton,main,pix)

#----------------------------------------------------------------------

root = Tk()
pix=np.array([[(i,j,255) for i in range(256)] for j in range(255,-1,-1)])
x=MainWindow(root,pix)
root.mainloop()

Later I tried to use the same functions without the class and it looks like this:

from Tkinter import *
import numpy as np
from PIL import Image,ImageTk
import time

def onButton(main,pix):
        global i,j
        if j==100:
            return
        pix[i][j]=255-pix[i][j]
        i+=1
        if i==100:
            i=0
            j+=1
        im=Image.fromarray(pix.astype('uint8'))
        photo = ImageTk.PhotoImage(image=im)
        my_images = photo
        canvas.itemconfig(image_on_canvas, image = my_images)
        main.after(1,onButton,main,pix)
    else:
        main.after(0,onButton,main,pix)

root = Tk()
pix=np.array([[(i,j,255) for i in range(256)] for j in range(255,-1,-1)])
canvas = Canvas(root, width=424, height=424)
canvas.grid(row=0, column=0)
im=Image.fromarray(pix.astype('uint8'))
photo = ImageTk.PhotoImage(image=im)
image_on_canvas = canvas.create_image(0, 0, anchor = NW, image = photo )
i,j=0,0
root.after(1,onButton,root,pix)# button to change image
print "hi"
root.mainloop(f i==100:
            i=0
            j+=1
        im=Image.fromarray(pix.astype('uint8'))
        photo = ImageTk.PhotoImage(image=im)
        my_images = photo
        canvas.itemconfig(image_on_canvas, image = my_images)
        main.after(1,onButton,main,pix)
    else:
        main.after(0,onButton,main,pix)

root = Tk()
pix=np.array([[(i,j,255) for i in range(256)] for j in range(255,-1,-1)])
canvas = Canvas(root, width=424, height=424)
canvas.grid(row=0, column=0)
im=Image.fromarray(pix.astype('uint8'))
photo = ImageTk.PhotoImage(image=im)
image_on_canvas = canvas.create_image(0, 0, anchor = NW, image = photo )
i,j=0,0
root.after(1,onButton,root,pix)# button to change image
print "hi"
root.mainloop()

Why does this not work? This is the first time I am working with tkinter, so I am probably missing something crucial. What do I need to change?

rishabh
  • 71
  • 11
  • 1
    There appears to be a copy & paste error in your code. Can you please fix it? The main cause of the new image not appearing in the Canvas is that you need to keep a reference to the .PhotoImage or it will get garbage collected when you exit from the `onButton` function. See the note at the end of the [PhotoImage docs](http://effbot.org/tkinterbook/photoimage.htm). – PM 2Ring Mar 27 '17 at 09:20
  • What does "doesn't work" mean? How is the behavior different than you expect? Do you get errors? If so, what's the error? If not, what is it doing different in the second version? – Bryan Oakley Mar 27 '17 at 11:06
  • don't have two `mainloops` in one program, and don't name them both `root`...and having class is better – Taku Mar 27 '17 at 23:52

1 Answers1

0

I'm curious why you need to implement such a thing without a class, but first let's look at your problem, namely the OnButton function.

You have already defined global variables i and j. But how about others? All variables that you are trying to mutate (and keep value) must also be declared as global! This is a root of your problem and as for the answer to the question "why doesn't it work" - @PM 2Ring give you a good refer to photoimage docs.

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

try:
    from tkinter import *
except ImportError:
    from Tkinter import *

import numpy as np
from PIL import Image,ImageTk


def onButton():
    global i, j, photo     #, pix

    print(i, j)
    if j == 100:
        return
    pix[i][j] = 255-pix[i][j]
    i += 1
    if i == 100:
        i = 0
        j += 1
        photo = ImageTk.PhotoImage(image=Image.fromarray(pix.astype('uint8')))
        canvas.itemconfig(image_on_canvas, image=photo)
        root.after(1, onButton)
    else:
        root.after(0, onButton)


root = Tk()
pix=np.array([[(i, j, 255) for i in range(256)] for j in range(255, -1, -1)])
canvas = Canvas(root, width=424, height=424)
canvas.grid(row=0, column=0)
photo = ImageTk.PhotoImage(image=Image.fromarray(pix.astype('uint8')))
image_on_canvas = canvas.create_image(0, 0, anchor=NW, image=photo)
i, j = 0, 0
root.after(1, onButton)     # button to change image
print("hi")
root.mainloop()

And if there's no need for this variables outside function - then make'em local and move all relevant code into function!

After all, please, take a time to read this article. Maybe you change your mind about the classes (and about wildcard import).

Community
  • 1
  • 1
CommonSense
  • 4,232
  • 2
  • 14
  • 38