Reputation: 285
I have a problem trying to create a simple calculation with combo box in tkinter using Classes. For me this is quite tricky, and difficult to understand it! Hope you can help me with this.
Thanks in advance.
Héctor.
Here is my code:
from Tkinter import *
import ttk
from ttk import Combobox
root= Tk()
root.minsize(550,450)
root.maxsize(560,460)
root.title('myAPP')
class Calculation:
def __init__(self, parent):
self.parent = parent
self.Value1()
self.Value2()
self.Result()
Label(self.parent,text='Num 1').grid(column=2, row=5,sticky=W,pady=3)
Label(self.parent,text='Num 2').grid(column=2, row=6,sticky=W,pady=3)
Label(self.parent,text='result').grid(column=9,row=9,sticky=W,pady=3)
self.msg =Label(self.parent,text='Sum of 2 number')
self.msg.grid(row=3,column=1,columnspan=2)
self.Button =Button(text='Calculate',width=8,command =self.Result)
self.Button.grid(row=9,column=2,padx=2,pady=3)
def Value1(self):
self.field1 = StringVar()
self.field1 = ttk.Combobox(self.parent, textvariable= self.field1)
self.field1['values'] = ('5', '6', '7')
self.field1.grid(column=3, row=5)
def Value2(self):
self.field2 = StringVar()
self.field2 = ttk.Combobox(self.parent, textvariable=self.field2)
self.field2['values'] = ('1', '2', '3')
self.field2.grid(column=3, row=6)
def Result(self):
self.entry = StringVar()
self.entry = ttk.Entry(self.parent, textvariable = self.entry)
#self.entry = field1 + field2 ----> Here is the problem I have!
self.entry.grid(column=3, row=9)
#End Code
if __name__ == '__main__':
app = Calculation (root)
root.mainloop()
Upvotes: 0
Views: 3207
Reputation: 369494
from Tkinter import *
import ttk
root= Tk()
root.minsize(550,450)
root.maxsize(560,460)
root.title('myAPP')
class Calculation:
def __init__(self, parent):
self.parent = parent
self.Value1()
self.Value2()
self.Result()
Label(self.parent,text='Num 1').grid(column=2, row=5, sticky=W, pady=3)
Label(self.parent,text='Num 2').grid(column=2, row=6, sticky=W, pady=3)
Label(self.parent,text='result').grid(column=9,row=9, sticky=W, pady=3)
self.msg = Label(self.parent,text='Sum of 2 number')
self.msg.grid(row=3,column=1,columnspan=2)
def Value1(self):
self.field1_value = StringVar()
self.field1_value.trace('w', self.Calc)
self.field1 = ttk.Combobox(self.parent, textvariable=self.field1_value)
self.field1['values'] = ('5', '6', '7')
self.field1.grid(column=3, row=5)
def Value2(self):
self.field2_value = StringVar()
self.field2_value.trace('w', self.Calc)
self.field2 = ttk.Combobox(self.parent, textvariable=self.field2_value)
self.field2['values'] = ('1', '2', '3')
self.field2.grid(column=3, row=6)
def Result(self):
self.entry = StringVar()
self.entry = ttk.Entry(self.parent, textvariable=self.entry)
self.entry.grid(column=3, row=9)
def Calc(self, *args):
self.entry.delete(0, END)
try:
value = int(self.field1.get()) + int(self.field2.get())
except ValueError:
self.entry.insert(0, 'Input numbers.')
else:
self.entry.insert(0, str(value))
if __name__ == '__main__':
app = Calculation(root)
root.mainloop()
I splitted Result method into two methods: Result, Calc
EDIT - Removed button. - Attach textvariable (field1_value, field2_value) to comboboxes. - When variables change (= comboxbox value change) call Calc() using StringVar.trace
Upvotes: 1
Reputation: 4623
Your interface code will be splitted in two parts: a description of your widgets wich will be run at initialisation and the dynamic behavior of your application.
You already have the description of your GUI. For the behavior, defining a command
on the button is a good start, but this code will not look like your Result
method (which create an entry). In this method (named a callback), you will manipulate your already existing object : read the value of the comboxboxes, set the new value of the entry... For example (adapted from falsetru's answer):
self.button = Button(... , command=self.calcultate)
def calculate(self):
self.entry.delete(0, END)
value = int(self.field1.get()) + int(self.field2.get())
self.entry.insert(0, str(value))
There are other way to define the behavior of you application, for instance, you can associate variables to widgets with values (entries, comboboxes...) and trigger an action as soon as this variables are modified:
self.number1 = IntVar()
self.field1 = ttk.Combobox(self.parent, textvariable=self.number1)
self.number1.trace("w", self.calculate)
(Note that I have choose to use an IntVar to avoid the need of int()
parse of the previous solution).
To avoid errors when the user enter non number in the combobox, you could either catch exception when you read values, or use a validation command to forbid non-digit input.
def ensure_digit(candidate_string):
return candidate_string.isdigit()
self.field1.config(validate = "key", validatecommand =(self.field1.register(ensure_digit), "%S"))
Upvotes: 0
Reputation: 123531
I think this does what you're trying to accomplish:
from Tkinter import *
import ttk
from ttk import Combobox
class Calculation(object):
def __init__(self, parent):
self.parent = parent
self.create_widgets()
def create_widgets(self):
self.msg = Label(self.parent, text='Sum of 2 numbers:')
self.msg.grid(row=3, column=1, columnspan=2)
Label(self.parent, text='Num 1').grid(row=5, column=2, sticky=W, pady=3)
self.number1 = IntVar()
self.widget1 = ttk.Combobox(self.parent, textvariable=self.number1)
self.widget1['values'] = '5', '6', '7'
self.widget1.grid(row=5, column=3)
Label(self.parent, text='Num 2').grid(row=6, column=2, sticky=W, pady=3)
self.number2 = IntVar()
self.widget2 = ttk.Combobox(self.parent, textvariable=self.number2)
self.widget2['values'] = '1', '2', '3'
self.widget2.grid(row=6, column=3)
self.button = Button(text='Calculate', command=self.calculate_result)
self.button.grid(row=9, column=2, padx=2, pady=3)
self.result = StringVar()
self.widget3 = ttk.Entry(self.parent, textvariable=self.result)
self.widget3.grid(row=9, column=3)
Label(self.parent, text='result').grid(row=9, column=9, sticky=W, pady=3)
def calculate_result(self):
self.result.set(self.number1.get() + self.number2.get())
if __name__ == '__main__':
root= Tk()
root.minsize(550, 450)
root.maxsize(560, 460)
root.title('myAPP')
app = Calculation(root)
root.mainloop()
I also highly recommend that you read and start following the recommendations in PEP 8 -- Style Guide for Python Code especially in regards to naming of entities in your code. In addition, I think if you were more consistent in the ordering of keyword arguments and spacing of them that it would be a great improvement in your coding style. It's good to establish doing things properly early on, so that they'll become habits you won't even have to think about doing later.
Upvotes: 0