I'm working on a simple registration phase for a password scheme, but I can't seem to get the value in the combobox as an integer as it keeps giving ValueError: invalid literal for int() with base 10: ''. I've tried many methods but they don't seem to work. Additionally, I want to store the data in the entry and comboboxes for my next window, but it keeps registering as ValueError: '' is not in list.
The code:
import tkinter as tk
from tkinter import *
import random
from tkinter import messagebox
from tkinter import ttk
from tkinter.ttk import Combobox
root = tk.Tk()
root.geometry("375x130")
var = tk.StringVar()
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lbl = tk.Label(root, text = "Your password must have 7 to 15 characters with \nat least 1 number, 1 uppercase and 1 lowercase letter. ")
lbl1 = tk.Label(root, text = "Choose your password: ")
lbl2 = tk.Label(root, text = "n")
lbl3 = tk.Label(root, text = "y")
entry1 = tk.Entry(root)
combo1 = Combobox(root, values = data, state = "readonly")
combo2 = Combobox(root, values = data, state = "readonly")
lbl.place(x = 10, y = 0)
lbl1.place(x = 10, y = 35)
lbl2.place(x = 10, y = 60)
lbl3.place(x = 10, y = 85)
entry1.place(x = 155, y = 35)
combo1.place(x = 25, y = 60)
combo2.place(x = 25, y = 85)
pw = entry1.get()
n = combo1.get()
y = combo2.get()
root.title('Registration')
done_button = tk.Button(root, text = "Done", command = root.destroy, width = 5)
done_button.place(x = 205, y = 80)
root.mainloop()
password = str(pw)
n = int(data.index(n)) - 1
y = int(data.index(y)) - 1
When the following lines are executed:
pw = entry1.get()
n = combo1.get()
y = combo2.get()
The entry box and the two comboboxes are just created, so nothing is input in the entry box and nothing is selected in the two comboboxes.
You need to do it inside a function triggered by the "Done" button:
...
# function called by "Done" button
def done():
pw = entry1.get()
n = int(combo1.get()) # convert selection to integer
y = int(combo2.get()) # convert selection to integer
print(f"{pw=}, {n=}, {y=}")
n = data.index(n) - 1
y = data.index(y) - 1
print(f"{n=}, {y=}")
root.destroy()
root.title('Registration')
done_button = tk.Button(root, text = "Done", command = done, width = 5)
done_button.place(x = 205, y = 80)
root.mainloop()
Output in console:
pw='hello', n=4, y=9
n=2, y=7
There are a couple of issues with your code:
Firstly, you need to bind the combobox change events with a function of some sort
The combobox returns a string of the number selected - which needs conversion
I am not sure what you aimed to do with n and y - but I kept the formula you used.
Fix these, and the combobox issues resolve.
See code below:
Code:
import tkinter as tk
from tkinter import *
import random
from tkinter import messagebox
from tkinter import ttk
from tkinter.ttk import Combobox
def combo_n_changed(event):
n = combo1.get()
n = int(data.index(int(n))) - 1
print("n=",n)
def combo_y_changed(event):
y = combo2.get()
y = int(data.index(int(y))) - 1
print("y=",y)
root = tk.Tk()
root.geometry("375x130")
var = tk.StringVar()
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lbl = tk.Label(root, text = "Your password must have 7 to 15 characters with \nat least 1 number, 1 uppercase and 1 lowercase letter. ")
lbl1 = tk.Label(root, text = "Choose your password: ")
lbl2 = tk.Label(root, text = "n")
lbl3 = tk.Label(root, text = "y")
entry1 = tk.Entry(root)
combo1 = Combobox(root, values = data, state = "readonly")
combo2 = Combobox(root, values = data, state = "readonly")
lbl.place(x = 10, y = 0)
lbl1.place(x = 10, y = 35)
lbl2.place(x = 10, y = 60)
lbl3.place(x = 10, y = 85)
entry1.place(x = 155, y = 35)
combo1.place(x = 25, y = 60)
combo2.place(x = 25, y = 85)
pw = entry1.get()
combo1.bind('<<ComboboxSelected>>', combo_n_changed)
combo2.bind('<<ComboboxSelected>>', combo_y_changed)
root.title('Registration')
done_button = tk.Button(root, text = "Done", command = root.destroy, width = 5)
done_button.place(x = 205, y = 80)
root.mainloop()
I entered the information as per the image below:
Output:
n= 1
y= 2
Related
So simply, I was trying to create a code that when you press certain buttons, it writes out whatever you put into the Tk input. I was trying to make a hotkey with alt and another letter but whenever I use alt or ctrl, the function does not work and opens up random applications on my screen. everything works fine with keys like shift + a for example, but outputs it all in capitals because of the use of shift. The part where I write the Hotkeys is where all the Hotkey variables are
from tkinter import *
import keyboard, pyautogui
import os
import sys
import tkinter.messagebox
import time
root = Tk()
root.resizable(False, False)
root.iconbitmap('Logo.ico')
root.title(" ")
root.geometry("170x300")
Canvas(root, width=170, height=300)
hotkey1 = "alt + q"
hotkey2 = "alt + w"
hotkey3 = "alt + e"
hotkey4 = "alt + r"
Label(root, text="MacMaker").place(x = 50)
Label(root, text="Type in Macros below:").place(x = 27, y = 21)
Label(root, text="F4:").place(x = 5, y = 48)
Label(root, text="F7:").place(x = 5, y = 78)
Label(root, text="F8:").place(x = 5, y = 108)
Label(root, text="F9:").place(x = 5, y = 138)
thing1 = Entry(width=20)
thing1.place(x = 35, y = 50)
thing2 = Entry(width=20)
thing2.place(x = 35, y = 80)
thing3 = Entry(width=20)
thing3.place(x = 35, y = 110)
thing4 = Entry(width=20)
thing4.place(x = 35, y = 140)
def my_mainloop():
macro1 = thing1.get()
macro2 = thing2.get()
macro3 = thing3.get()
macro4 = thing4.get()
if keyboard.is_pressed(hotkey1):
pyautogui.typewrite(macro1)
elif keyboard.is_pressed(hotkey2):
pyautogui.typewrite(macro2)
elif keyboard.is_pressed(hotkey3):
pyautogui.typewrite(macro3)
elif keyboard.is_pressed(hotkey4):
pyautogui.typewrite(macro4)
root.after(1, my_mainloop)
root.after(1, my_mainloop)
root.mainloop()
From the docs, it looks like it should be:
hotkey1 = "alt+q"
hotkey2 = "alt+w"
hotkey3 = "alt+e"
hotkey4 = "alt+r"
without the spaces
my code:
import tkinter as tk
from tkinter import *
truth = ""
us = ""
uss = ""
root = Tk()
s = Label(root, text = ".")
s.grid(row = 1, column = 1)
wel = Label(root, text = "whats your email")
wel.grid(row = 1, column = 5)
inp = Entry(root).get()
inp.grid(row = 3, column = 5)
def callback():
us = inp[:inp.index("#")]
uss = inp[inp.index("#")+1:]
truth =us, " is username, and ", uss,"is domain"
print(truth)
sub = Button(root, text = "submit", command = callback)
sub.grid(row = 5, column = 5)
final = Label(root, textvariable = truth)
final.grid(row = 5, column = 6)
root.mainloop()
Then I get an error message:
'str' object has no attribute 'grid'
How do I use grid system on entry widget affected by .get()?
I've a Tkinter-programm where I regularly (10 times/second) update Labels with certain sensor-values.
The problem is that they are arranged with .grid right next to each other and when a value gets/loses a place (e.g. 10 -> 9, 60 -> 150, you see the number needs extra space) the label jumps back and forth (because the number gains or loses a space and therefore .grid responds by adjusting the Label).
How can i avoid that? Do I need to change Text & Numbers to a certain font or is there a function that fixes the Labels place? I'd be happy about useful answers.
Here's a code example (please notice how the labels are adjusting cause that's the problem):
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import random
i = 0
x = 0
def GetValue():
x = random.randint(0,10000)
time.sleep(0.1)
return x
def UebergabeTkinter():
while 1:
CompleteValue = GetValue()
Variable1.set(CompleteValue)
Variable2.set(CompleteValue)
Variable3.set(CompleteValue)
Variable4.set(CompleteValue)
root.update()
def Exit():
root.destroy()
return
try:
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1, sticky = W+E+N+S)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3, sticky = W+E+N+S)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5, sticky = W+E+N+S)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7, sticky = W+E+N+S)
UebergabeTkinter()
root.mainloop()
except KeyboardInterrupt:
print "Hallo"
You can give labels a fixed width:
Label1 = Label(root, textvariable=Variable1, width=4)
Just make sure they are large enough to fit every number that could be put in, since of course next no the label not shrinking when the number is shorter, this also means that they will not grow to fit larger numbers.
I am new in creating GUI. I am doing it in Python with Tkinter. In my program I calculate following characteristics
def my_myfunction():
my code ...
print("Centroid:", centroid_x, centroid_y)
print("Area:", area)
print("Angle:", angle)
I would like to ask for any help/tips how to display those values in GUI window or how to save them in .txt file so that I can call them in my GUI
Thanks in advance
Tkinter is easy and an easy way to do a GUI, but sometimes it can be frustrating. But you should have read the docs before.
However, you can do in this way.
from tkinter import *
yourData = "My text here"
root = Tk()
frame = Frame(root, width=100, height=100)
frame.pack()
lab = Label(frame,text=yourData)
lab.pack()
root.mainloop()
There are several ways to display the results of any operation in tkiner.
You can use Label, Entry, Text, or even pop up messages boxes. There are some other options but these will probably be what you are looking for.
Take a look at the below example.
I have a simple adding program that will take 2 numbers and add them together. It will display the results in each kind of field you can use as an output in tkinter.
import tkinter as tk
from tkinter import messagebox
class App(tk.Frame):
def __init__(self, master):
self.master = master
lbl1 = tk.Label(self.master, text = "Enter 2 numbers to be added \ntogether and click submit")
lbl1.grid(row = 0, column = 0, columnspan = 3)
self.entry1 = tk.Entry(self.master, width = 5)
self.entry1.grid(row = 1, column = 0)
self.lbl2 = tk.Label(self.master, text = "+")
self.lbl2.grid(row = 1, column = 1)
self.entry2 = tk.Entry(self.master, width = 5)
self.entry2.grid(row = 1, column = 2)
btn1 = tk.Button(self.master, text = "Submit", command = self.add_numbers)
btn1.grid(row = 2, column = 1)
self.lbl3 = tk.Label(self.master, text = "Sum = ")
self.lbl3.grid(row = 3, column = 1)
self.entry3 = tk.Entry(self.master, width = 10)
self.entry3.grid(row = 4, column = 1)
self.text1 = tk.Text(self.master, height = 1, width = 10)
self.text1.grid(row = 5, column = 1)
def add_numbers(self):
x = self.entry1.get()
y = self.entry2.get()
if x != "" and y != "":
sumxy = int(x) + int(y)
self.lbl3.config(text = "Sum = {}".format(sumxy))
self.entry3.delete(0, "end")
self.entry3.insert(0, sumxy)
self.text1.delete(1.0, "end")
self.text1.insert(1.0, sumxy)
messagebox.showinfo("Sum of {} and {}".format(x,y),
"Sum of {} and {} = {}".format(x, y, sumxy))
if __name__ == "__main__":
root = tk.Tk()
myapp = App(root)
root.mainloop()
I am currently using Canopy to run my code. I was trying to fetch some integer data from the entry box in my GUI according to the number that I give in the for loop and print it. It is not working.
Here is the error:
Traceback (most recent call last):
File "C:\Program Files\Enthought\Canopy\App\appdata\canopy-1.5.5.3123.win- x86_64\lib\lib-tk\Tkinter.py", line 1532, in __call__
return self.func(*args)
File "C:\Users\SIMULATOR\Desktop\python\life cycle graph\try4.py", line 24, in const
z=int(s)
ValueError: invalid literal for int() with base 10: ''
My code is:
from Tkinter import *
root = Tk()
root.geometry('1000x600+400+400')
def const():
const_entries = []
for i in range(0, 4):
en = Entry(root)
en.pack()
en.place(x=50, y = 200 + 25*i)
s = en.get()
z = int(s)
const_entries.append(z)
j = i + 1
label = Label(root, text="Alternative %r"%j)
label.pack()
label.place(x = 200, y = 200 + 25*i)
print const_entries
button1 = Button(root, text="Construction cost", command = const).grid(row = 15, column = 0)
root.mainloop()
Clarification: Assuming that s isn't empty (en.get() returns some number).
Check out this example:
int('55.500000')
It gets you a: ValueError: invalid literal for int() with base 10: '55.500000'
And:
float('55.500000')
Gets you: 55.5
So just cast to float instead of int.
When literal s couldn't be converted to int, int(s) failed.
try:
z = int(s)
except ValueError:
z = 0
When you call en.get() at this point, it will return '' and then int('') will raise an error. Maybe before getting the integer you want to set an integer as string to the entry.
When you write button1 = Button(root, text="Construction cost", command = const).grid(row = 15, column = 0) button1 will not be a Button instance; button1 should be the result of the grid function.
As already stated in the other answers, your code is failing, because your entries are empty when you call the const method.
Assuming that you want to enter something in your entry boxes and then print the alternatives I guess code like this would do the job:
from Tkinter import *
root=Tk()
root.geometry('1000x600+400+400')
def const():
const_entries = []
for i in range(4):
s = entryArray[i].get()
z = int(s)
const_entries.append(z)
print const_entries
button1 = Button(root, text="Construction cost", command = const).grid(row = 15, column = 0)
entryArray = []
for i in range(0,4):
entryArray.append(Entry(root))
#Insert default value 0
entryArray[i].insert(0, 0)
entryArray[i].pack()
entryArray[i].place(x = 50, y = 200 + 25*i)
label = Label(root, text="Alternative %d"%(i+1))
label.pack()
label.place(x = 200, y = 200 + 25*i)
root.mainloop()
This way you create the entries at startup and you give the user the time to enter something. When you press the Construction cost button the const function is called which will read the content of your entries and print them out.
Update
If you then want the user to enter the number of entries I'd suggest using a class and defining two buttons:
One for creating the entries after the user has entered the number
One for processing the number the user enters in the created entries
from Tkinter import *
root=Tk()
root.geometry('1000x600+400+400')
class MainWindow():
def __init__(self):
Label(root, text='Number of Entries').grid(row = 15, column = 0)
self.numEntry = Entry(root)
self.numEntry.grid(row = 15, column = 1)
self.numEntry.insert(0, 0)
Button(root, text="Build entries", command = self.buildEntries).grid(row = 15, column = 3)
Button(root, text = "Construction cost", command = self.const).grid(row = 18, column = 0)
def buildEntries(self):
self.entryArray = []
numEntries = int(self.numEntry.get())
for i in range(numEntries):
self.entryArray.append(Entry(root))
#Insert default value 0
self.entryArray[i].insert(0, 0)
self.entryArray[i].pack()
self.entryArray[i].place(x = 50, y = 200 + 25*i)
label=Label(root, text="Alternative %d"%(i+1))
label.pack()
label.place(x = 200, y = 200 + 25*i)
def const(self):
const_entries = []
numVal = len(self.entryArray)
for i in range(numVal):
s = self.entryArray[i].get()
z = int(s)
const_entries.append(z)
print 'Const Entries:', const_entries
m = MainWindow()
root.mainloop()