This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 2 years ago.
this code is just an example
code:
import tkinter as tk
root = tk.Tk()
photoImageObj = tk.PhotoImage(file="signout.png")
lab = tk.Label(root, image=photoImageObj).pack()
photoImageObjj = tk.PhotoImage(file="signout.png")
signout_button=tk.Button(root,image=photoImageObjj).pack()
root.mainloop()
In this code it is working and output is also working fine.
here is the output:
but in my real project, where I am using this button with the image is not working.
code:
photoImageObj = PhotoImage(file="signout.png")
signout_button=Button(stem,image=photoImageObj).pack()
here I haven't pasted my whole code since it is having 50-60 line's of code.
Output:
so if the same code is working fine, then there is problem in my real project file.
so can anyone help me debug that.
When an image is inside a function you have to keep reference to the image or it will be garbage collected by python. With the code provided its hard to say, but just try something like:
signout_button = Button(stem,image=photoImageObj)
signout_button.pack() #so that signout_button is not None
signout_button.image=photoImageObj #keeping a reference
Alternatively, you could also say global photoImageObj on top of function, but its not recommended to use global. This question should be marked as a duplicate and closed, but just in-case you dont understand what to do in your "specific case", here is the answer.
Related
This question already has an answer here:
When should I use root.update() in tkInter for python
(1 answer)
Closed 1 year ago.
Beginner programmer here currently trying to learn Tkinter for a school assignment.
I have a GUI class that stores the Tkinter labels etc, the labels are innitiated like this:
# GUI for Player 1
self.player_1_name_field = Label(
self.root,
text="Player 1",
font=GUI_Settings.player_information_font,
anchor=W,
background=GUI_Settings.playerfield_active_color
)
I then create a Game() object that looks like this:
class Game():
def __init__(self):
self.GUI = GUI()
self.GUI.initializeBoard()
self.GUI.root.mainloop()
When I run the code, the labels do get created and are where they are supposed to be, but are completely black. Once I move or resize the window it instantly becomes how I want it to be, it just behaves weird when at the start of the code
The interesting thing is that I also have a Canvas and a List that work perfectly fine, only the Labels are not cooperative
If you need further info, just ask for it!
Thank you!
Edit 1: I have a function called drawWindow() that redraws the chessboard when I re-configure the window. In the init of the GUI class I set self.root.bind("<Configure>", self.drawWindow). If I remove that line of code, the Labels work but the Canvas doesn't anymore. I'm so confused. For anyone wanting to take a look at my tiny code: https://codeshare.io/DZYzyZ
See comment of Thingamabobs
The issue is self.root.update(). Remove this line and you'll be fine.
When should I use root.update() in tkInter for python.
This works but you shouldn't do it
This is a tricky issue. Your problem come from the bind of the configure event. Bind to the root window, it is applied to all sub-widgets of the window, which cause the bug (I don't know why yet).
This will solve your issue (line 202):
self.chessboard.bind("<Configure>", self.drawWindow)
instead of:
self.root.bind("<Configure>", self.drawWindow)
Result without moving or resizing the window:
I found the information here (french forum).
This question already has an answer here:
Tkinter assign button command in a for loop with lambda [duplicate]
(1 answer)
Closed 2 years ago.
Here is my code:
buttons=[]
for i in range(100):
buttons.append(Button(parent,text="0",command=lambda:[change(i)])
def change(i):
buttons[i]["text"]="1"
but as finally, the i will go to 99, I could only change the last button no matter which button I clicked. So I wonder is there any good way to do so?
The solution is very easy
Just change the command by below command
command = lambda i=i:change(i)
This will do the job for you.
Your solution not worked as expected because
python passes the last value of i
And hence to resolve this problem
The above command is the solution.
Here lambda is given argument(that is i) at the same time when each execution of loop is going and then that i
is passed to change function which is why it worked
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 3 years ago.
I am trying to get a button to do some stuff in Python (using Tkinter). I want the button to get the current choice of a combobox and print it on screen.
The graphical layout is 3 separate frames, but both the button and the combobox reside in the same frame (frame #2).
The problem is that i cannot refer to the combobox. The errors i am getting read:
Frame object has no attribute 'box'
Window object has no attribute 'box'
self.box=ttk.Combobox(self.frame2 , values[...])
self.button1=tk.Button(self.frame2, command= self.wipe(), text=...)
def wipe(self):
self.box.get()
ALTERNATIVELY i tried:
def wipe(self):
self.frame2.box.get()
The goal is to simply get the selected choice from the Combobox.
HERE IS MINIMAL CODING THAT PRODUCES THE SAME ERROR:
import tkinter as tk
from tkinter import ttk
class window():
def __init__(self,root):
self.frame=tk.Frame(root)
self.key=tk.Button(self.frame,text='PRESS ME',command=self.wipe())
self.box=ttk.Combobox(self.frame, options=['1','2','3'])
self.frame.pack()
self.key.pack()
self.box.pack()
def wipe(self):
self.box.get()
master=tk.Tk()
master.geometry('400x400')
app=window(master)
master.mainloop()
I would add the tag "tkinter" to the question.
Try the following:
def wipe(self):
# code
self.box=ttk.Combobox(self.frame2 , values[...])
self.button1=tk.Button(self.frame2, command=wipe, text=...)
Notice the following:
I first defined wipe, only then used it.
I am not quite sure why you wanted to do command=self.wipe(), as there are two issues here. First, you are setting command to the result of self.wipe() which is NOT a function. Second, you haven't defined self.wipe, you defined wipe.
command=wipe Sets the command keyword argument to the
function wipe
Its been long since I dealt with tkinter, if this doesn't work, I'll try to help by checking the docs again.
This question already has answers here:
Tkinter Frame container color not visible
(2 answers)
Closed 4 years ago.
I feel like I am missing something very basic here. This is my first try creating a GUI in Python. I try to add several frames inside my main window and place stuff inside by using grid manager. The frame creation and sizing and stuff works fine, until I add anything inside the frame. Like in this example with only one frame, when I put my dummy label, the frame just completely vanishes and only the label is displayed.
I really want to understand what is going on and why it is behaving like it is ... and of course, how to fix it. Thanks a lot.
from tkinter import *
window = Tk()
# Window geometry
window.title("Tk")
window.geometry('850x600')
# Set Frames
LeftTopFrame = Frame(window,bg='red',height=200,width=300)
LeftTopFrame.pack(fill=X,side=LEFT)
lblInp = Label(LeftTopFrame, text='Label',font=('Tahoma', 10))
lblInp.grid(column=0,row=0)
window.mainloop()
Tkinter frames shrink or grow to fit their contents. Use
LeftTopFrame.grid_propagate(0)
Every result I've gotten from searching this question up has to do with changing the border color for Tkinter widget's WITHIN the main app window, or changing the background color and stuff.
What I'm looking to do is actually change the windows border color itself. Which I have marked in this picture here
I read some stuff concerning 'Styles' but it didn't seem to be what I was looking for.
Can anyone help point me to a tutorial for changing this, or explain how it can be done?
Or if there is a question that asked exactly the same question I was asking that is answered point me to it.
As I see you are using windows.
This color is set by the theme you are currently using. It is the same for every window.
So I cross out the possibility of only using the Tkinter module for this.
Tkinter is responsible for what is in the window but the window manager decides about the border. For example in Ubuntu the window would look totally different.
I guess, you would need some windows specific calls for that.
You can remove the border with root.overrideredirect(1) if I remember correctly.
PS: put "windows" into the tags of this question.
Hi I was looking for this answer too, found it after like 80 minutes searching, Only work, to activate DWMWA_USE_IMMERSIVE_DARK_MODE
found it here: Can I change the title bar in Tkinter?
I didnt found dwmwindowattribute in dwmwindowattribute that affect Top bar color sadly :(.
For border colour:
It should be possible to call DWMWA_BORDER_COLOR, but honestly I dont know how, there is some article calling it in C++ here:
change-the-color-of-the-title-bar-caption-of-a-win32-application
Tried this but doesnt work:
set_window_attribute(hwnd, 22, '0x000000FF', 4)
Here is working code for pure black top:
import tkinter as tk
import ctypes as ct
def dark_title_bar(window):
"""
MORE INFO:
https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
"""
window.update()
set_window_attribute = ct.windll.dwmapi.DwmSetWindowAttribute
get_parent = ct.windll.user32.GetParent
hwnd = get_parent(window.winfo_id())
value = 2
value = ct.c_int(value)
set_window_attribute(hwnd, 20, ct.byref(value),
4)
root = tk.Tk()
root.title("Crystaly Ball")
root.geometry("1400x900")
root.configure(background="#222246")
dark_title_bar(root)
root.mainloop()