Hello,

Im trying to make a simple equation solver with tkinter. Originally i built it without using classes and it worked fine however I am now trying to use a class.

from tkinter import *
import math

class RootFinder(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        self.root1lbl=Label(self.outputframe, text='')
        self.root1lbl.grid(row=0,column=1)

        self.root2lbl=Label(self.outputframe,text='')
        self.root2lbl.grid(row=0, column=4)

        self.calcbutton=Button(self.inputframe, text="Calculate Roots",\
                               command=self.findroots())
        self.calcbutton.grid(row=1, column=5, padx=20)

    def findroots(self):
        sqr=self.sqrcoeff.get()
        xcoeff=self.xcoeff.get()
        const=self.constant.get()

        a=float(sqr)
        b=float(xcoeff)
        c=float(const)

        root1=round((-b+math.sqrt(b*b-4*a*c))/(2*a),3)
        root2=round((-b-math.sqrt(b*b-4*a*c))/(2*a),3)
        self.root1lbl.configure(text=root1)
        self.root2lbl.configure(text=root2)

app=RootFinder()
app.mainloop()

Ive only shown the widgets concerned. The problem is that it doesnt like me trying to configure the root1 and root2 labels and I really don't know why. This is the output when run:

Traceback (most recent call last):
File "C:/Python32/Programs/new class.py", line 83, in <module>
app=RootFinder()
File "C:/Python32/Programs/new class.py", line 9, in __init__
self.create_widgets()
File "C:/Python32/Programs/new class.py", line 37, in create_widgets
command=self.findroots())
File "C:/Python32/Programs/new class.py", line 80, in findroots
RootFinder.root1lbl.configure(text=root1)
AttributeError: type object 'RootFinder' has no attribute 'root1lbl'


Any help is appreciated thanks.

We really need the whole code.

Or at least try to replace RootFinder.root1lbl.configure(text=root1) with self.root1lbl.configure(text=root1)

Edited 5 Years Ago by vegaseat: n/a

But one sure thing is that you are calling findroots instead of giving findroots method as parameter in line 37 in error message, line 18 in posted code.

There are a lot of problems with the code you posted:

## there is no root window
app=RootFinder()
app.mainloop()
#----------  should be 
root = Tk()
app=RootFinder(root)
root.mainloop()
#
## self.outputframe is never declared in the code you posted
    def create_widgets(self):
        self.root1lbl=Label(self.outputframe, text='')

And that is all that I care to examine at this point. See Ene Uran's example for starters.

Edited 5 Years Ago by woooee: n/a

Here is the full code:

from tkinter import *
import math
import cmath

class RootFinder(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid()
        self.create_widgets()

    def create_widgets(self):
        self.labelf=Label(self, text="What is f(x)?", font='Arial 10 bold', pady=5)
        self.labelf.grid(sticky='w')
        
        self.inputframe=Frame(self)
        self.inputframe.grid(row=1, columnspan=5)
        
        self.sqrcoeff=Entry(self.inputframe, width=5)
        self.sqrcoeff.grid(row=1, column=0)
        self.sqrcoeff.insert(0, '1')
        
        self.xsqrlabel=Label(self.inputframe, text="x\u00B2 + ")
        self.xsqrlabel.grid(row=1, column=1)

        self.xcoeff=Entry(self.inputframe, width=5)
        self.xcoeff.grid(row=1, column=2)
        self.xcoeff.insert(0, '0')
        
        self.xlabel=Label(self.inputframe, text="x + ")
        self.xlabel.grid(row=1, column=3)
        
        self.constant=Entry(self.inputframe, width=5)
        self.constant.grid(row=1, column=4)
        self.constant.insert(0, '0')
        
        self.calcbutton=Button(self.inputframe, text="Calculate Roots",\
                               command=self.findroots())
        self.calcbutton.grid(row=1, column=5, padx=20)
        
        self.outputframe=Frame(self)
        self.outputframe.grid(row=2, columnspan=5)
        
        self.rootlabel=Label(self.outputframe, text="x = ")
        self.rootlabel.grid(row=0,column=0)
        
        self.root1lbl=Label(self.outputframe, text='       ')
        self.root1lbl.grid(row=0,column=1)
        
        self.orlabel=Label(self.outputframe,text=" or ")
        self.orlabel.grid(row=0, column=2)
        
        self.root2lbl=Label(self.outputframe,text='       ')
        self.root2lbl.grid(row=0, column=4)

    def findroots(self):
        sqr=self.sqrcoeff.get()
        xcoeff=self.xcoeff.get()
        const=self.constant.get()
        
        if sqr == "" or sqr == "0":
            messagebox.showinfo(message="This is not a quadratic equation")

        else:
            a=float(sqr)
            b=float(xcoeff)
            c=float(const)

        if b*b-4*a*c < 0:  #for complex roots
            root1=(-b+cmath.sqrt(b*b-4*a*c))/(2*a)
            root2=(-b-cmath.sqrt(b*b-4*a*c))/(2*a)
            re1, im1=round(root1.real,3), round(root1.imag,3)
            re2, im2=round(root2.real,3), round(root2.imag,3)
            root1, root2=complex(re1,im1), complex(re2,im2)
            self.root1lbl.configure(text=root1)
            self.root2lbl.configure(text=root2)

        else:      #for real roots
            root1=round((-b+math.sqrt(b*b-4*a*c))/(2*a),3)
            root2=round((-b-math.sqrt(b*b-4*a*c))/(2*a),3)
            self.root1lbl.configure(text=root1)
            self.root2lbl.configure(text=root2)

app=RootFinder()
app.mainloop()

In response to woooee, I had said in my previus post that i had only shown relevant widgets.

Instead of 84 lines of code, with no idea what the problem is, compose the program in steps and test after each step. To get you started: (note the difference between final three lines here, and your code).

try:
    # Python2
    import Tkinter as tk
except ImportError:
    # Python3
    import tkinter as tk

import math
import cmath

class RootFinder():
    def __init__(self, master=None):
        self.fr = tk.Frame(master)
        self.fr.grid()
        self.create_widgets()

    def create_widgets(self):
        self.labelf=tk.Label(self.fr, text="What is f(x)?", font='Arial 10 bold', pady=5)
        self.labelf.grid(row=0, column=0, sticky='w')

        self.sqrcoeff=tk.Entry(self.fr, width=5)
        self.sqrcoeff.grid(row=1, column=0)
        self.sqrcoeff.insert(0, '1')

root = tk.Tk()
RF = RootFinder(root)
root.mainloop()

Edited 5 Years Ago by woooee: n/a

After your suggestion I added each line of code at a time...
It didnt like it when lines 74,75 and 80,81 were added

In your button you are calling
command=self.findroots()
it needs to be a reference, not a call
command=self.findroots

Right Tony! A mistake frequently made by beginners to Tkinter. The error message is often confusing in this case.

Problem with these "procedural functions" which do not at least say: "wrong number of parameters". One place where there would be really benefit for type check. (until you want to use function returning function, like decorated function)

Edited 5 Years Ago by pyTony: n/a

This question has already been answered. Start a new discussion instead.