I want to get a value from another window?(python, tkinter) - python

I wanted to get a value from another window so i saved the value using xlsxwriter and got it using pandas but the problem is that i get the value not after the that window is destroyed but after the main window is closed?
can you tell me how i get the value without closing the main window??

Here is a helpful link with a simple solution to what you are attempting to accomplish. Basically, you need one frame to accept a variable as input and the other frame to 'get' the variable from the first frame.
https://www.code4example.com/python/tkinter/tkinter-passing-variables-between-windows/
** copied here from source for simplicity **
from tkinter import *
class Frames(object):
def newFrame(self):
newwin = Toplevel(root)
newwin.title('New Window')
newwin.geometry("200x100")
newwin.resizable(0, 0)
#getting parameter via query var
display = Label(newwin, text="Hello, " + self.query.get())
display.pack()
def mainFrame(self,root):
self.query = StringVar() #passing parameter via query var
root.title('Open Window!!!')
root.geometry("200x200")
root.resizable(0, 0)
button1 =Button(root, text ="Open and Send New Window", command =self.newFrame)
button1.place(x = 15, y = 25, width=170, height=25)
entry1 = Entry(root, textvariable=self.query)
entry1.place(x = 50, y = 75, width=100, height=25)
root = Tk()
app = Frames()
app.mainFrame(root)
root.mainloop()

Related

Tkinter IntVar weird Value

I made a new object of tk.IntVar and called it pwHardness
but its value is something random like 140358607937898IntVar.
i want the radio buttons to set the value of the variable pwHardness 1 or 2
import tkinter as tk
pwHardness = tk.IntVar
window = tk.Tk()
window.geometry("1600x500")
window.configure(bg="#323e52")
Label = tk.Label(text="Password Gen", background="#323e52", foreground="#fafafa")
Label.config(width=200)
Label.config(font=("Courier", 44))
setPwRadioButtonEasy = tk.Radiobutton(
text="Easy PW",
padx = 20,
var=pwHardness,
variable=pwHardness,
value=1,
)
setPwRadioButtonHard = tk.Radiobutton(
text="Hard PW",
padx = 20,
var=pwHardness,
variable=pwHardness,
value=2,
)
label1 = tk.Label(text=pwHardness)
Label.pack()
setPwRadioButtonEasy.pack()
setPwRadioButtonHard.pack()
label1.pack()
window.mainloop()
FYI This is going to be a Password Generator.
You aren't initializing the variable, you're just taking the IntVar object.
pwHardness = tk.IntVar()
would initialize a new IntVar – you're missing the parentheses.
Additionally, you're passing the var as a "string" value to text.
You'd want
label1 = tk.Label(text=pwHardness.get())
to "read" the variable into the label. However, it won't refresh automatically with that configuration.
You are missing parentheses after pwHardness = tk.IntVar. It should be pwHardness = tk.IntVar(). Additionally, change label1 = tk.Label(text=pwHardness) to label1 = tk.Label(textvar=pwHardness), so the label gets automatically updated. And, tk.IntVar must be initiated with a parent, e.g. the toplevel window. Example :
import tkinter as tk
root = tk.Tk()
var = tk.IntVar(root)
label = tk.Label(root, textvar=var)
label.pack()
while True:
inp = input("enter new value ")
if inp != "quit":
var.set(int(inp))
else:
break

How do I delete a Tkinter label using a button command?

I want my program to run in a way that once the user presses the Info button, a label called GameInfoLabel is displayed due to a command from the Info button. Within the same condition (if the Info button is pressed), I want to add a Back button that deletes/destroys the GameInfoLabel.
I have attempted to implement this in the code below, but I'm getting the message
NameError: name 'GameInfoLabel' is not defined.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def QuitGameInfo():
GameInfoLabel.destroy()
BackInfoButton['state'] = NORMAL
def GameInfo():
RulesNotepad = open("GameInfo.txt",'r')
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140").pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack()
RulesNotepad.close()
button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()
root.mainloop()
The error is due to that GameInfoLabel is a local variable inside GameInfo() and it is not accessible inside QuitGameInfo().
You can fix this error by either declaring GameInfoLabel as global or pass it to QuitGameInfo() via argument. Same apply on BackInfoButton as well.
However you need to fix another issue: both GameInfoLabel and BackInfoButton are None because they are result of pack().
Below is the modified code using global solution:
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def QuitGameInfo():
GameInfoLabel.destroy()
#BackInfoButton['state'] = NORMAL # why ??? Should it be destroyed as well?
BackInfoButton.destroy()
def GameInfo():
global GameInfoLabel, BackInfoButton
with open("GameInfo.txt",'r') as RulesNotepad:
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
GameInfoLabel.pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo)
BackInfoButton.pack()
Button(root, text = "Info", command = GameInfo, width = "20", height = "3").pack()
root.mainloop()
However I would suggest to use a frame to hold the GameInfoLabel and BackInfoButton and the frame is hidden initially. When Info button is clicked, show the frame. When Back button is clicked, hide the frame.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
def GameInfo():
with open("GameInfo.txt",'r') as RulesNotepad:
Rules = RulesNotepad.read()
GameInfoLabel.config(text=Rules)
info_frame.pack() # show the game info frame
Button(root, text="Info", command=GameInfo, width="20", height="3").pack()
# create the game info frame but don't show it initially
info_frame = Frame(root)
GameInfoLabel = Label(info_frame, fg="blue", bg="red", height="14", width="140")
GameInfoLabel.pack()
Button(info_frame, text="Back", command=info_frame.pack_forget).pack()
root.mainloop()
As mentioned in acw1668's comment GameInfoLabel is local to the GameInfo() method. This means once this method has finished running anything declared in it ceases to exist.
The usual solution to this is passing/returning variables to functions to get results for instance your game info could return the label, however since you want to call these functions automatically when an event occurs, e.g. your button is pressed, this is not so easy.
I believe the easiest solution to your problem would be to declare the GameInfoLabel variable globally (in the global scope), this is not always the best coding practice but I'm not certain of tkinter's ability to pass variables parameters to an event handler and this can be complicated.
Also as mentioned by acw1668 you call .pack() immediately on the new label which is returned from the initialization Label(...). Pack then does not return the label so we do that separately.
This should work, give it a careful read.
from tkinter import *
root = Tk()
root.title("Game Menu")
root.geometry("1920x1080")
root.resizable(True, True)
# Declare any global UI Components
GameInfoLabel = None # Dont set a Label yet
def QuitGameInfo():
GameInfoLabel.destroy()
BackInfoButton['state'] = NORMAL
def GameInfo():
RulesNotepad = open("GameInfo.txt",'r')
Rules = RulesNotepad.read()
GameInfoLabel = Label(root, text = Rules, fg = "blue", bg = "red", height = "14", width = "140")
GameInfoLabel.pack()
BackInfoButton = Button(root, text = "Back", command = QuitGameInfo).pack()
RulesNotepad.close()
button3 = Button(root, text = "Info", command = GameInfo, width = "20", height = "3")
button3.pack()
root.mainloop()

Python/Tkinter - clear the graphical interface screen

i am developing an application to calculate some taxes and show the result in the graphical interface. The code itself works perfectly, but if i use numbers with bigger squares, the result overlaps over the previous one. My question is, is it possible to clear the previous result and calculate the new one?
Follow the complete code below:
from tkinter import *
root = Tk()
l_vlrRec = Label(root, text='Receita')
l_vlrRec.place(x=10, y=10)
e_vlrRec = Entry(root)
e_vlrRec.place(x=75, y=10, width=75)
def calcular():
receita = float(e_vlrRec.get())
l_result = Label(root, text='{:.2f}'.format(receita))
l_result.place(x=10, y=150)
e_vlrRec.delete(0, END)
bt = Button(root, text='Calcular', command=calcular)
bt.place(x=10, y=50)
root.mainloop()
You can use the label's textvariable and also you don't have to instantiate a new Label every time the button is pressed:
v_result = DoubleVar()
l_result = Label(root, textvariable=v_result)
l_result.place(x=10, y=150)
def calcular():
v_result.set(round(float(e_vlrRec.get()),2))
You can do the same for your Entry object e_vlrRec so you don't have to cast the string you get by calling e_vlrRec.get() but use the variable's get() instead
Without using textvariable you can also reconfigure the label's text parameter:
l_result.configure(text='{:.2f}'.format(receita))
or
l_result['text'] = '{:.2f}'.format(receita)

Problem when defining a function in python with tkinter

Im making a program that searches a website for a specific word.
Exampel : Word: football on the website fifa.com.
I made it in a terminal which was very easy. Now i want to make a program using tkinter and it wont work.
The problem i have is when i run my program it says
File "c:/Users/Censored/Desktop/PythonFolder/Program.py", line 22, in
temp = Button(root, text='GO', command=searchgo)
NameError: name 'searchgo' is not defined
This is my code:
import requests
import re
from tkinter import *
root = Tk()
root.title('WordCounter')
root.configure(bg='#2f3136')
root.geometry('700x700')
root.resizable(False, False)
# Buttons
e1 = Entry(root, width='35')
label1 = Label(root, text='Write The Word You Want To Search For', bg='#2f3136', fg='white',)
e2 = Entry(root, width='35')
label2 = Label(root, text='Write the websites URL', bg='#2f3136', fg='white',)
temp = Button(root, text='GO', command=searchgo)
# Buttons on screen
label1.grid(row='1', column='1',padx='10')
e1.grid(row='2', column='1', padx='10')
label2.grid(row='1', column='2', padx='10')
e2.grid(row='2', column='2', padx='10')
temp.pack()
# Define Functions
def searchgo():
word = e1.get()
URL = e2.get()
page = requests.get(URL).text
print(page.find(word))
root.mainloop()
Thanks for helping me!
Your code has couple of bugs,
Define the function searchgo before you assign the callback to your button
In this code, better use grid to place you button instead of place or you get the following error
cannot use geometry manager pack inside . (root) which already has slaves managed by grid
The reason of this error is that, you cannot use pack and grid geometry managers inside the same master window (root in this program). Since you have used grid for most of the widgets, use grid for placing the button also.
Also, in case you are not aware, in grid geometry manager row and column position values start at 0 and not 1
Here is the code:
import requests
import re
from tkinter import *
root = Tk()
root.title('WordCounter')
root.configure(bg='#2f3136')
root.geometry('700x700')
root.resizable(False, False)
# Buttons
e1 = Entry(root, width='35')
label1 = Label(root, text='Write The Word You Want To Search For', bg='#2f3136', fg='white',)
e2 = Entry(root, width='35')
label2 = Label(root, text='Write the websites URL', bg='#2f3136', fg='white',)
# Define Functions
def searchgo():
word = e1.get()
URL = e2.get()
page = requests.get(URL).text
print(page.find(word))
temp = Button(root, text='GO', command=searchgo)
# Buttons on screen
label1.grid(row='0', column='0',padx='10')
e1.grid(row='1', column='0', padx='10')
label2.grid(row='0', column='1', padx='10')
e2.grid(row='1', column='1', padx='10')
# use the grid manager to place your button
temp.grid(row='1', column='2', padx='10')
root.mainloop()
I have tried explaining the changes I made with some theory. I hope you understand!
Should the function be defined before you assigne it as Button attribute?
This will raise same exception:
class A:
def __init__(self, something):
self.something = something
a = A(func)
def func():
return
But, this works as expected:
def func():
return
class A:
def __init__(self, something):
self.something = something
a = A(func)

Python : Retrieve ttk.Frame size

I'm tring to get Frame's size - but no luck.
in code below- I got both answers ,"0" ( line marked with ***)
from tkinter import *
from tkinter import ttk
root = Tk()
w = '400'
h = '100'
root.geometry('{}x{}'.format(w, h))
root.configure(bg='lightgreen')
txt = StringVar()
txt.set("Hello")
testframe = ttk.Frame(root)
testframe.grid(row=0, column=1 )
label1 = ttk.Label(testframe, textvariable=txt)
label1.grid(row=0, column=0)
print(testframe["width"], testframe.cget("width")) ***This line
root.mainloop()
The update method needs to be called first, so as to have the widget rendered.
If it is not, then its width is equal to zero.
This is explained in this answer.
Now, the problem with testframe['width'] is that it's only a hint of the actual width of the widget, as explained in this answer.
The following code will ouput 32, as expected.
from tkinter import *
from tkinter import ttk
root = Tk()
w = '400'
h = '100'
root.geometry('{}x{}'.format(w, h))
root.configure(bg='lightgreen')
txt = StringVar()
txt.set("Hello")
testframe = ttk.Frame(root)
testframe.grid(row=0, column=1 )
label1 = ttk.Label(testframe, textvariable=txt)
label1.grid(row=0, column=0)
# Modified lines
testframe.update()
print(testframe.winfo_width())
root.mainloop()
The frame widget will not have a size until it gets mapped on screen. There is a Tk event raised when a widget is mapped so the right solution for this example is to bind the <Map> event for the frame and do the print statement in the event handler function.
def on_frame_mapped(ev):
print(ev.widget.winfo_width())
testframe.bind('<Map>', on_frame_mapped)

Categories

Resources