How to print the items in a tkinter window? - python

I have this code:
root= tk.Tk()
button1 = tk.Button(root, text='Button', command=lambda:print("Click"))
button1.grid(row=1, column=1)
Label = tk.Label(root, text="Text")
Label.grid(row=1, column=2)
root.mainloop()
What I want to get:
Button:(1, 1), Label:(1, 2)
How can I print the items and their destinations in root?

If you just want to get the information about grid, use grid_info() could get the info about the widget.To get all the widgets on root, just use root.winfo_children().
import tkinter as tk
root = tk.Tk()
button1 = tk.Button(root, text='Button', command=lambda:print("Click"))
button1.grid(row=1, column=1)
Label = tk.Label(root, text="Text")
Label.grid(row=1, column=2)
for widget in root.winfo_children():
print(f"{widget.widgetName}:({ widget.grid_info()['row']}, {widget.grid_info()['column']})")
root.mainloop()
Result:
button:(1, 1)
label:(1, 2)

Would this solve it? What you do is create a function that generates a label in root and then give it to the command argument of your button.
import tkinter as tk
root= tk.Tk()
def x():
y = tk.Label(root, text = "Click")
y.grid(row = 2, column = 1)
button1 = tk.Button(root, text='Button', command=x)
button1.grid(row=1, column=1)
Label = tk.Label(root, text="Text")
Label.grid(row = 2, column = 1)
root.mainloop()

Related

how to update getting results from an entry box automatically?

I want to update getting results from an entry box in a way that when an integer enters, the equivalent rows of entry boxes appear below that. I have written the below code to make it work using a button. However, I want to make it happen automatically without a button as I entered the number, the rows update. I checked one way of doing that is using the after(). I placed after after() in the function and out of the function but it is not working.
from tkinter import *
root = Tk()
root.geometry("400x400")
n_para = IntVar()
label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)
entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)
def update():
for i in range(1, n_para.get()+1):
entryX = Entry(root)
entryX.grid(row=i+1, column=0)
entryY = Entry(root)
entryY.grid(row=i+1, column=1)
entryZ = Entry(root)
entryZ.grid(row=i+1, column=2)
root.after(100, update)
root.after(1, update)
button1 = Button(root, text="update", command=update)
button1.grid(row=1, column=0)
root.mainloop()
You should try using the <KeyRelease> event bind.
import tkinter as tk
def on_focus_out(event):
label.configure(text=inputtxt.get())
root = tk.Tk()
label = tk.Label(root)
label.pack()
inputtxt = tk.Entry()
inputtxt.pack()
root.bind("<KeyRelease>", on_focus_out)
root.mainloop()
This types the text entered in real-time.
Edited Code with OP's requirement:
from tkinter import *
root = Tk()
root.geometry("400x400")
n_para = IntVar()
label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)
entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)
def upd(event):
x = entry1.get()
if not x.isnumeric():
x = 0
for i in range(1, int(x)+1):
entryX = Entry(root)
entryX.grid(row=i+1, column=0)
entryY = Entry(root)
entryY.grid(row=i+1, column=1)
entryZ = Entry(root)
entryZ.grid(row=i+1, column=2)
# root.after(100, update)
root.bind("<KeyRelease>", upd)
# button1 = Button(root, text="update", command=update)
# button1.grid(row=1, column=0)
root.mainloop()

Why isn't my label configuring correctly? [duplicate]

This question already has answers here:
Why isn't this label changing when I use the tkinter config option
(2 answers)
Closed 1 year ago.
I want this label to configure into the text entry after the user enters the text and hits go but the label isn't configuring.
I want the label that says "Hello!" to change into whatever is put in the main entry. I'm looking for an answer written in full code instead of one fixed line.
Here's my code:
import tkinter as tk
root = tk.Tk()
root.attributes('-fullscreen', True)
exit_button = tk.Button(root, text="Exit", command = root.destroy)
exit_button.place(x=1506, y=0)
def answer():
answer_label.config(text=main_entry.get())
entry_frame = tk.Frame(root)
main_entry = tk.Entry(entry_frame, width=100)
main_entry.grid(row=0, column=0)
go_button = tk.Button(entry_frame, text= 'Go!', width=85, command= answer)
go_button.grid(row=1, column=0)
answer_label = tk.Label(text = "Hello!").pack()
entry_frame.place(relx=.5, rely=.5, anchor='center')
root.mainloop()
1.Split tk.Label and pack().
2.Pass the lable.
import tkinter as tk
root = tk.Tk()
root.attributes('-fullscreen', True)
exit_button = tk.Button(root, text="Exit", command = root.destroy)
exit_button.place(x=1506, y=0)
def answer(answer_label):
answer_label.config(text=main_entry.get())
entry_frame = tk.Frame(root)
main_entry = tk.Entry(entry_frame, width=100)
main_entry.grid(row=0, column=0)
answer_label = tk.Label(text = "Hello!")
answer_label.pack()
go_button = tk.Button(entry_frame, text= 'Go!', width=85, command=lambda: answer(answer_label))
go_button.grid(row=1, column=0)
entry_frame.place(relx=.5, rely=.5, anchor='center')
root.mainloop()

Looking for a solution to a tkinter error and efficiency/design problems

The code below represents my first steps into making a calculator on python using tkinter. The idea is to put the numbers on a grid accordingly, and then make the all of the necessary adjustments. The problem here is that I get the following error:
_tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack
I'm aware that this is because of the canvas.pack(), but isn't it necessary for the background? How can I separate them in the most efficient way possible? On that note, is there a way to put all of the buttons/grids together using fewer lines of code? Thanks in advance.
from tkinter import *
#Creating the window function (?)
window = Tk()
#Creating a frame and a background for the calculator
canvas = tk.Canvas(window, height=700, width=700, bg="#83CFF1")
canvas.pack()
frame = tk.Frame(window, bg="white")
frame.place(relwidth=0.7, relheight=0.7, relx=0.15, rely=0.15)
#Creating the buttons for the calculator
button1 = Label(window, text="1")
button2 = Label(window, text="2")
button3 = Label(window, text="3")
button4 = Label(window, text="4")
button5 = Label(window, text="5")
button6 = Label(window, text="6")
button7 = Label(window, text="7")
button8 = Label(window, text="8")
button9 = Label(window, text="9")
button0 = Label(window, text="0")
#Adding it to the screen
button1.grid(row=0, column=0)
button2.grid(row=0, column=1)
button3.grid(row=0, column=2)
button4.grid(row=1, column=0)
button5.grid(row=1, column=1)
button6.grid(row=1, column=2)
button7.grid(row=2, column=0)
button8.grid(row=2, column=1)
button9.grid(row=2, column=2)
button0.grid(row=3, column=1)
#Ending the loop (?)
window.mainloop()
Create buttons using Python list comprehension.
For the grid placment use i // 3 (floor division) and i % 3 (modulo) inside a for loop.
Then just simply add the last button manually.
This code below will do the trick:
import tkinter as tk
window = tk.Tk()
frame = tk.Frame(window, bg="white")
frame.place(relwidth=0.7, relheight=0.7, relx=0.15, rely=0.15)
#Creating the buttons for the calculator
buttons = [tk.Button(frame, text = i) for i in range(1, 10)]
for i, button in enumerate(buttons):
button.grid(row = i // 3, column = i % 3)
#Add last button 0
buttons.append(tk.Button(frame, text = 0))
buttons[-1].grid(row=3, column=1)
window.mainloop()

Is using if statements possible with Tkinter Buttons

What I would like to occur is that when I press the other button, the first label is destroyed and only the corresponding label is on the GUI. Is there a way to incorporate If statements into this or should I approach it another way?
from tkinter import *
root = Tk()
root.geometry("250x50")
def func1():
label = Label(root, text = 'Hello', fg="White", bg="Orange" )
label.pack(fill=BOTH, expand=True)
def func2():
label = Label(root, text = 'Goodbye', fg="White", bg="Orange" )
label.pack(fill=BOTH, expand=True)
button1 = Button(root, text = "Button 1", command = func1, fg="White",
bg="Black", width=10, height=5)
button1.pack(side=LEFT)
button2 = Button(root, text = "Button 2", command = func2, fg="White",
bg="Black", width=10, height=5)
button2.pack(side=LEFT)
root.mainloop()
Here is the approach that #jasonsharper proposed: It is indeed easier to have a single Label, created at the start, then to use the two buttons to set its text, and other properties.
import tkinter as tk
if __name__ == '__main__':
root = tk.Tk()
root.geometry("250x50")
def set_label(txt):
label['text'] = txt
label['fg'] = "White"
label['bg'] = "Orange"
button1 = tk.Button(root, text = "Button 1", command = lambda x='hello': set_label(x), fg="White", bg="Black", width=10, height=5)
button1.pack(side=tk.LEFT)
button2 = tk.Button(root, text = "Button 2", command = lambda x='bye': set_label(x), fg="White", bg="Black", width=10, height=5)
button2.pack(side=tk.LEFT)
label = tk.Label(root, text='')
label.pack(fill=tk.BOTH, expand=True)
root.mainloop()
Note:
Please avoid import * --> to keep your namespace clean, use import tkinter as tk

Grid and Entry, Correct Alignment

How would I implement this in TkInter with Python?
Two numbers are input as the width and height, and are then saved to Mapwidth and Mapheight respectively. When the Confirm button is hit, the window closes.
More or less:
import tkinter as tk
# --- function ---
def on_confirm():
print('Mapwidth:', e1.get())
print('Mapheight:', e2.get())
root.destroy()
# --- main ---
root = tk.Tk()
l = tk.Label(root, text="Width")
l.grid(row=0, column=0)
e1 = tk.Entry(root)
e1.grid(row=0, column=1)
l = tk.Label(root, text="Height")
l.grid(row=1, column=0)
e2 = tk.Entry(root)
e2.grid(row=1, column=1)
b = tk.Button(root, text="Confirm", command=on_confirm)
b.grid(row=2, column=0, columnspan=2)
root.mainloop()

Categories