Use an image-button defined inside an object with TKinter












3















I'm trying to build a tkinter button with an image as background inside an object. It doesn't make any sense why the second implementation doesn't work !



Here are 3 very simple examples ; Who can explain the reason why the second implementation is not working?



(Python 3.6.4 :: Anaconda, Inc.)



1. Button created globally.



Works like a charm...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
def cb():
print("Hello World")
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=cb, image=image)
b.pack()
w.mainloop()


2. Button created inside the object A with a background image



The button doesn't work when clicked and doesn't display the image :(. There's clearly a problem but I don't understand it...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()


3. Button created inside the object A without a background image



The button works properly, but I would like to display the image as well



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb)#, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()









share|improve this question























  • Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

    – toti08
    Nov 14 '18 at 14:28











  • However if you make it a class variable it works....

    – toti08
    Nov 14 '18 at 14:29











  • Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

    – Mike - SMT
    Nov 14 '18 at 14:32








  • 1





    @toti08 indeed… and actually, it's in the doc of PhotoImage 😳

    – Jav
    Nov 14 '18 at 14:32








  • 1





    @toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

    – Mike - SMT
    Nov 14 '18 at 14:42
















3















I'm trying to build a tkinter button with an image as background inside an object. It doesn't make any sense why the second implementation doesn't work !



Here are 3 very simple examples ; Who can explain the reason why the second implementation is not working?



(Python 3.6.4 :: Anaconda, Inc.)



1. Button created globally.



Works like a charm...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
def cb():
print("Hello World")
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=cb, image=image)
b.pack()
w.mainloop()


2. Button created inside the object A with a background image



The button doesn't work when clicked and doesn't display the image :(. There's clearly a problem but I don't understand it...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()


3. Button created inside the object A without a background image



The button works properly, but I would like to display the image as well



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb)#, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()









share|improve this question























  • Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

    – toti08
    Nov 14 '18 at 14:28











  • However if you make it a class variable it works....

    – toti08
    Nov 14 '18 at 14:29











  • Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

    – Mike - SMT
    Nov 14 '18 at 14:32








  • 1





    @toti08 indeed… and actually, it's in the doc of PhotoImage 😳

    – Jav
    Nov 14 '18 at 14:32








  • 1





    @toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

    – Mike - SMT
    Nov 14 '18 at 14:42














3












3








3








I'm trying to build a tkinter button with an image as background inside an object. It doesn't make any sense why the second implementation doesn't work !



Here are 3 very simple examples ; Who can explain the reason why the second implementation is not working?



(Python 3.6.4 :: Anaconda, Inc.)



1. Button created globally.



Works like a charm...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
def cb():
print("Hello World")
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=cb, image=image)
b.pack()
w.mainloop()


2. Button created inside the object A with a background image



The button doesn't work when clicked and doesn't display the image :(. There's clearly a problem but I don't understand it...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()


3. Button created inside the object A without a background image



The button works properly, but I would like to display the image as well



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb)#, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()









share|improve this question














I'm trying to build a tkinter button with an image as background inside an object. It doesn't make any sense why the second implementation doesn't work !



Here are 3 very simple examples ; Who can explain the reason why the second implementation is not working?



(Python 3.6.4 :: Anaconda, Inc.)



1. Button created globally.



Works like a charm...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
def cb():
print("Hello World")
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=cb, image=image)
b.pack()
w.mainloop()


2. Button created inside the object A with a background image



The button doesn't work when clicked and doesn't display the image :(. There's clearly a problem but I don't understand it...



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()


3. Button created inside the object A without a background image



The button works properly, but I would like to display the image as well



from tkinter import *
from PIL import Image, ImageTk
from numpy import random
w = Tk()
class A():
def __init__(self, w):
image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb)#, image=image)
b.pack()

def cb(self):
print("Hello World")

a = A(w)
w.mainloop()






python tkinter python-imaging-library tk






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 14 '18 at 14:13









JavJav

451527




451527













  • Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

    – toti08
    Nov 14 '18 at 14:28











  • However if you make it a class variable it works....

    – toti08
    Nov 14 '18 at 14:29











  • Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

    – Mike - SMT
    Nov 14 '18 at 14:32








  • 1





    @toti08 indeed… and actually, it's in the doc of PhotoImage 😳

    – Jav
    Nov 14 '18 at 14:32








  • 1





    @toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

    – Mike - SMT
    Nov 14 '18 at 14:42



















  • Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

    – toti08
    Nov 14 '18 at 14:28











  • However if you make it a class variable it works....

    – toti08
    Nov 14 '18 at 14:29











  • Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

    – Mike - SMT
    Nov 14 '18 at 14:32








  • 1





    @toti08 indeed… and actually, it's in the doc of PhotoImage 😳

    – Jav
    Nov 14 '18 at 14:32








  • 1





    @toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

    – Mike - SMT
    Nov 14 '18 at 14:42

















Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

– toti08
Nov 14 '18 at 14:28





Tricky indeed...and if you declare your image outside the class it works...maybe this question could help...

– toti08
Nov 14 '18 at 14:28













However if you make it a class variable it works....

– toti08
Nov 14 '18 at 14:29





However if you make it a class variable it works....

– toti08
Nov 14 '18 at 14:29













Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

– Mike - SMT
Nov 14 '18 at 14:32







Simple answer is you need to add a special argument to the button that tells it to use both the image and text. compound. And change image to self.image.

– Mike - SMT
Nov 14 '18 at 14:32






1




1





@toti08 indeed… and actually, it's in the doc of PhotoImage 😳

– Jav
Nov 14 '18 at 14:32







@toti08 indeed… and actually, it's in the doc of PhotoImage 😳

– Jav
Nov 14 '18 at 14:32






1




1





@toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

– Mike - SMT
Nov 14 '18 at 14:42





@toti08 just to clarify you mean a class attribute. A variable is what they are using now. The class attribute is what we create with self..

– Mike - SMT
Nov 14 '18 at 14:42












2 Answers
2






active

oldest

votes


















1














I think I understood what happened. Thanks to the linked question what's happening in the second case is that your image gets garbage collected once the __init__ method is finished. As a result your image is not available anymore to the root application, so it cannot be binded to it.
The way to solve it is to make it a class attribute:



class A():
def __init__(self, w):
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=self.image)
b.pack()

def cb(self):
print("Hello World")





share|improve this answer


























  • This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

    – Mike - SMT
    Nov 14 '18 at 14:43













  • @Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

    – toti08
    Nov 14 '18 at 14:45











  • Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

    – Mike - SMT
    Nov 14 '18 at 14:46













  • That's because in example #3 he commented the image=image part out...at least I interpreted like this...

    – toti08
    Nov 14 '18 at 14:47











  • Maybe but all 3 code examples use text.

    – Mike - SMT
    Nov 14 '18 at 14:48



















2














You have 2 problems here.



The first problem is the image is not being saved after __init__. You probably know you need to save a reference to the image for it to be used in tkinter. You may not know that in a class if you do not assign the image to a class attribute it will not save the image after __init__.



So to fix the first issue you need change this:



image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


To this:



# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


The 2nd issue you may not notice here is that your text will not display while loading an image. This is because you need to add the argument compound in order for tkinter to display both an image and text in the button. That said you also need to update the image argument to include the new self.image.



So change this:



b = Button(w, text="text", command=self.cb, image=image)


To this:



# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)


Results:



enter image description here






share|improve this answer


























  • Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

    – Jav
    Nov 15 '18 at 8:48











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53302234%2fuse-an-image-button-defined-inside-an-object-with-tkinter%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














I think I understood what happened. Thanks to the linked question what's happening in the second case is that your image gets garbage collected once the __init__ method is finished. As a result your image is not available anymore to the root application, so it cannot be binded to it.
The way to solve it is to make it a class attribute:



class A():
def __init__(self, w):
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=self.image)
b.pack()

def cb(self):
print("Hello World")





share|improve this answer


























  • This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

    – Mike - SMT
    Nov 14 '18 at 14:43













  • @Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

    – toti08
    Nov 14 '18 at 14:45











  • Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

    – Mike - SMT
    Nov 14 '18 at 14:46













  • That's because in example #3 he commented the image=image part out...at least I interpreted like this...

    – toti08
    Nov 14 '18 at 14:47











  • Maybe but all 3 code examples use text.

    – Mike - SMT
    Nov 14 '18 at 14:48
















1














I think I understood what happened. Thanks to the linked question what's happening in the second case is that your image gets garbage collected once the __init__ method is finished. As a result your image is not available anymore to the root application, so it cannot be binded to it.
The way to solve it is to make it a class attribute:



class A():
def __init__(self, w):
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=self.image)
b.pack()

def cb(self):
print("Hello World")





share|improve this answer


























  • This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

    – Mike - SMT
    Nov 14 '18 at 14:43













  • @Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

    – toti08
    Nov 14 '18 at 14:45











  • Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

    – Mike - SMT
    Nov 14 '18 at 14:46













  • That's because in example #3 he commented the image=image part out...at least I interpreted like this...

    – toti08
    Nov 14 '18 at 14:47











  • Maybe but all 3 code examples use text.

    – Mike - SMT
    Nov 14 '18 at 14:48














1












1








1







I think I understood what happened. Thanks to the linked question what's happening in the second case is that your image gets garbage collected once the __init__ method is finished. As a result your image is not available anymore to the root application, so it cannot be binded to it.
The way to solve it is to make it a class attribute:



class A():
def __init__(self, w):
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=self.image)
b.pack()

def cb(self):
print("Hello World")





share|improve this answer















I think I understood what happened. Thanks to the linked question what's happening in the second case is that your image gets garbage collected once the __init__ method is finished. As a result your image is not available anymore to the root application, so it cannot be binded to it.
The way to solve it is to make it a class attribute:



class A():
def __init__(self, w):
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))
b = Button(w, text="text", command=self.cb, image=self.image)
b.pack()

def cb(self):
print("Hello World")






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 14 '18 at 14:43

























answered Nov 14 '18 at 14:33









toti08toti08

1,76441623




1,76441623













  • This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

    – Mike - SMT
    Nov 14 '18 at 14:43













  • @Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

    – toti08
    Nov 14 '18 at 14:45











  • Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

    – Mike - SMT
    Nov 14 '18 at 14:46













  • That's because in example #3 he commented the image=image part out...at least I interpreted like this...

    – toti08
    Nov 14 '18 at 14:47











  • Maybe but all 3 code examples use text.

    – Mike - SMT
    Nov 14 '18 at 14:48



















  • This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

    – Mike - SMT
    Nov 14 '18 at 14:43













  • @Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

    – toti08
    Nov 14 '18 at 14:45











  • Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

    – Mike - SMT
    Nov 14 '18 at 14:46













  • That's because in example #3 he commented the image=image part out...at least I interpreted like this...

    – toti08
    Nov 14 '18 at 14:47











  • Maybe but all 3 code examples use text.

    – Mike - SMT
    Nov 14 '18 at 14:48

















This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

– Mike - SMT
Nov 14 '18 at 14:43







This will correct the image issue but does not display text. So this is not quite a complete solution for the issue with the 2nd and 3rd block's of code.

– Mike - SMT
Nov 14 '18 at 14:43















@Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

– toti08
Nov 14 '18 at 14:45





@Mike-SMT in the original question the issue was with the image and the functioning of the button. I honestly didn't check the text displayed in the button...

– toti08
Nov 14 '18 at 14:45













Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

– Mike - SMT
Nov 14 '18 at 14:46







Well the OP states The button works properly, but I would like to display the image as well so with that I would think the OP wants both the text and image to work. And considering they have both a text and image argument they likely want to use both.

– Mike - SMT
Nov 14 '18 at 14:46















That's because in example #3 he commented the image=image part out...at least I interpreted like this...

– toti08
Nov 14 '18 at 14:47





That's because in example #3 he commented the image=image part out...at least I interpreted like this...

– toti08
Nov 14 '18 at 14:47













Maybe but all 3 code examples use text.

– Mike - SMT
Nov 14 '18 at 14:48





Maybe but all 3 code examples use text.

– Mike - SMT
Nov 14 '18 at 14:48













2














You have 2 problems here.



The first problem is the image is not being saved after __init__. You probably know you need to save a reference to the image for it to be used in tkinter. You may not know that in a class if you do not assign the image to a class attribute it will not save the image after __init__.



So to fix the first issue you need change this:



image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


To this:



# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


The 2nd issue you may not notice here is that your text will not display while loading an image. This is because you need to add the argument compound in order for tkinter to display both an image and text in the button. That said you also need to update the image argument to include the new self.image.



So change this:



b = Button(w, text="text", command=self.cb, image=image)


To this:



# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)


Results:



enter image description here






share|improve this answer


























  • Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

    – Jav
    Nov 15 '18 at 8:48
















2














You have 2 problems here.



The first problem is the image is not being saved after __init__. You probably know you need to save a reference to the image for it to be used in tkinter. You may not know that in a class if you do not assign the image to a class attribute it will not save the image after __init__.



So to fix the first issue you need change this:



image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


To this:



# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


The 2nd issue you may not notice here is that your text will not display while loading an image. This is because you need to add the argument compound in order for tkinter to display both an image and text in the button. That said you also need to update the image argument to include the new self.image.



So change this:



b = Button(w, text="text", command=self.cb, image=image)


To this:



# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)


Results:



enter image description here






share|improve this answer


























  • Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

    – Jav
    Nov 15 '18 at 8:48














2












2








2







You have 2 problems here.



The first problem is the image is not being saved after __init__. You probably know you need to save a reference to the image for it to be used in tkinter. You may not know that in a class if you do not assign the image to a class attribute it will not save the image after __init__.



So to fix the first issue you need change this:



image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


To this:



# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


The 2nd issue you may not notice here is that your text will not display while loading an image. This is because you need to add the argument compound in order for tkinter to display both an image and text in the button. That said you also need to update the image argument to include the new self.image.



So change this:



b = Button(w, text="text", command=self.cb, image=image)


To this:



# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)


Results:



enter image description here






share|improve this answer















You have 2 problems here.



The first problem is the image is not being saved after __init__. You probably know you need to save a reference to the image for it to be used in tkinter. You may not know that in a class if you do not assign the image to a class attribute it will not save the image after __init__.



So to fix the first issue you need change this:



image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


To this:



# add self. to make it a class attribute and keep the reference alive for the image.
self.image = ImageTk.PhotoImage(image=Image.fromarray(random.random((50,50))))


The 2nd issue you may not notice here is that your text will not display while loading an image. This is because you need to add the argument compound in order for tkinter to display both an image and text in the button. That said you also need to update the image argument to include the new self.image.



So change this:



b = Button(w, text="text", command=self.cb, image=image)


To this:



# added compound and change text color so you can see it.
b = Button(w, compound="center" , text="text", fg="white", command=self.cb, image=self.image)


Results:



enter image description here







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 14 '18 at 15:08

























answered Nov 14 '18 at 14:41









Mike - SMTMike - SMT

9,54921434




9,54921434













  • Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

    – Jav
    Nov 15 '18 at 8:48



















  • Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

    – Jav
    Nov 15 '18 at 8:48

















Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

– Jav
Nov 15 '18 at 8:48





Thx. I realize my question was unclear about the "text". I don't need/want to make a text appear. I should have removed that option from the Button in the two first code snippets. Anyway, thanks for your answer which explains everything

– Jav
Nov 15 '18 at 8:48


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53302234%2fuse-an-image-button-defined-inside-an-object-with-tkinter%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python