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.
Related
I am trying to make a program which calculates 3-4 values using some user inputted values
I have tried making a function which saves the entries into variables, and making the variables global but that didn't work
from tkinter import *
from math import *
root = Tk()
label1 = Label(root, text = "Enter value for length ")
label1.grid(columnspan = 2, sticky = "W")
length = Entry(root)
length.grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume ")
label2.grid(columnspan = 2, sticky = "W")
volume = Entry(root)
volume.grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder ")
label3.grid(columnspan = 2, sticky = "W")
thickness = Entry(root)
thickness.grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature ")
label4.grid(columnspan = 2, sticky = "W")
st_T = Entry(root)
st_T.grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature ")
label5.grid(columnspan = 2, sticky = "W")
end_T = Entry(root)
end_T.grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
Button(root, text = "Submit", command = save).grid(row = 6, column = 0)
root.mainloop()
I know the current code isn't very pretty and is very inefficient but the error keeps saying that v is not defined
You might consider declaring a variable, or a an instance of a context object (that you will define) at global scope to store your user inputs.
Then you will be able to read the user inputs later in another function.
Do not forget to use the keyword 'global' before modifying the global object in a different scope (like in a function). Have a look here : https://www.geeksforgeeks.org/global-keyword-in-python/
By example you could declare your global object/variable/whatever you need, along with your root Tkinter object.
This question already has answers here:
Why is my Button's command executed immediately when I create the Button, and not when I click it? [duplicate]
(5 answers)
Closed 3 years ago.
I am trying to write a program using a tkinter GUI to calculate a few things. My get() function isn't working and I'm not sure why
from tkinter import *
from math import *
root = Tk()
v = 0
l = 0
w = 0
t1 = 0
t0 = 0
label1 = Label(root, text = "Enter value for length (mm) :").grid(columnspan = 2, sticky = "E")
length = Entry(root).grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume (mm^2) :").grid(columnspan = 2, sticky = "E")
volume = Entry(root).grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder (mm) :").grid(columnspan = 2, sticky = "E")
thickness = Entry(root).grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature (K) :").grid(columnspan = 2, sticky = "E")
st_T = Entry(root).grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature (K) :").grid(columnspan = 2, sticky = "E")
end_T = Entry(root).grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
answer = StringVar()
labelans = Label(root, textvariable = answer).grid(columnspan = 3,)
answer.set("Answer = ")
def area_circle():
global answer
answer = v / l
print(answer)
Button(root, text = "Submit", command = save()).grid(row = 6, column = 0)
root.mainloop()
Obviously there are variables i'm not using yet but im trying to get the first part right first.
For v the error displayed is:
Message='NoneType' object has no attribute 'get'
The Grid geometry manager puts the widgets in a 2-dimensional table.
The master widget is split into a number of rows and columns, and each
“cell” in the resulting table can hold a widget.
What is important Grid() is returning NoneValue
if you are doing like:
length = Entry(root).grid(row = 0, column = 2)
in your variable length you will have NoneValue
you should do it like :
length = Entry(root)
length.grid(row = 0, column = 2)
your code:
label1 = Label(root, text = "Enter value for length (mm) :")
label1.grid(columnspan = 2, sticky = "E")
length = Entry(root)
length.grid(row = 0, column = 2)
label2 = Label(root, text = "Enter value for volume (mm^2) :")
label2.grid(columnspan = 2, sticky = "E")
volume = Entry(root)
volume.grid(row = 1, column = 2)
label3 = Label(root, text = "Enter value for the thickness of the cylinder (mm) :")
label3.grid(columnspan = 2, sticky = "E")
thickness = Entry(root)
thickness.grid(row = 2, column = 2)
label4 = Label(root, text = "Enter value for starting temperature (K) :")
label4.grid(columnspan = 2, sticky = "E")
st_T = Entry(root)
st_T.grid(row = 3, column = 2)
label5 = Label(root, text = "Enter value for finishing temperature (K) :")
label5.grid(columnspan = 2, sticky = "E")
end_T = Entry(root)
end_T.grid(row = 4, column = 2)
def save():
v = volume.get()
l = length.get()
w = thickness.get()
t0 = st_T.get()
t1 = end_T.get()
global values
values = [v, l, w, t1, t0]
answer = StringVar()
labelans = Label(root, textvariable = answer).grid(columnspan = 3,)
answer.set("Answer = ")
def area_circle():
global answer
answer = v / l
print(answer)
Button(root, text = "Submit", command = save()).grid(row = 6, column = 0)
root.mainloop()
output:
The command argument should be a callback, not the actual call:
Button(root, text="Submit", command=save).grid(row=6, column=0)
I was really curious why I cannot get my add_button to work,
as the window fails to come up when creating it.
from tkinter import *
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = 0
self.input2 = 0
input1 = Entry(master)
input2 = Entry(master)
input1.grid(row = 0, column = 1)
input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_buton = Button(master, text = "Add", command = self.add())
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
return self.input1.get() + self.input2.get()
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
#-------------------------------------------------
Welcome to Stack!
I've looked through you code I've been able to do what you are asking. There were a few errors within your code:
a) you had self.add_buton and self.add_button which caused an error.
b) self.input1 = 0 and self.input2 = 0 are not required.
c) You were calling self.add() as the command and you should be calling self.add. When calling it as a command you do not need ()
d)input1 = Entry(master) should be self.input1 = tk.Entry(master)
e) You should convert your input values into int or float as otherwise it will just one value onto the end of the other. (Eg, 1 + 5 = 15 whereas int(1) + int(5) = 6
Here is your code with the entry boxes working as they should. I have import tkinter as tk hence why it is tk.Entry
from tkinter import *
import tkinter as tk
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input2 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input1.grid(row = 0, column = 1)
self.input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_button = tk.Button(master, text = "Add", command = self.add)
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
val = self.input1.get()
print(val)
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
This should now work how you wanted it too. The variables within the entry can be changed to suit. You were correct in calling the value of the entry with self.input1.get().
Hope this has helped.
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 working on this short code that compares the single characters of two strings. After the first running, when I change the strings in the entryBoxes,I would like to replace the label created before, instead of creating a new one. I have already tried with StringVar() but it seems not working. (If it can be useful I'm using Python 2.7.6). Could you please give me a hint?
from Tkinter import *
app = Tk()
app.geometry('450x300')
labelTF = Label(app, text="Insert sequence of TF").pack()
eTF = Entry(app, width=50)
eTF.pack()
eTF.focus_set()
labelSpazio = Label(app, text="\n").pack()
labelResultedSequence = Label(app, text="Insert sequence of ResultedSequence").pack()
eResultedSequence = Entry(app, width=50)
eResultedSequence.pack()
eResultedSequence.focus_set()
def prova():
count = 0
uno = eTF.get().lower()
due = eResultedSequence.get().lower()
if len(uno)==len(due):
for i in range(0,len(uno)):
if uno[i] == due[i]:
if uno[i] in ("a", "c","g","t"):
count = count + 1
if uno[i] == "r" and due[i] in ("a", "g"):
count = count + 1
if uno[i] == "y" and due[i] in ("t", "c"):
count = count + 1
percentage = int(float(count)/float(len(uno))*100)
labelSpazio = Label(app, text="\n").pack()
mlabel3=Label(app,text= "The final similarity percentage is: "+(str(percentage) + " %")).pack()
if len(uno)!=len(due):
mlabel2 = Label(app,text="The length of the sequences should be the same").pack()
b = Button(app, text="get", width=10, command=prova)
b.pack()
mainloop()
Create the labels only once outside of the for loop and use a StringVar to modify its value. It would look like this:
# initialization
app = Tk()
label3text = StringVar()
mlabel3 = Label(app, textvariable=label3text, width=100)
mlabel3.pack()
Then in the for loop inside your function:
label3text.set("The final similarity percentage is: "+(str(percentage) + " %"))