I am fairly new to TKinter and have been trying to convert my normal Python code into a GUI (TKinter Code)! I have been working on this code and so far, I have got the basic layout made but I am having problems coding buttons and using entries. You will most likely find a lot of errors in my code so be warned! :D
I have got an entry at the top of the window and I want the user to input a number into the entry and then I want to use the text inputted in the entry in some code (btn1()). I also want the user to press a button and then the button to run some code with labels underneath where the buttons are showing the results of the code (the labels in the btn1() function).
First, I want the user to input a number into the entry. Then, I want the user to click on a button which is underneath the entry. Finally, I want the results of the code behind the button, to be show underneath the buttons (in labels!).
Here is my code:
from tkinter import *
class window_design:
def __init__(self):
root=Tk()
root.title("Bag Weight")
root.geometry("500x700")
root.wm_iconbitmap('favicon.ico')
image=PhotoImage(file="Weight Program.png")
imagelabel=Label(root,image=image)
imagelabel.pack()
weightentrylabel=Label(root,text="Enter Weight!")
weightentrylabel.pack()
self.string=StringVar()
weightentry=Entry(root,textvariable=self.string)
weightentry.pack()
menutext=Label(root,text="What coin are you using?")
menutext.pack(side=LEFT)
values=['1p','2p','5p','10p','20p','50p','£1','£2','Exit']
def btn1(self,btn1code):
p1=3.56
p1should=356
if (self.string.get()) > p1should:
weightdif=(self.string.get())-p1should
coins=weightdif/p1
labeldif=Label(text=weightdif)
labelcoins=Label(text=coins)
elif (self.string.get()) < p1should:
weightdif=p1should-(self.string.get())
coins=weightdif/p1
labeldif=Label(text=weightdif)
labelcoins=Label(text=coins)
button1=Button(root,text="1p",command=btn1)
button1.pack(side=LEFT)
root.mainloop()
window_design()
I am currently getting this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\cjay2\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
TypeError: btn1() missing 2 required positional arguments: 'self' and 'btn1code'
You should use self.btn1 ( btn1 is a class method) in button1=Button(root,text="1p",command=btn1).
btn1() is called with one argument and it needs two arguments, set a default value to btn1code or removeit (if you do not use it).
When you call get() method on StringVar() it will return a string so you need to convert before comparing with integers.
To show result in label use a self.result = StringVar() then call self.result.set(a_string).
Check the following code:
from tkinter import *
class window_design:
def __init__(self):
root=Tk()
root.title("Bag Weight")
#root.geometry("500x700")
root.wm_iconbitmap('favicon.ico')
image=PhotoImage(file="Weight Program.png")
imagelabel=Label(root,image=image)
imagelabel.pack()
weightentrylabel=Label(root,text="Enter Weight!")
weightentrylabel.pack()
self.string=StringVar()
weightentry=Entry(root,textvariable=self.string)
weightentry.pack()
menutext=Label(root,text="What coin are you using?")
#menutext.pack(side=LEFT)
menutext.pack()
values=['1p','2p','5p','10p','20p','50p','£1','£2','Exit']
button1=Button(root,text="1p",command=self.btn1)
#button1.pack(side=LEFT)
button1.pack()
#--------------------------------------------------
self.result=StringVar()
resultlabel=Label(root, textvariable = self.result)
resultlabel.pack()
#--------------------------------------------------
root.mainloop()
#-------------------------------------
def btn1(self):
p1=3.56
p1should=356
if not self.string.get(): return
value = int(self.string.get())
if value > p1should:
weightdif = value - p1should
coins=weightdif/p1
elif value < p1should:
weightdif=p1should - value
coins=weightdif/p1
self.result.set(coins)
#-----------------------------------
window_design()
You defined btn1() as needing an argument besides self, but Tkinter is calling it without one. It looks like you are not even using btn1code, so you can change your function definition to def btn1(self):
you can declare btn1code as member variable,and remove it from your function definition, or if you want call function with arguments from the Button; use lambda function like this :
button1=Button(root,text="1p",command=lambda: btn1(btn1code))
Related
I'm working on a small project and I'm having issues retrieving the values stored in combo boxes. The program has a "plus" button that creates additional boxes beneath the existing ones. They are created by calling a "create" function that makes a new instance of the ComboBox class, where the box is created and put onto the screen. A separate "submit" function is then supposed to loop through and retrieve all of the box values and store them in a list. My main flaw is that I used data in the variable names, but I have no clue how else to do this in this scenario. Does anyone have an alternative solution?
(there are some off screen variables that are show used here as parameters, but there are definitely not the source of the issue)
class ComboBox:
def __init__(self, master, counter, fields):
self.master = master
self.counter = counter
self.fields = fields
self.field_box = ttk.Combobox(width=20)
self.field_box["values"] = fields
self.field_box.grid(row=counter + 1, column=0, pady=5)
def get_value(self):
value = self.field_box.get()
return value
def create():
global entry_counter
name = "loop"+str(entry_counter-1)
name = ComboBox(window, entry_counter, fields)
values.append(name.get_value())
entry_counter += 1
def submit():
for i in range(1, entry_counter):
name = "loop" + str(entry_counter-1)
values.append(name.get_value())
For example, if I created 2 boxes and selected the options "test1" and "test2" I would want the my values list to contain ["test1, "test2"]
Not sure I understand the question right, but I guess you are asking about how to loop throw all instances of ComboBox. You can just create an global array, append new instance into it in create() method:
comboboxes = []
def create():
...
comboboxes.append(new_instance)
def submit():
for combobox in comboboxes:
...
You're on the right track with .get(). I believe your solution is that your get_value function also needs an event parameter:
def get_value(self, event):
value = self.field_box.get()
return value
See the following:
Getting the selected value from combobox in Tkinter
Retrieving and using a tkinter combobox selection
I am trying to write a small program to use at work. It looks like this:
As you can see there are two dropdown menu's. When clicking on one of the buttons on the menu, filling in the other two Entry's (Korte beschrijving, datum) and clicking on Voeg incident toe (Add new incident) it should be saved as an entry in the database. I guess there are a few things not working and I'm getting two errors:
First I got the: "Option menu has no attribute get" error. Then I made two functions:
def drop_down_soort():
soort.get()
window.quit()
def drop_down_user():
user.get()
window.quit()
Now I am getting a new error:
This is the entire code: frontend and backend + error.
from tkinter import *
import backend
def alle_incidenten():
tekst_vak.delete(0,END)
for row in backend.alle():
tekst_vak.insert(END,row)
def drop_down_soort():
soort.get()
window.quit()
def drop_down_user():
user.get()
window.quit()
def voeg_toe():
backend.voeg_toe(drop_down_soort.get(),drop_down_user.get(),
beschrijving_tekst.get(),datum_tekst.get())
tekst_vak.delete(0,END)
tekst_vak.insert(END,(drop_down_soort.get(),drop_down_user.get(),
beschrijving_tekst.get(),datum_tekst.get()))
window=Tk()
window.wm_title("T I T A A N Incidenten Register")
soort = StringVar(window)
soort.set("Soort")
menu = OptionMenu(window, soort, "Incident", "RFC", "Opdracht")
menu.grid(row=0,column=0)
user = StringVar(window)
user.set("User")
user_menu = OptionMenu(window, user, "Jesse", "Jan", "Sirano", "Shannon",
"Niek", "Thomas", "Patrick")
user_menu.grid(row=1,column=0)
l3=Label(window,text="Korte beschrijving")
l3.grid(row=0,column=2)
l4=Label(window,text="Datum")
l4.grid(row=1,column=2)
beschrijving_tekst=StringVar()
l3=Entry(window,textvariable=beschrijving_tekst)
l3.grid(row=0,column=3)
datum_tekst=StringVar()
l4=Entry(window,textvariable=datum_tekst)
l4.grid(row=1,column=3)
tekst_vak=Listbox(window,height=10,width=35)
tekst_vak.grid(row=2,column=0,rowspan=6,columnspan=2)
scrollbar1=Scrollbar(window)
scrollbar1.grid(row=2,column=2,rowspan=10)
tekst_vak.configure(yscrollcommand=scrollbar1.set)
scrollbar1.configure(command=tekst_vak.yview)
b1=Button(window,text="Alle incidenten", width=14, bg='Gray',
command=alle_incidenten)
b1.grid(row=2,column=3)
b2=Button(window,text="Voeg incident toe", width=14, bg='Gray',
command=voeg_toe)
b2.grid(row=3,column=3)
b3=Button(window,text="Pas incident aan", width=14, bg='Gray')
b3.grid(row=4,column=3)
b4=Button(window,text="Verwijder incident", width=14, bg='Red')
b4.grid(row=5,column=3)
b5=Button(window,text="Sluit programma", width=14, bg='Orange')
b5.grid(row=6,column=3)
window.mainloop()
Backend:
import sqlite3
def verbind_met_database():
verbinding=sqlite3.connect("titaan_incidenten.db")
cur=verbinding.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS titaan_incidenten
(id INTEGER PRIMARY KEY, soort TEXT, user TEXT, beschrijving TEXT,
datum TEXT)")
verbinding.commit
verbinding.close()
def alle():
verbinding=sqlite3.connect("titaan_incidenten.db")
cur=verbinding.cursor()
cur.execute("SELECT * FROM titaan_incidenten")
rijen=cur.fetchall()
verbinding.close()
return rijen
def voeg_toe(soort,user,beschrijving,datum):
verbinding=sqlite3.connect("titaan_incidenten.db")
cur=verbinding.cursor()
cur.execute("INSERT INTO titaan_incidenten VALUES (NULL,?,?,?,?)",
(soort,user,beschrijving,datum))
verbinding.commit()
verbinding.close()
def pas_aan(id,soort,user,beschrijving,datum):
verbinding=sqlite3.connect("titaan_incidenten.db")
cur=verbinding.cursor()
cur.execute("UPDATE titaan_incidenten SET
soort=?,user=?,beschrijving=?,datum=? WHERE id=?",
(id,soort,user,beschrijving,datum))
verbinding.commit
verbinding.close()
def verwijder():
verbinding=sqlite3.connect("titaan_incidenten.db")
cur=verbinding.cursor()
cur.execute("DELETE FROM titaan_incidenten WHERE id=?",(id,))
ERROR:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\crisc\Anaconda3\lib\tkinter\__init__.py", line 1702, in __
call__
return self.func(*args)
File "frontend.py", line 18, in voeg_toe
backend.voeg_toe(drop_down_soort.get(),
drop_down_user.get(),beschrijving_tekst.get(),datum_tekst.get())
AttributeError: 'function' object has no attribute 'get'
For me, working with the dropdown menu's is something I never done before. So maybe the functions I created are not necessary. If somebody could give me some pointers on how to get that menu working, that would be great!
I edited it with the correct error and code. Sorry for the earlier confusion.
Thanks,
Cris
Based on the information you've provided, you're passing the wrong parameters to backend.voeg_toe() function. Rather than using drop_down_soort.get(), drop_down_user.get(), you should pass just these functions without .get() which does not make sense to your function, and return values inside the function.
Function bodies can contain one or more return statement. They can be situated anywhere in the function body. A return statement ends the execution of the function call and "returns" the result, i.e. the value of the expression following the return keyword, to the caller. If the return statement is without an expression, the special value None is returned. If there is no return statement in the function code, the function ends, when the control flow reaches the end of the function body and the value "None" will be returned.
for example:
def drop_down_soort():
test = soort.get() #not sure even if soort.get() is getting any value, but I suppose yes!!!!
window.quit()
return test
def drop_down_user():
test = user.get() #not sure even if user.get() is getting any value, but I suppose yes!!!!
window.quit()
return test
so then whenever you call backend.voeg_toe(drop_down_soort(),drop_down_user(),....) it will get the returning values of those two functions and will pass it as parameters.
--UPDATE:
I changed
variable=self.optionVal.get()
to
variable=self.optionVal
But nothing changed.Also I wonder why it automatically call self.selected while compiling?
----Original:
I'm trying to get familiar with radiobutton, but I don't think I understand how radiobutton works. Here's a brief code for demonstration:
self.optionVal = StringVar()
for text, val in OPTIONS:
print(text,val)
radioButton = Radiobutton(self,
text=text,
value=val,
variable=self.optionVal.get(),
command = self.selected())
radioButton.pack(anchor=W)
def selected(self):
print("this option is :"+self.optionVal.get())
In my opinion this should work like once I choose certain button, and it prints out "this option is *the value*", however now what it does is once compiled, it prints out everything, and the self.optionVal.get() is blankspace, as if value wasn't set to that variable.
I wonder what happens to my code,
Many thanks in advance.
AHA! I beleive I've figured it out. I had the exact same issue. make sure you are assigning a master to the IntVar like self.rbv=tk.IntVar(master) #or 'root' or whatever you are using):
import Tkinter as tk
import ttk
class My_GUI:
def __init__(self,master):
self.master=master
master.title("TestRadio")
self.rbv=tk.IntVar(master)#<--- HERE! notice I specify 'master'
self.rb1=tk.Radiobutton(master,text="Radio1",variable=self.rbv,value=0,indicatoron=False,command=self.onRadioChange)
self.rb1.pack(side='left')
self.rb2=tk.Radiobutton(master,text="Radio2",variable=self.rbv,value=1,indicatoron=False,command=self.onRadioChange)
self.rb2.pack(side='left')
self.rb3=tk.Radiobutton(master,text="Radio3",variable=self.rbv,value=2,indicatoron=False,command=self.onRadioChange)
self.rb3.pack(side='left')
def onRadioChange(self,event=None):
print self.rbv.get()
root=tk.Tk()
gui=My_GUI(root)
root.mainloop()
try running that, click the different buttons (they are radiobuttons but with indicatoron=False) and you will see it prints correctly changed values!
You're very close. Just take out the .get() from self.optionVal.get(). The Radiobutton constructor is expecting a traced variable, you're giving it the result of evaluating that variable instead.
You need to:
Remove the .get() from the variable=self.optionVal argument in the constructor the button. You want to pass the variable, not the evaluated value of the variable; and
Remove the parenthesis from command=self.selected() and use command=self.selected instead. The parenthesis says "call this function now and use the return value as the callback". Instead, you want to use the function itself as the callback. To better understand this, you need to study closures: a function can return a function (and, if that was the case, that would be used as your callback).
EDIT: A quick reminder, also: Python is not compiled, but interpreted. Your callback is being called while the script is being interpreted.
def view(interface):
choice = interface.v.get()
if choice == 0:
output = "0"
elif choice == 1:
output = "1"
elif choice == 2:
output = "2"
elif choice == 3:
output = "3"
else:
output = "Invalid selection"
return tk.messagebox.showinfo('PythonGuides', f'You Selected {output}.')
class Start:
def __init__(self):
self.root = tk.Tk()
self.root.geometry('500x500')
self.root.resizable(False, False)
self.root.title('find out the degree of severity')
self.v = tk.IntVar()
dolori_ossa = {"nessun dolore": 0,
"dolori articolari": 1,
"frattura composta": 2,
"frattura scomposta": 3}
for (txt, val) in dolori_ossa.items():
tk.Radiobutton(self.root,
text=txt,
variable=self.v,
value=val,
command=lambda:view(self)
).pack()
I'm having some trouble adding a value taken from an Entry box and adding it to an existing number. In this case, I want the value of the "change speed" box to be added to the robots current speed. When run, my code produces an error:
TypeError: unsupported operand type(s) for +=: 'int' and 'IntVar'.
Below is the code that produces the entry box:
change_speed_entry = ttk.Entry(main_frame, width=5) # Entry box for linear speed
change_speed_entry.grid()
data = tkinter.IntVar()
change_speed_entry['textvariable'] = data
And next is where I try to manipulate the result. This is a method within a class. All other methods of the class work correctly:
def changeSpeed(self, delta_speed):
self.speed += delta_speed
You need to first invoke the .get method of IntVar:
def changeSpeed(self, delta_speed):
self.speed += delta_speed.get()
which returns the variable's value as an integer.
Since I don't have your full code, I wrote a small script to demonstrate:
from Tkinter import Entry, IntVar, Tk
root = Tk()
data = IntVar()
entry = Entry(textvariable=data)
entry.grid()
def click(event):
# Get the number, add 1 to it, and then print it
print(data.get() + 1)
# Bind the entrybox to the Return key
entry.bind("<Return>", click)
root.mainloop()
When you run the script, a small window appears that has an entrybox. When you type a number in that entrybox and then click Return, the script gets the number stored in data (which will be the number you typed in), adds 1 to it, and then prints it on the screen.
You didn't show the code defining .speed or delta_speed, so I'm guessing here. Try:
self.speed += delta_speed.get()
^^^^^^
If delta_speed is an IntVar, .get() will retrieve its value as a Python int.
I am making a GUI Program in Tkinter and am running into problems.What I want to do is draw 2 checkboxes and a button. According to the user input next steps should take place. A part of my code has been shown below :-
CheckVar1 = IntVar()
CheckVar2 = IntVar()
self.C1 = Checkbutton(root, text = "C Classifier", variable = CheckVar1, onvalue = 1, offvalue = 0, height=5,width = 20).grid(row=4)
self.C2 = Checkbutton(root, text = "GClassifier", variable = CheckVar2, onvalue = 1, offvalue = 0, height=5, width = 20).grid(row=5)
self.proceed1 = Button(root,text = "\n Proceed",command = self.proceed(CheckVar1.get(),CheckVar2.get())).grid(row=6)
# where proceed prints the combined values of 2 checkboxes
The error that I am getting is typical ie a default value of both the selected checkboxes gets printed up and then there is no further input. The error that I get is NullType Object is not callable.
I searched on the net and I think the answer is related to lambda events or curry.
Please help ..
You're passing the value of self.proceed(CheckVar1.get(),CheckVar2.get()) to the Button constructor, but presumably what you want is for command to be set to a function which will call self.proceed(CheckVar1.get(),CheckVar2.get()) and return a new, possibly different value every time the button is pressed. You can fix that with a lambda, or by wrapping the call in a short callback function. For example, replace the last line with:
def callback():
return self.proceed(CheckVar1.get(), CheckVar2.get())
self.proceed1 = Button(root, text="\n Proceed", command=callback).grid(row=6)
This is pretty typical Tkinter. Remember: when you see a variable called command in Tkinter, it's looking for a function, not a value.
EDIT: to be clear: you're getting 'NullType Object is not callable' because you've set command to equal the return value of a single call to self.proceed (that's the NullType Object). self.proceed is a function, but its return value is not. What you need is to set command to be a function which calls self.proceed.
Like Peter Milley said, the command option needs a reference to a function (ie: give it a function name (ie: no parenthesis). Don't try to "inline" something, create a special function. Your code will be easier to understand and to maintain.