How to over-write a label - python

I'm trying to write the simplest tkinter window that will show an entry box and a button and the square of whatever number is entered in the entry box.
The code I've written sort of works, except that each new answer is over-written on the previous one so if you have a long number followed by a small number you can see the remains of the old answer underneath the new one.
How could I fix this? Is there a way to cancel the previous label?
from tkinter import *
x=Tk()
x.geometry('900x400')
e=Entry(x)
e.place(relx=0.4, rely=0.2)
def z():
aa=e.get()
aa=int(aa)
aa=aa**2
l=Label(x, text=aa).place(relx=0.4, rely=0.4)
e.delete(0, END)
b=Button(x, text='PRESS', command=z).place(relx=0.6, rely=0.2)
x.mainloop()

Do not create mpnew labels. Create the label once, then use the configure method to change the text.
global l
l = Label(...)
l.pack(...)
...
l.configure(text="some string")
As a suggestion: when learning tkinter, ignore place. It is much less useful than pack and grid.
note: you must create the label and then call pack/place/grid on separate lines because pack/place/grid always returns None.

Related

Hi , How can I change a string number from Entry of tkinter into int number?

Hi i'm a beginner in python and I really got int trouble with some methods, I wanna give some number from Entry of tkinter class and show them with a chart,
but the thing is that I cant get int number:
so the chart wont work [here is the picture of my code , I get some bumber from entry but i cant make them integer number]
1: https://i.stack.imgur.com/2Vuvn.jpg
2: https://i.stack.imgur.com/Pa23V.jpg
Welcome. I'm posting a complete, I think, answer to this question but there are a couple of etiquette things you should know:
Please don't post screenshots of your code. Copy and paste into the editor.
Please post just enough code to show your problem, but which is complete enough that we can just copy it into our own editors / IDEs and run without a lot of modification.
The previous commenters are correct that this question has probably been answered a hundred times, so please try to search through previous answers before posting your question.
Having said that, I have not answered this question before, so here's my rendition. I know you're a beginner so I've tried to keep it as simple as possible, but you're also tackling TKinter so I've not made it overly simplistic.
import tkinter as tk
def main():
global entryVar, lableVar
#create a tkinter window:
rootWin = tk.Tk() #creates a root window
rootWin.title('Entry Test') #shows text on the title bar
rootWin.geometry('500x200') #sets the displayable size of the window
#we'll need these variables and they MUST be tk.StringVar()
entryVar = tk.StringVar() #variable to hold the entry value
lableVar = tk.StringVar() #variable to hold the lable value
#create an entry widget:
entry = tk.Entry(
rootWin,
width = 5,
textvariable = entryVar
)
entry.pack(expand=1)
entry.bind('<Return>', getEntryValue) #bind enter key to widget
entry.bind('<KP_Enter>', getEntryValue, add='+') #bind the other enter key to widget
#create a lable widget
lable = tk.Label(
rootWin,
textvariable = lableVar
)
lable.pack(expand=1)
lableVar.set("This is where the lable is.")
entry.focus_set() #set focus on the entry widget for convenience
rootWin.mainloop()
def getEntryValue(event):
global entryVar, lableVar
x = entryVar.get() #get the value from Entry
x = int(x) #change it to an int
lableVar.set(x) #set the lable variable
entryVar.set("") #clear the entry variable
if __name__ == "__main__":
main()
So, what's going on here is that we make a window in the usual way. I've created both an Entry() widget to get some input, and a Label() widget to show whatever has been input. I've broken the Entry() and Label() declarations up over multiple lines just to make them easier to read.
You can attach variables to many TKinter widgets to that you can .get() and .set() their values more easily, but they almost always need to be TKinter variable types such as StringVar() or IntVar(). I've created two such variables, one for the Entry() widget and another for the Label() widget.
I've also added "bindings" to the Entry() widget to both show how that works and to make data entry a bit more convenient. I don't know if you have a separate number pad on your computer keyboard so I've bound both the main <enter> key as well as the number pad's <enter> key. When you hit either one of those keys, the Entry() widget will call the getEntryValue() function which does the work of getting the value and displaying it on the window.
For convenience, entry.focus_set() immediately puts the focus on the Entry() widget, then the TKinter window enters the .mainloop() to do its stuff.
The getEntryValue() function is called by the events which we set on the Entry() widget. I broke it down into more lines than necessary to illustrate what needs to happen. First we retrieve the value of the Entry() widget through its variable, entryVar. You do that using entryVar's .get() method: x = entryVar.get(). That returns a string value which you will have to convert to an integer using the normal int() function available in Python. For this purposes of this demonstration I've chosen to display that value to a Label() widget which I've placed in the window, so I use the Label() widget's variable lableVar: lableVar.set(x). You don't have to convert the integer back into a string before doing this.
I then clear out the entryVar variable so that there isn't anything left in the Entry() widget to get in the way of our next entry.
I've used entryVar and lableVar as globals just to simplify the example.
And that's how you do it.
I guess the problem is here:
a=str(e3.get())
Try something like this:
a=int(e3.get())
Since what you want is an integer

My Radiobutton is checked on creation

My problem is that when creating a Radiobutton it is automatically checked and i can't uncheck it. I create it inside a frame of x and y dimensions.
I've tried the .deselect() function but it changes nothing
(Python 3.6)
code:
frm = ttk.Frame(root)
frm.place(x=0,y=0,width=1000,height=1000)
Ek = ttk.Radiobutton(frm,text="text")
Ek.place(x=100,y=400)
And photo of it:
photo
First, if we just wanted to modify your code to give us a single unchecked radio button all by itself, this would do the trick.
from tkinter import Tk, IntVar, Radiobutton, mainloop, ttk
root = Tk()
frm = ttk.Frame(root)
frm.place(x = 0, y = 0, width = 1000, height = 1000)
v = IntVar()
Ek = ttk.Radiobutton(frm, text = "text", variable = v, value = 1)
Ek.place(x = 100, y = 100)
mainloop()
Aside from the boilerplate for setup at the beginning and end, the only thing we had to change in your original code was to add the arguments variable = v, value = 1 to the Radiobutton call.
Those extra arguments don't really make sense in isolation, for the same reason that it doesn't generally make sense to have a single radio button. Once we add two of them, we can see what's going on a bit better.
In the documentation #Stack posted (this thing), the first code sample looks like this:
from Tkinter import *
master = Tk()
v = IntVar()
Radiobutton(master, text="One", variable=v, value=1).pack(anchor=W)
Radiobutton(master, text="Two", variable=v, value=2).pack(anchor=W)
mainloop()
If we run that, we get two unchecked radio buttons by default. If we then change the value=1 part to value=0, the first radio button shows up checked, and if we change value=2 to value=0, the second radio button shows up checked. So value=0 seems to give us buttons that are checked by default, but we don't know why yet. Let's experiment a bit more.
If we try to delete pieces in the new sample until we get back to something more closely resembling what you wrote originally, we can sort of see what happened. Deleting the value arguments entirely and running it like this:
Radiobutton(master, text="One", variable=v).pack(anchor=W)
Radiobutton(master, text="Two", variable=v).pack(anchor=W)
leaves us with neither button checked by default, though then further deleting the variable arguments to make the code look like your original call:
Radiobutton(master, text="One").pack(anchor=W)
Radiobutton(master, text="Two").pack(anchor=W)
gives us two buttons that are both checked by default, which gets us back to your original problem.
Basically, we're running into various odd corner cases here because we just started fiddling with code and forgot what a radio button actually represents.
What the concept of a radio button represents in the first place is the value of a variable. Not the entire variable, just one of the things it might be equal to. And the set of radio buttons itself, taken together, gives us a visual representation of a discrete variable: a thing that can be in 1 of N states.
So the API for Radiobuttons, naturally, is asking us for some information like "what python variable do you want us to use to hold these values?" (that's roughly the variable keyword) and "what values do you want us to glue to each of these buttons behind the scenes to distinguish the different states?" (that's the value keyword).
As expected, the code works best in the case above where the values were 1 and 2, because in that case the code is properly reflecting what a radio button actually is, conceptually. When we collide the values or set them to zero or leave them out entirely, things get a bit weird and less predictable because we're then dealing with the implementation details of the tkinter API, rather than with the simple concept of a radio button that the API is meant to implement.
Laptop's about to die, so I'm gonna go ahead and hit send. Hope that wasn't too wordy. Good luck. :)
Radiobuttons need to be associated with one of the special Tkinter variables (StringVar, etc), and are designed to work in groups of two or more. If you don't specify a variable, one will be created for you. The default value of a Radiobutton is the empty string, which is also the default variable will be set to.
Just assign a different value to the declared variable
from tkinter import Tk, IntVar, Radiobutton, mainloop, ttk
root = Tk()
frm = ttk.Frame(root)
frm.place(x=0,y=0,width=100,height=400)
language=StringVar(value='portuguese')
Ek = ttk.Radiobutton(frm,variable="language",text="spanish",value="spanish")
Ek.place(x=10,y=50)
Ek = ttk.Radiobutton(frm,variable="language",text="english",value="english")
Ek.place(x=10,y=85)
mainloop()

Checking if the user presses 'Return' while selected in an Entry box Tkinter

I'm using Tkinter to create a GUI for a simple geometry calculator I'm creating.
Basically, what I have is an Entry box. What I want is for the program/GUI/system to detect when the user of the program hits the 'Enter' or 'return' key WHILE they are in the Entry box. When this is detected, I want the contents of the Entry box to be appended to a list I have defined earlier. I also want a simple label to be created on the GUI that displays the contents of the list (including the appended item(s)). Note that the list begins with nothing in it.
Here is my code so far:
from tkinter import *
#Window setup(ignore this)
app = Tk()
app.title('Geometry Calculator')
app.geometry('384x192+491+216')
app.iconbitmap('Geo.ico')
app.minsize(width=256, height=96)
app.maxsize(width=384, height=192)
app.configure(bg='WhiteSmoke')
#This is the emtry list...
PointList = []
#Here is where I define the variable that I will be appending to the list (which is the object of the Entry box below)
StrPoint = StringVar()
def list_add(event):
#I don't really know how the bind-checking works and how I would implement it; I want to check if the user hits enter while in the Entry box here
if event.char == '':
PointList.append(StrPoint)
e1 = Entry(textvariable=StrPoint).grid(row=0, column=0)
app.bind('<Return>', list_add)
mainloop()
I don't really know the proper way to check for 'Return' and then use it in an if statement.
I hope you understand what I'm trying to get help with, and I've looked all around for an explanation that I could understand with no success.
Instead of binding with the app just bind it with the Entry widget object,i.e,e1
from tkinter import *
#Window setup(ignore this)
app = Tk()
app.title('Geometry Calculator')
app.geometry('384x192+491+216')
app.iconbitmap('Geo.ico')
app.minsize(width=256, height=96)
app.maxsize(width=384, height=192)
app.configure(bg='WhiteSmoke')
#This is the emtry list...
PointList = []
#Here is where I define the variable that I will be appending to the list (which is the object of the Entry box below)
StrPoint = StringVar()
def list_add(event):
print ("hello")
#I don't really know how the bind-checking works and how I would implement it; I want to check if the user hits enter while in the Entry box here
if event.char == '':
PointList.append(StrPoint)
e1 = Entry(textvariable=StrPoint)
e1.grid(row=0, column=0)#use grid in next line,else it would return None
e1.bind('<Return>', list_add)# bind Entry
mainloop()
The solution is to set the binding on the widget itself. That way, the binding will only apply while focus is on that widget. And since you're binding on a specific key, you don't need to check for the value later. You know the user pressed return, because that's the only thing that will cause the binding to fire.
...
e1.bind('<Return>', list_add)
...
You have another problem in that your list_add function needs to call the get method of the variable rather than accessing the variable directly. However, since you aren't using any of the special features of a StringVar, you really don't need it -- it's just one more thing you have to manage.
Here's how to do it without the StringVar:
def list_add(event):
PointLit.append(e1.get())
...
e1 = Entry(app)
e1.grid(row=0, column=0)
e1.bind('<Return>', list_add)
Note that you need to create the widget and lay out the widget in two steps. Doing it the way you did it (e1=Entry(...).grid(...) will cause e1 to be None since that is what .grid(...) returns.

Making Entry widget "disabled" like in windows calc

I've got a problem with Entry widget while making a copy of Windows Calc.
I have made buttons like in windows calc and I also bind the keyboard 1234567890 + - / * % buttons, to make the same things as the calc buttons.
The mainly problem was that I wanted the Entry to store only numbers and let user input only numbers... but after searching many topics about validatecommand and also looking at windows calc I decided that validatecommand isn't the thing I need - I don't know how to make it validate every character the user inputs to the entry box and after making the keyboard binds, when I am in entrybox and press "1" to write the number it does it two times, because the keyboard event binding inserts the "1" to the entry box too.
So, the thing I want to make is to make entry widget work like the Windows Calc.exe entry box.
The windows calc entry box doesn't let you insert any other character then numbers and also doesn't let you to put your cursor into the entry box...,
it looks like this:
-entrybox is disabled BUT it looks like ENABLED
-numbers and operations can be made by calc buttons or by keyboard buttons
I tried getting this effect by disabling the entry widget at start, and making all buttons functions like that:
-enable the entry widget
-insert the number (the widget must be in enabled? or normal? (don't remember the name) state to let you insert something to it)
-disable the entry widget
It works like I want... but it doesn't look like I want it to look. Is there any possibility to change Entry widget disabled bg color to normal?
Or maybe is there another way to make such entry box? :S
The way to do it is with the validatecommand and validate options of the entry widget. This scenario is precisely what those features are for.
You say you "don't know how to make it validate every character the user inputs to the entry box". If you set the validate attribute to "key", that will cause your validate command to be called on every keypress.
Unfortunately, this is a somewhat under-documented feature of Tkinter, though it's documented quite well for Tk. Here's a working example which performs some very rudimentary checks:
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
# define a command to be called by the validation code. %P
# represents the value of the entry widget if the edit is
# allowed. We want that passed in to our validation comman so
# we can validate it. For more information see
# http://tcl.tk/man/tcl8.5/TkCmd/entry.htm#M7
vcmd = (self.register(self._validate), '%P')
e = tk.Entry(self, validate="key", validatecommand=vcmd)
e.pack()
def _validate(self, P):
# accept the empty string, "." or "-." (to make it possible to
# enter something like "-.1"), or any string that can be
# converted to a floating point number.
try:
if P in (".", "-", "-.", ""):
return True
n = float(P)
return True
except:
self.bell()
return False
app=SampleApp()
app.mainloop()
If you search this site for [tkinter] validatecommand you'll find many other examples.

Tkinter - Why is my background/frame not re-painting?

I am not sure if I am on the right track here-- but I started GUI programming with Python.
I have all of my buttons and entries worked out. The main problem I am having is with the method that rolls my die and places the result.
def roll(self):
self.die = Die(int(self.sides.get())) # gets from label
t = self.die.roll()
t += int(self.mod.get()) # gets from label
self.result = Label(self.root, text=t).grid(row=2, column=1, sticky=W)
Is my problem the fact that I am re-instantiating a Label over the old one? Shouldn't the old Label's text be destroyed and the frame should only show the new label in its place?
It seems to me that you're not using objects at their best values. You should modify you code in this way:
each time you need a new roll, you instantiate a new Die. Why not keeping the same instance?
each time you want to display the roll, you instantiate a new Label. Maybe you're not aware of this, but you can update the label text (and any Tkinter widget), using its configure() method. This would mean that you need to grid the instance only the first time.
By the way, .grid returns None. If you want to keep reference of the result label, you have to use two lines for Label instantiation:
self.result = Label(self.root, text=t) # first creating instance...
self.result.grid(row=2, colum=1, sticky=W) # ... and placing it in self.root
Try to update your code like this. You will certainly feel the need to move some of this code to the __init__() function of self, so write it in your question as well.

Categories

Resources