Python Tkinter StringVar only displaying Py_Var(number) - python

I am using Tkinter in python 3.4 to make a text based game, and I cannot figure out how to get a string from an Entry widget, it just returns Py_Var#, # being a number. I have looked at answers to similar questions, but none of them quite line up with what I need and have. Here's the relevant pieces of code:
from tkinter import *
win = Tk()
win.geometry("787x600")
playername = StringVar()
def SubmitName():
playername.get
#messagebox.showinfo("Success", playername)
print(playername)
frame3 = Frame(win)
frame3.pack()
label1 = Label(frame3, text="You awaken in a room, with no memories of yourself or your past. ")
label2 = Label(frame3, text="First, how about you give yourself a name:")
label1.config(font=("Courier", 11))
label2.config(font=("Courier", 11))
entry1 = Entry(frame3, textvariable=playername)
entry1.config(font=("Courier", 11))
label1.grid(row=0, column=0, columnspan=3)
label2.grid(row=1, column=0)
entry1.grid(row=1, column=1)
bnamesub= Button(frame3, text="Submit", command=lambda: SubmitName())
bnamesub.grid()
win.mainloop()
Also, first time using stackoverflow and its reading weird but w/e.

You have two mistakes in SubmitName().
First, you need to get the text like this:
txt = playername.get()
Then you need to print that txt:
print(txt)
By mistake you printed the StringVar variable itself.

from tkinter import *
import pickle
win = Tk()
win.geometry("787x600")
def SubmitName():
playername = entry1.get()
messagebox.showinfo("Success", playername)
print(playername)
frame3 = Frame(win)
frame3.grid()
label1 = Label(frame3, text="You awaken in a room, with no memories of yourself or your past. ")
label2 = Label(frame3, text="First, how about you give yourself a name:")
label1.config(font=("Courier", 11))
label2.config(font=("Courier", 11))
#name entered is a StringVar, returns as Py_Var7, but I need it to return the name typed into entry1.
entry1 = Entry(frame3)
entry1.config(font=("Courier", 11))
label1.grid(row=0, column=0, columnspan=3)
label2.grid(row=1, column=0)
entry1.grid(row=1, column=1)
bnamesub= Button(frame3, text="Submit", command=lambda: SubmitName())
bnamesub.grid()
What I changed:
-deleted playername = StringVar(). We don't really need it;
-changed inside the function: changed playername.get to playername = entry1.get();
-added frame3.grid() (without geometry managment, widgets cannot be shown on the screen.);
-also, a little edit: in Python, comments are created with # sign. So I changed * to #.

I was happy to find a solution here, but all these answers "as it is" are not working with my setting, python3.8, pycharm 2018.2
So if anyone could answer this, it seems that entry1.get() cannot be used as a string. I first wanted to append it in a list, and I did a more simple version to point out the trouble :
from tkinter import *
import pickle
win = Tk()
win.geometry("300x300")
#playername = StringVar()
def SubmitName():
labell = Label(win, text="Little tryup").grid()
playername = entry1.get()
# result about line 11: 'NoneType' object has no attribute 'get'
labelle = Label(win, text=playername).grid()
# print(txt)
label1 = Label(win, text="Enter a name:").grid()
entry1 = Entry(win).grid()
boutonne = Button(win, text="label-it!", command=lambda: SubmitName())
boutonne.grid()
win.mainloop()

Related

How do I link a function to a button in Tkinter?

So, I made a "love calculator" code and it's working but I want to give it a GUI. I want when I click on the button a number shows up under it. but I can't get it working. I really need help. I'm using python 3.8 with Tkinter. I want when I click on the button. I get an error that l1 is not defined. If you can please help because I'm an absolute beginner to Pyhton.
Here is the code:
import random
import tkinter as tk
from tkinter import *
from random import*
def get_love():
name1 = entry1.get()
name2 = entry2.get()
if (len(name1)) - (len(name2))== 2 or 1 or 0 or -1 or -2 or -3:
l1 = tk.Label(root, text="Here is how much you love eachother: ", (randint(40, 100)), '%')
else:
l2 = tk.Label(root, "Here is how much you love eachother: ", (randint(0, 49)), '%')
root = tk.Tk()
root.title("Love Calculator")
root.minsize(600, 600)
root.configure(background = 'pink')
w = tk.Label(root, bg="pink",font="Times 32 bold", text="Welcome to Love Calculator")
w1 = tk.Label(root, bg="pink",font="Arial 20", text=" ")
w2 = tk.Label(root, bg="pink", fg="white" ,font="Arial 19", text="Write your name here")
entry1 = tk.Entry (root)
w10 = tk.Label(root, bg="pink",font="Arial 20", text=" ")
w3 = tk.Label(root, bg="pink", fg="white" ,font="Arial 19", text="Write your lover's name here")
entry2 = tk.Entry (root)
b = Button(root, text="Click to see how much you love each other", font='Times 20 bold', command=get_love)
w.pack()
w1.pack()
w2.pack()
entry1.pack()
entry2.pack()
w3.pack()
w10.pack()
b.pack()
l1.pack()
l2.pack()
root.mainloop()
Here is a complete guide for you to fix your issue with only a few simple changes.
There are three simple problems with your program:
Problem 1:
You are using or in a wrong way so the condition(if) always returns True and the else block never gets executed, Here:
if (len(name1)) - (len(name2)) == 2 or 1 or 0 or -1 or -2 or -3:
Solution:
You can use range to solve this issue. You have to give it two numbers keeping in mind that the second number won't be included in the range, Like this:
if (len(name1)) - (len(name2)) in range(-3, 3):
Problem 2:
You are doing a mistake in the string concatenation, Here:
text="Here is how much you love each other: ", (randint(40, 100)), '%')
Solution:
There are two possible solutions for this problem:
You can use the plus "+" symbol instead of commas in it, Like this:
text="Here is how much you love each other: " + str(randint(40, 100)) + '%'
But as you can see, then you will also have to convert the random integer(randint(40, 100)) to a string, Like this: str(randint(40, 100))
The easiest solution to this problem is to use a formatted string, Like this:
text=f"Here is how much you love each other: {(randint(40, 100))}%"
Problem 3:
The main reason for getting the error is that you have defined your labels(l1 and l2) inside a function(get_love()), And you are trying to pack() these labels outside the function.
Solution:
The solution is to remove the pack() from outside the function for both labels(l1 and l2), and pack() them inside the function right after defining them. Like This:
def get_love():
name1 = entry1.get()
name2 = entry2.get()
if (len(name1)) - (len(name2)) == 2 or 1 or 0 or -1 or -2 or -3:
l1 = tk.Label(root, text=f"Here is how much you love each other: {(randint(40, 100))}%")
l1.pack()
else:
l2 = tk.Label(root, text=f"Here is how much you love each other: {(randint(0, 49))}%")
l2.pack()
Complete Fixed Code:
Here is the complete fixed code for you:
import tkinter as tk
from random import *
def get_love():
name1 = entry1.get()
name2 = entry2.get()
if (len(name1)) - (len(name2)) in range(-3, 3):
l1 = tk.Label(root, text=f"Here is how much you love each other: {(randint(40, 100))}%")
l1.pack()
else:
l2 = tk.Label(root, text=f"Here is how much you love each other: {(randint(0, 49))}%")
l2.pack()
root = tk.Tk()
root.title("Love Calculator")
root.minsize(600, 600)
root.configure(background='pink')
w = tk.Label(root, bg="pink", font="Times 32 bold", text="Welcome to Love Calculator")
w1 = tk.Label(root, bg="pink", font="Arial 20", text=" ")
w2 = tk.Label(root, bg="pink", fg="white", font="Arial 19", text="Write your name here")
entry1 = tk.Entry(root)
w10 = tk.Label(root, bg="pink", font="Arial 20", text=" ")
w3 = tk.Label(root, bg="pink", fg="white", font="Arial 19", text="Write your lover's name here")
entry2 = tk.Entry(root)
b = tk.Button(root, text="Click to see how much you love each other", font='Times 20 bold', command=get_love)
w.pack()
w1.pack()
w2.pack()
entry1.pack()
entry2.pack()
w3.pack()
w10.pack()
b.pack()
root.mainloop()
I don't believe a lambda is needed here, simply use the if/else to generate the number then format it into the label text.
Python has a nice feature for testing if a number is between two values: if -3 <= x <= 2
Also, avoid pitfalls like using numbers as variables, and importing things multiple times (import tkinter as tk, from tkinter import *)
For labels that are never going to change you don't need to store them to a variable, just pack/grid/place them as-is.
If you just need a space on the window add padding to an existing widget, or use a grid layout.
These are all just suggestions to hopefully help.
I did a bunch of code cleanup here:
from random import randint
import tkinter as tk
def get_love():
name1 = entry1.get()
name2 = entry2.get()
if -3 <= (len(name1) - len(name2)) <= 2:
number = randint(40, 100)
else:
number = randint(0, 49)
display.config(text="Here is how much you love eachother: {}%".format(number))
root = tk.Tk()
root.title("Love Calculator")
root.minsize(600, 600)
root.configure(background = 'pink')
tk.Label(root, bg="pink",font="Times 32 bold",
text="Welcome to Love Calculator").pack(pady = (0, 20))
tk.Label(root, bg="pink", fg="white", font="Arial 19",
text="Write your name here").pack()
entry1 = tk.Entry(root)
entry1.pack()
entry2 = tk.Entry(root)
entry2.pack()
tk.Label(root, bg="pink", fg="white",font="Arial 19",
text="Write your lover's name here").pack(pady = (0, 20))
tk.Button(root, text="Click to see how much you love each other",
font='Times 20 bold', command=get_love).pack(pady = (0, 20))
display = tk.Label(root, bg="pink")
display.pack()
root.mainloop()

I cant generate a random number and print it

I can't generate the number because I get the error NameError: name 'z' is not defined.
import tkinter as tk
from random import randint
def randomize():
z.set ( randint(x.get(),y.get()))
root = tk.Tk()
x = tk.IntVar()
y = tk.IntVar()
text= tk.Label(root, text = "press the button for random number")
enterX = tk.Entry(root)
enterY = tk.Entry(root)
button = tk.Button(root, text = "Press here", command=randomize)
result = tk.Label(root,text="Number is:")
number = tk.Label(root, textvariable=z)
text.pack()
enterX.pack()
enterY.pack()
button.pack()
result.pack()
number.pack()
root.mainloop()
I need help to resolve the error
You have 2 problems here.
One. You are missing z = tk.Intvar() in the global namespace.
Two. You need to assign each entry field one of the IntVar()'s.
Keep in mind that you are not validating the entry fields so if someone types anything other than a whole number you will run into an error.
Take a look at this code.
import tkinter as tk
from random import randint
def randomize():
z.set(randint(x.get(),y.get()))
print(z.get()) # added print statement to verify results.
root = tk.Tk()
x = tk.IntVar()
y = tk.IntVar()
z = tk.IntVar() # added IntVar()
text= tk.Label(root, text = "press the button for random number")
enterX = tk.Entry(root, textvariable=x) # added textvariable
enterY = tk.Entry(root, textvariable=y) # added textvariable
button = tk.Button(root, text = "Press here", command=randomize)
result = tk.Label(root,text="Number is:")
number = tk.Label(root, textvariable=z)
text.pack()
enterX.pack()
enterY.pack()
button.pack()
result.pack()
number.pack()
root.mainloop()

Tkinter questionnaire based on get() method

I am trying to make my first GUI script based on the answers of 2 questions. I'll show an example of the non GUI script
while True:
ammount = input("What is your debt")
if ammount.isdigit() == True:
break
else:
print("Please try typing in a number")
while True:
month = input("In which month did the debt originate?")
if month not in ["January", "February"]:
print("Try again")
else:
break
The point of this script is that it is scalable with all the questions one may add, I want to understand it in the same way in Tkinter. I'll show what I've tried:
from tkinter import *
def click():
while True:
entered_text = text_entry.get()
if entered_text .isdigit() == False:
error = Label(window, text="Try again", bg = "black", fg="red", font="none 11").grid(row = 3, column = 2, sticky= W).pack()
else:
break
return True
window = Tk()
window.title("Tax calculator")
window.configure(background="black")
monto = Label(window, text="¿What is your debt?", bg="black", fg="white", font="none 12 bold")
monto.grid(row = 1, column = 0, sticky= W)
text_entry = Entry(window, width = 20, bg="white")
text_entry.grid(row = 2, column=2, sticky=W)
output = Button(window, text = "Enter", width = 6, command = click)
output.grid(row = 3, column = 0, sticky = W)
The thing is, I can't add a Label() method in the if/else of the click() method, because I would like to ask a new question once the condition is met. I can't also can't get True from click once the condition is met, because the input comes from Button() method. Thanks in advance
You don't actually need any loops here, a simple if statement would be enough to do the trick. Also, there is no need to recreate the label every time, you can just configure() its text. And, note that indexing starts from 0 - so, in your grid, actual first row (and column) needs to be numbered 0, not 1. Besides that, I suggest you get rid of import *, since you don't know what names that imports. It can replace names you imported earlier, and it makes it very difficult to see where names in your program are supposed to come from. You might want to read what PEP8 says about spaces around keyword arguments, as well:
import tkinter as tk
def click():
entered_text = text_entry.get()
if not entered_text.isdigit():
status_label.configure(text='Please try again')
text_entry.delete(0, tk.END)
else:
status_label.configure(text='Your tax is ' + entered_text)
text_entry.delete(0, tk.END)
root = tk.Tk()
root.title('Tax calculator')
root.configure(background='black')
monto = tk.Label(root, text='¿What is your debt?', bg='black', fg='white', font='none 12 bold')
monto.grid(row=0, column=0, padx=10, pady=(10,0))
text_entry = tk.Entry(root, width=20, bg='white')
text_entry.grid(row=1, column=0, pady=(10,0))
status_label = tk.Label(root, text='', bg='black', fg='red', font='none 11')
status_label.grid(row=2, column=0)
button = tk.Button(root, text='Enter', width=17, command=click)
button.grid(row=3, column=0, pady=(0,7))
root.mainloop()
I forgot to mention, if your application gets bigger, you might be better off using a class.

Pass values to python script with Tkinter

So I've written a python script that uses the PIL library to format a png passed to it. I want to make the script more user friendly and after looking around I saw the Tkinter library which seemed perfect. Basically the script has five variables that I need to pass to it for it to run. I'm currently using the raw_input() function to asking the user for the following variables:
path_to_png
title
subtitle
source
sample_size
Once received the script runs and exports the formatted png. I've used Tkinter to build those basic inputs as you can see from the picture below but I don't know how to pass the inputed text values and the file path from the choose png button to their respective variables.
from Tkinter import *
from tkFileDialog import askopenfilename
from tkMessageBox import *
app = Tk()
app.title("Picture Formatting")
app.geometry('500x350+200+200')
#
def callback():
chart_path = askopenfilename()
return
def title_data():
title_data = chart_title
return
errmsg = 'Error!'
browse_botton = Button(app, text="Choose png", width=15, command=callback)
browse_botton.pack(side='top', padx=15, pady=15)
# Get chart data
chart_title = StringVar()
title = Entry(app, textvariable = chart_title)
title.pack(padx=15, pady=15)
chart_subtitle = StringVar()
subtitle = Entry(app, textvariable = chart_subtitle)
subtitle.pack(padx=15, pady=15)
chart_source = StringVar()
source = Entry(app, textvariable = chart_source)
source.pack(padx=15, pady=15)
chart_sample_size = IntVar()
sample_size = Entry(app, textvariable = chart_sample_size)
sample_size.pack(padx=15, pady=15)
submit_button = Button(app, text="Submit", width=15)
submit_button.pack(side='bottom', padx=15, pady=15)
app.mainloop()
I have tried your code, and I added some lines:
from Tkinter import *
from tkFileDialog import askopenfilename
from tkMessageBox import *
app = Tk()
app.title("Picture Formatting")
app.geometry('500x350+200+200')
#
def callback():
global chart_path
chart_path = askopenfilename()
return
def title_data():
title_data = chart_title
return
def calculate():
chart_title = title.get()
chart_subtitle = subtitle.get()
chart_source = source.get()
chart_sample_size = sample_size.get()
print "chart_path : ", chart_path
print "chart_title : ", chart_title
print "chart_subtitle : ", chart_subtitle
print "chart_source : ", chart_source
print "chart_sample_size : ", chart_sample_size
#Call your functions here
return
errmsg = 'Error!'
# Get chart data
chart_path = ''
browse_botton = Button(app, text="Choose png", width=15, command=callback)
browse_botton.pack(side='top', padx=15, pady=15)
chart_title = StringVar()
title = Entry(app, textvariable = chart_title)
title.pack(padx=15, pady=15)
chart_subtitle = StringVar()
subtitle = Entry(app, textvariable = chart_subtitle)
subtitle.pack(padx=15, pady=15)
chart_source = StringVar()
source = Entry(app, textvariable = chart_source)
source.pack(padx=15, pady=15)
chart_sample_size = IntVar()
sample_size = Entry(app, textvariable = chart_sample_size)
sample_size.pack(padx=15, pady=15)
submit_button = Button(app, text="Submit", width=15, command=calculate)
submit_button.pack(side='bottom', padx=15, pady=15)
app.mainloop()
I think the problem you want to ask is how to get the text values in the entry widgets and get the path text from the askopenfilename() function. You can use the method Entry.get() to get the text value in certain entry widget.
And you can just use str = askopenfilename() to get the path's text value. But because this line of code is written in a function, you need to declare that it is a global variable or create a class to contain them, or the interpreter will consider that variable is an local variable and it will not be passed to the function calculate() which I added.
Since you didn't use a class to contain the variables, I also use the variables as global variables. It is not a good design. You can consider to create a class instead.
In order to receive the value from an entry widget, you would want to use the get() function. The get() function will return whatever is in the entry widget. For instance in your case: response = sample_size.get() will set the variable response to 0. See this page for more documentation on the entry widget.
Hope this helped.

Tkinter Entry Box 2 is receiving entry box 1 's characters whiles i type in entrybox 1

When I type in entrybox1 it automatically appears in entrybox2. So is like anything that happens entrybox1 happens to entrybox2.
Below is my code
from Tkinter import*
import random
class Love:
def __init__(self):
window = Tk()
window.title("Love Calculator")
window.geometry("300x180")
frame1 = Frame(window)
frame1.pack()
self.lbl = Label(frame1, text = "Love is Pure",fg="white",bg = "blue")
self.lbl2=Label(frame1, text ="are you meant for one another",fg="White",bg = "red")
self.lbl3=Label(frame1,text="Let FIND OUT!!",fg="white",bg = "green")
self.lbl.pack()
self.lbl2.pack()
self.lbl3.pack()
frame2=Frame(window)
frame2.pack()
label = Label(frame2,text = "Your Name")
label2 = Label(frame2, text= "Your Lovers name")
self.msg = StringVar
entry1 = Entry(frame2, textvariable =self.msg)
self.out = StringVar
entry2 = Entry(frame2, textvariable =self.out)
btCalculate=Button(frame2, text="Calculate", command=self.processButton)
label.grid(row=1,column=1)
label2.grid(row=2,column=1)
entry1.grid(row=1,column=2)
entry2.grid(row=2,column=2)
btCalculate.grid(row=4,column=3,sticky=E)
Both of your Entry widgets are effectively using the same textvariable. This is because you are using StringVar wrong. You aren't creating newStringVars, you're merely referencing the class.
In short, you need to do this:
self.msg = StringVar()
... Rather than this:
self.msg = StringVar
Notice the use of ().

Categories