I am working on a program where I create some widgets in a for loop. So I need to get the name of them dynamically. I have set up is when the mouse enters the frame. Which holds the two text label widgets. I causes a function to run. And I want to change the background color of a widget with the name of noteName. But I seem to have run into a stopping point and I can no figure it out. I have searched online but could not find much. SO does anyone here know how to get the name of a widget?
Code:
def get_children_hover(event):
for widgets in event.widget.winfo_children():
#This is here where I can not seem to figure out how to get the widgets name.
Can someone push me into the right direction.
winfo_children() is the right thing to use but you are using it wrong. It is a method for parent widgets. (i.e. root, frame, canvas etc..)
Also:
If the order doesn’t matter, you can get the same information from the
children widget attribute (it’s a dictionary mapping Tk widget names
to widget instances, so widget.children.values() gives you a list of
instances).
simple example:
import tkinter as tk
def foo():
print ("Frame:", frm.winfo_children())
print ("Root:", root.winfo_children())
print ("children_values:", root.children.values())
root = tk.Tk()
frm = tk.Frame(root)
tk.Label(root,text="foo").pack()
btn = tk.Button(frm,text="FOOO",command=foo)
frm.pack()
btn.pack()
root.mainloop()
about your code:
def get_children_hover(event):
for widgets in root.winfo_children(): #assuming your Tk() instance named root
Related
from tkinter import *
window=Tk()
Button(window,text='').pack(in=?)
How to set 'in' attribute in pack method? what does that mean?
I looked at the source code of the pack, but I still couldn't understand how to set the ’in' attribute about pack method.
How to set 'in' attribute in pack method?
You must use in_ rather than in. For example:
root = tk.Tk()
frame = tk.Frame(root)
button = tk.Button(root)
button.pack(in_=frame)
what does that mean?
When laying out a widget, every widget except the root window has a master -- some other widget which contains the widget and which controls how it is laid out. By default the master is the same as the parent. For example, if you do Button(window,text=''), the parent of the button is window, and thus its master will also default to window.
You can use in_ to change the master. For example, you could make a button be the child of the root window, but be laid out in some other frame. In the earlier example, the button is a child of the root window but will be a slave inside of the frame.
This is something you almost never need to do with tkinter, since it's usually preferable to have the parent and the master be the same widget.
I have created two frames using Tkinter. In one of the frames I am trying to add a button using a grid. When I run the program, there is no output. Instead it just freezes and I have to kill the process.
Here is the code:
from Tkinter import *
window=Tk()
window.title("calculator")
window.geometry("500x500")
window.resizable(0,0)
input_field=StringVar()
display_frame=Frame(window).pack(side="top")
button_frame=Frame(window).pack(side="bottom")
text=Entry(display_frame,font=('arial',20,'bold'),textvariable=input_field,justify="right").pack(fill="x",ipady=10)
clear_button=Button(button_frame,text="C").grid(row=0)
window.mainloop()
However, if I change the clear_button variable as
clear_button=Button(button_frame,text="C").pack()
I get an output. What am I missing here?
You cannot mix grid and pack inside the same container (a Frame/Window).
That said you should realize that your display_frame and button_frame variables are actually None! Why, because Frame(Window) will return a Frame object, but you have applied the pack() function just after that whose return value is None.
So basically the Entry and the Button widgets that you created have master=None and that means they are not inside the Frames that you defined, but actually part of the main Window.
Now you can easily see why clear_button=Button(button_frame,text="C").pack() was working as now the main window has only one geometry manager namely pack.
Here is the working code.
from tkinter import * # "Tkinter" on python 2
window=Tk()
window.title("calculator")
window.geometry("500x500")
window.resizable(0,0)
input_field=StringVar()
display_frame=Frame(window)
display_frame.pack(side="top")
button_frame=Frame(window)
button_frame.pack(side="bottom")
Entry(display_frame,font=('arial',20,'bold'),textvariable=input_field,justify="right").pack(fill="x",ipady=10)
Button(button_frame, text="C").grid(row=0)
window.mainloop()
You cannot use both grid and pack method on widgets having same master.
Here, follow the below thread for a detailed understanding :
python pack() and grid() methods together
I've been struggling with this for a while. I think I'm missing some simple piece of information and I hope you guys can help clear this up for me.
I'm trying to get tkinter to display different frames which I will eventually place widgets inside of. Here's what I did:
I've made a class that is supposed to initialize the window and make all the different frames the program will run.
I've made a separate class for each frame(I'm intending to have variables associated with the different classes when the program is done), and assigned a variable that will start that class up and make it run it's init function
I ended the StartUp class by telling it to tkraise() the frame I want displayed, and that's where things stop working correctly.
I set each frame to a different color, so when you run this program you will see that they split the screen space up instead of one being raised to the top. What am I missing?
One last point, I am purposely trying to spell everything out in my program, I learn better that way. I left it so I have to type tkinter.blah-blah-blah in front of each tkinter command so I can recognize them easily, and I decided not to have my classes inherit Frame or Tk or anything. I'm trying to understand what I'm doing.
import tkinter
class StartUp:
def __init__(self):
self.root = tkinter.Tk()
self.root.geometry('300x300')
self.container = tkinter.Frame(master=self.root, bg='blue')
self.container.pack(side='top', fill='both', expand=True)
self.page1 = Page1(self)
self.page2 = Page2(self)
self.page1.main_frame.tkraise()
class Page1():
def __init__(self, parent):
self.main_frame = tkinter.Frame(master=parent.container, bg='green')
self.main_frame.pack(side='top', fill='both', expand=True)
class Page2():
def __init__(self, parent):
self.main_frame = tkinter.Frame(master=parent.container, bg='yellow')
self.main_frame.pack(side='top', fill='both', expand=True)
boot_up = StartUp()
boot_up.root.mainloop()
When you do pack(side='top', ...), top doesn't refer to the top of the containing widget, it refers to the top of any empty space in the containing widget. Page initially takes up all of the space, and then when you pack Page2, it goes below Page1 rather than being layered on top of it.
If you are using the strategy of raising one window above another, you need to either use grid or place to layer the widgets on top of each other. The layering is something pack simply can't do.
Your other choice is to call pack_forget on the current window before calling pack on the new windowl
My problem is this. I create a tkinter widget and later down the road I create a new frame that I want to add this widget to. When I call .grid() on the widget the widget is placed on the first frame, not the newer one that I want it to be on.
By default a widget is managed by its parent. If you don't want that, use the parameter in_ when calling pack, place or grid.
For example:
self.f1 = tk.Frame(...)
self.label = tk.Label(self.f1, ...)
self.label.pack(...)
...
self.f2 = tk.Frame(...)
self.label.pack(in_=self.f2, ...)
However, if you find yourself doing this a lot, you're probably doing something wrong. This is almost never necessary in most tkinter applications.
I'm having some trouble figuring out how to use grid properly with tkinter. I just want two labels to appear side by side.
When I do the following, they appear in a separate window from my app. I'm confused because I have buttons on my app that appear as I want them(not using grid), but I can't quite figure out the labels in a grid.
//this is just a snippet from a function
self.root = tk.Tk()
tk.Label(master=self.root, text=directory).grid(row=0,column=0)
tk.Label(master=self.root, text=directory).grid(row=0,column=1)
The root window is created in a different part of the app, so all I'm doing here is making another one (I think). I just want the labels to appear in the window that has already been created but I can't figure out what I'm supposed to reference it to.
This is in a separate file that includes the file with the code above
from Tkinter import *
import tkinter as tk
import widgetActions
import shutil
class mywidgets(widgetActions.Actions):
def __init__(self,root):
frame = tk.Frame(root)
self.makeMenuBar(frame)
frame.pack()
frame.config(width=400)
self.body()
return
def makeMenuBar(self,frame):
menubar = Frame(frame,relief=RAISED,borderwidth=1)
menubar.pack()
mb_file = Menubutton(menubar,text='file')
mb_file.pack(side=LEFT)
mb_file.menu = Menu(mb_file)
mb_file.menu.add_command(label='open', command = self.openfile)
mb_file.menu.add_command(label='close', command = menubar.quit)
mb_file['menu'] = mb_file.menu
return
def body(self):
self.filename()
def main():
root = tk.Tk()
k=mywidgets(root)
root.title('menu bar')
root.mainloop()
main()
You cannot create two instances of Tk. As you observed, you will get two windows. That's not the only problem, just the most obvious one.
You need to pass in a reference to the winget that is to contain these labels. Or, store the root window as a global variable, or as an attribute of an object.
To position the 2 labels side by side i.e label1 and label2:
label1.grid(column=0, row=0)
label2.grid(column=1, row=0)
That should do it