I need to fetch one number from a column
cursor.execute('''SELECT vacas FROM animales''')
cantidad1 = cursor.fetchone()
Then I need this number to be shown in a Tkinter Label:
cantidad = Label (ventana, textvariable=cantidad1).grid(row=1, column=3)
And I have a refresh button in order to update the data.
ref = Button (ventana, text="Refresh", command=update )
The problem is that the Label is always blank, even when I press button and call Update():
Here is the complete code:
cantidad1 = 0
ventana = Tk()
cursor = db.cursor()
def update():
cursor.execute('''SELECT vacas FROM animales''')
cantidad1 = cursor.fetchone()
print (cantidad1[0]) #The number shown in command is right, but blank in tkinter.
ref = Button (ventana, text="Refresh", command=update )
ref.grid(row=3, column=2)
cantidad = Label (ventana, textvariable=cantidad1).grid(row=1, column=3)
ventana.mainloop()
https://imgur.com/AvsNAuL "Screenshot tkinter blank"
Using textvariable in Tkinter can be handy, but it requires thinking a bit in Tcl/Tk style instead of Python style. You may want to read up on it I'm not sure where the best docs are, but Entry and The Variable Classes in the old book are probably a good place to start.
Anyway, a textvariable binding has to refer to a Tcl variable, like a StringVar. Somewhere before creating that Label with textvariable=cantidad1 you need to do something like this:
cantidad1 = StringVar('0')
And then, instead of this:
cantidad1 = cursor.fetchone()
… you have to do this:
cantidad1.set(cursor.fetchone())
What you're doing is changing the name cantidad1 to refer to the new result, but what you need to do is leave it referring to the StringVar and change the value of the StringVar, so Tk can see it and update the label.
While we're at it, I think you actually want something like cursor.fetchone()[0]; otherwise you're trying to use a row (probably a list or other sequence, not a string).
Finally, you could use an IntVar here. That would allow you to initialize it to 0 instead of '0', but then of course you have to set it to int(spam) instead of just spam, and you may need some error handling to deal with what happens if the database returns Null.
If all of this is Greek to you (or, worse, Tcl), the other option is to just not use Tk variables:
cantidad = Label(ventana, text='0').grid(row=1, column=3)
Notice that the difference here is that I set the initial text, rather than setting a textvariable.
So now, every time you fetch new data, you'll have to manually update (re-config) the label's text, like this:
cantidad1 = ... # code that just gets a normal Python string
cantidad.config(text=cantidad1)
This is much less idiomatic Tk code, and arguably less idiomatic Tkinter code—but it's a lot more Pythonic, so it may be easier for you to read/debug/write. (Notice that the first line is exactly what you instinctively wrote, which was wrong with your original design, hence your question, but would be right with the explicit-update design.)
—-
There are other problems in the code that I haven’t fixed. For example, the grid method on widgets doesn’t return the widget, it returns None. You’re doing it right for ref, but not for cantidad. Your original code never actually referred to cantidad, so that wasn't a problem, but if you, e.g., switch to using manual updates instead of automatic variables, you're going to get a confusing exception about calling configure on None.
Related
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
I have a scale and an input field which both control the same variable to give the user choice of which one they'd like to use. I've coded it a bit like this:
def scale_has_moved(value):
entry_field.delete(0, END)
entry_field.insert(0, str(float(value)))
# Other functions I want the code to do
def entry_field_has_been_written(*args):
value = float( entry_field.get() )
scale.set(value)
This works, when I move the scale the entry_field gets written in and vice versa, and the other functions I want the code to do all happen. The obvious problem is the functions call each other in a loop, so moving the scale calls scale_has_moved() which calls the additional functions within and writes in the entry field, then because the entry field has been written in entry_field_has_been_written() gets called which in turn calls scale_has_moved() again, it doesn't go in an endless loop but it does everything at least twice everytime which affects performance.
Any clue how I'd fix this? Thank you
If you use the same variable for both widgets, they will automatically stay in sync. You don't need your two functions at all. The following code illustrates the technique.
import tkinter as tk
root = tk.Tk()
var = tk.IntVar(value=0)
scale = tk.Scale(root, variable=var, orient="horizontal")
entry = tk.Entry(root, textvariable=var)
scale.pack(side="top", fill="x")
entry.pack(side="top", fill="x")
root.mainloop()
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()
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.
I have a program where I need to take a selection from Tkinter.Listbox and an entry field and do something with that data. However, if I highlight any text within the entry field (i.e., to delete previous entry), the Listbox selection is cleared. How can I overcome it so that the Listbox selection persists?
import Tkinter as tk
master = tk.Tk()
listbox = tk.Listbox(master)
listbox.grid(row=0, column=0)
items = ['a', 'b', 'c']
for item in items:
listbox.insert(tk.END, item)
efield = tk.Entry(master)
efield.grid(row=1, column=0)
tk.mainloop()
Steps to reproduce:
Type something in the entry field.
Select something in the listbox.
Highlight whatever you entered in the entry field => selection in the listbox gets cleared.
This related question with similar issue How to select at the same time from two Listbox? suggests to use exportselection=0, which doesn't seem to work for me. In such case selection = listbox.selection_get() throws an error while the right line is still highlighted.
I know this is an old question, but it was the first google search result when I came across the same problem. I was seeing odd behavior using 2 list boxes when using selection_get() and also the selection persistence issue.
selection_get() is a universal widget method in Tkinter, and was returning selections that were last made in other widgets, making for some really strange behavior. Instead, use the ListBox method curselection() which returns the selected indices as a tuple, then you can use the ListBox's get(index) method to get the value if you need.
To solve the persistence issue, set exportselection=0 when instantiating the ListBox instance.
list_box = tk.Listbox(master, exportselection=False)
...
selected_indices = list_box.curselection()
first_selected_value = list_box.get(selected_indices[0])
As for now, I wasn't able to cleanly overcome the problem. One way around is to create a variable which will store the selected list value on click:
selected = None
def onselect(e):
global selected
selected = listbox.selection_get()
listbox.bind('<<ListboxSelect>>', onselect)
This doesn't keep the highlight, but the selection is now stored in a variable and can be used further.