Giving an error in Boolean statement in python - python

I am trying to make an app with Python, Tkinter. In this programme in line 47, I have used a boolean statement. But it is giving me an error. I want to use boolean statement as a memory bit and want to use anywhere in programme.
import serial
import Tkinter
from Tkinter import *
class SerialViewer:
def __init__(self):
self.win = Tk()
self.ser = serial.Serial('com8',9600)
def bt1 (self):
self.ser.write('on')
def bt2 (self):
self.ser.write('off')
def bt3 (self):
self.ser.write(self.v.get())
def makewindow (self):
frame1 = Frame(self.win)
frame1.pack(side = LEFT)
b1 = Button(frame1, text = "ON", command = self.bt1)
b2 = Button(frame1, text = "OFF", command = self.bt2)
b1.grid(row = 0, column = 0)
b2.grid(row = 0, column = 1)
frame2 = Frame(self.win)
frame2.pack()
self.v = StringVar()
r1 = Radiobutton(frame2,text = 'on', variable = self.v, value = 'on')
r2 = Radiobutton(frame2,text = 'off', variable = self.v, value = 'off')
r1.select()
b3 = Button(frame2, text = 'send', command = self.bt3)
b3.pack(sid = RIGHT, padx = 5)
r1.pack(side = LEFT)
r2.pack(side = LEFT)
frame3 = Frame(self.win)
frame3.pack()
self.d = StringVar()
self.d.set('default')
label = Label(frame3, textvariable = self.d, relief = RAISED)
label.pack(side = RIGHT)
def update(self):
data = self.ser.readline(self.ser.inWaiting())
self.d.set(data)
if data == 'f1':
self.M1 = True
if self.M1:
print("ok tested")
self.win.after(100,self.update)
def run(self):
self.makewindow()
self.update()
self.win.mainloop()
SerialViewer().run()
The error is:Traceback (most recent call last): File "Untitled",
line 58
SerialViewer().run() File "Untitled", line 55, in run
self.update() File "Untitled", line 49, in update
if self.M1: AttributeError: SerialViewer instance has no attribute 'M1'

I think you should initialize M1 in the constructor. Like this:
def __init__(self):
self.win = Tk()
self.ser = serial.Serial('com8',9600)
self.M1 = False
Because when you get into update method and data != 'f1' it seeks the M1 propriety that doesn't exists.

In your update method, you only define self.M1 when your data is equal to "f1". When it isn't, self.M1 is not defined, so you receive this error.
To fix it, add an else clause to your if statement before, where self.M1 can be set to false.

Related

Creating a small add/subtract calculator with tkinter in Python?

I've for the most part created the program using the tkinter GUI tools, I just cannot see where I've gone wrong in the actual point where the + or - are clicked. It should be taking the value entered into the entry field, and adding it to the result label, but it's throwing a TypeError saying can only concatenate str (not "StringVar") to str.
import tkinter
class Calculator_GUI:
def __init__(self):
self.mw = tkinter.Tk()
self.mw.title("Calculator")
self.top_frame = tkinter.Frame(self.mw)
self.mid_frame = tkinter.Frame(self.mw)
self.bottom_frame = tkinter.Frame(self.mw)
self.prompt_label = tkinter.Label(self.top_frame, text = "Total: ")
self.num_entry = tkinter.Entry(self.mid_frame, width = 15)
self.add_button = tkinter.Button(self.bottom_frame, text = "+", width = 10, command = self.add)
self.minus_button = tkinter.Button(self.bottom_frame, text = "-", width = 10, command = self.subtract)
self.reset_button = tkinter.Button(self.bottom_frame, text = "Reset", width = 10, command = self.reset)
self.result = tkinter.StringVar()
self.result_label = tkinter.Label(self.top_frame, textvariable = self.result)
self.prompt_label.pack(side = "left")
self.num_entry.pack(side = "left")
self.add_button.pack(side = "left")
self.minus_button.pack(side = "left")
self.reset_button.pack(side = "left")
self.result_label.pack(side = "left")
self.top_frame.pack()
self.mid_frame.pack()
self.bottom_frame.pack()
tkinter.mainloop()
def add(self):
self.result = float(self.num_entry.get() + self.result)
def subtract(self):
self.result = float(self.result - self.num_entry.get())
def reset(self):
self.result.set(0)
calc = Calculator_GUI()
Since self.result is a StringVar, you need to use self.result.set(...) to update its value.
Also you need to convert the strings returned by .get() to number before doing the addition and substraction.
class Calculator_GUI:
def __init__(self):
...
self.num_entry = tkinter.Entry(self.mid_frame, width = 15)
self.num_entry.insert(0, '0') # initialize to zero
...
def add(self):
try:
self.result.set(float(self.num_entry.get()) + float(self.result.get()))
except ValueError as e:
print(e)
def subtract(self):
try:
self.result.set(float(self.result.get()) - float(self.num_entry.get()))
except ValueError as e:
print(e)
...
You need to set and convert correctly
import tkinter
class Calculator_GUI:
def __init__(self):
self.mw = tkinter.Tk()
self.mw.title("Calculator")
self.top_frame = tkinter.Frame(self.mw)
self.mid_frame = tkinter.Frame(self.mw)
self.bottom_frame = tkinter.Frame(self.mw)
self.prompt_label = tkinter.Label(self.top_frame, text = "Total: ")
self.num_entry = tkinter.Entry(self.mid_frame, width = 15)
self.add_button = tkinter.Button(self.bottom_frame, text = "+", width = 10, command = self.add)
self.minus_button = tkinter.Button(self.bottom_frame, text = "-", width = 10, command = self.subtract)
self.reset_button = tkinter.Button(self.bottom_frame, text = "Reset", width = 10, command = self.reset)
self.result = tkinter.StringVar()
self.result.set('0')
self.result_label = tkinter.Label(self.top_frame, textvariable = self.result)
self.prompt_label.pack(side = "left")
self.num_entry.pack(side = "left")
self.add_button.pack(side = "left")
self.minus_button.pack(side = "left")
self.reset_button.pack(side = "left")
self.result_label.pack(side = "left")
self.top_frame.pack()
self.mid_frame.pack()
self.bottom_frame.pack()
tkinter.mainloop()
def add(self):
self.result.set (str(float(self.num_entry.get()) + float(self.result.get())))
def subtract(self):
self.result.set (str(float(self.result.get()) - float(self.num_entry.get())))
def reset(self):
self.result.set('0')
calc = Calculator_GUI()
self.result is of type StringVar and StringVar.get() returns type str, therefore this error makes sense. Moreover, due to the same fact, you need to use the setter method set() in order to set your result label.
I tried it real quick and it works so far with one problem: it concatinates the strings instead of adding their parsed values. You need to parse the str before adding them.

How can I detect which on which frame was a Button Clicked in Tkinter?

I have a question. I have this code:
import tkinter as tk
class new_f:
def __init__(self,root,num):
self.new_frame=tk.Frame(root,width=100,height=100,bg='white',bd=3,relief=tk.GROOVE)
self.new_frame.pack(side=tk.LEFT,fill=tk.X,expand=True)
self.num=num
def add_label(self,t):
self.l1=tk.Label(self.new_frame,bg='white',text=t)
self.l1.pack()
def return_instance(self):
return self.num
class Main_win:
def __init__(self,root):
self.root=root
self.bind_number=0
self.current_index=0
self.instance_list=[]
self.b1=tk.Button(self.root,text='Add Frame',command=self.add_frame_win)
self.b1.pack(side=tk.BOTTOM)
self.b2=tk.Button(self.root,text='Add text',command=self.add_text_frame)
self.b2.pack(side=tk.BOTTOM)
def return_instance_num(self,num,*args):
self.current_index=num
def add_frame_win(self):
new_in=new_f(self.root,self.bind_number)
self.instance_list.append(new_in)
new_in.new_frame.bind('<Button-1>',lambda evnt: self.return_instance_num(new_in.return_instance()))
#self.current_index=new_in.return_instance()
self.bind_number+=1
def add_text_frame(self):
instance=self.instance_list[self.current_index]
instance.add_label('Hello World')
root=tk.Tk()
ob=Main_win(root)
root.mainloop()
What I a trying to achieve is that I want to detect on which frame was the left mouse-button clicked so as to make that Frame active and add the labels to that particular Frame. However, I am stuck on how would I go about writing the code. I need a new class Because I don't know how many frames will the user need.
This is a short example of the code I will be implementing later. So my question is:
How will I go to detect which frame was picked so as to make it active to add the labels?
In this approach I have label l1 bound to Button-1
This was achieved by passing self to new_f instead of root
and binding self.l1 to Button-1
import tkinter as tk
class new_f:
def __init__(self, prog, num):
self.prog = prog
self.new_frame = tk.Frame(prog.root, width = 100, height = 100, bg = 'white', bd = 3, relief = tk.GROOVE)
self.new_frame.pack(side = tk.LEFT, fill = tk.X, expand = True)
self.num = num
def add_label(self, t):
self.l1 = tk.Label(self.new_frame, bg = 'white', text = t)
self.l1.pack()
# binding button-1 press to label
self.l1.bind("<Button-1>", lambda evnt: self.prog.return_instance_num(self.return_instance()))
def return_instance(self):
return self.num
class Main_win:
def __init__(self, root):
self.root = root
self.bind_number = 0
self.current_index = 0
self.instance_list = []
self.b1 = tk.Button(self.root, text = 'Add Frame', command = self.add_frame_win)
self.b1.pack(side = tk.BOTTOM)
self.b2 = tk.Button(self.root, text = 'Add text', command = self.add_text_frame)
self.b2.pack(side = tk.BOTTOM)
def return_instance_num(self, num, *args):
self.current_index = num
def add_frame_win(self):
# note passing self not root
new_in = new_f(self, self.bind_number)
self.instance_list.append(new_in)
new_in.new_frame.bind('<Button-1>', lambda evnt: self.return_instance_num(new_in.return_instance()))
#self.current_index = new_in.return_instance()
self.bind_number = self.bind_number + 1
def add_text_frame(self):
instance = self.instance_list[self.current_index]
instance.add_label('Hello World')
root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()
Here is an alternative method that uses dictionaries to store l1 and new_frame objects as keys and new_f instances as values.
This method can be used for other tkinter objects (Entry, Listbox, Text, Canvas)
import tkinter as tk
class new_f:
def __init__(self, parent):
self.parent = parent
self.frame = tk.Frame(
parent.root, width = 100, height = 100,
bg = "white", bd = 3, relief = tk.GROOVE)
self.frame.pack(
side = tk.LEFT, fill = tk.X, expand = True)
self.frame.bind("<Button-1>", parent.get_current_frame)
def add_label(self, t):
self.label = tk.Label(self.frame, bg = "white", text = t)
self.label.pack(fill = tk.BOTH, expand = True)
# bind button-1 to label, set instance_label and current to self
self.label.bind("<Button-1>", self.parent.get_current_label)
self.parent.instance_label[self.label] = self.parent.current = self
class Main_win:
instance_label = dict() # This method can be expanded for other objects
instance_frame = dict() # that you may want to create in frames
def __init__(self, root):
self.root = root
self.b1 = tk.Button(
self.root, text = "Add Frame", command = self.add_frame_win)
self.b1.pack(side = tk.BOTTOM)
self.b2 = tk.Button(
self.root, text = "Add text", command = self.add_text_frame)
self.b2.pack(side = tk.BOTTOM)
def get_current_label(self, ev):
self.current = self.instance_label[ev.widget]
def get_current_frame(self, ev):
self.current = self.instance_frame[ev.widget]
def add_frame_win(self):
# note passing self not root
self.new_in = new_f(self)
self.instance_frame[self.new_in.frame] = self.current = self.new_in
def add_text_frame(self):
# Change message with entry tool?
self.current.add_label("Hello World")
root = tk.Tk()
ob = Main_win(root)
# This necessary to prevent error if user hits 'Add text' before 'Add Frame'
ob.add_frame_win()
root.mainloop()

creating button with tkinter

I was really curious why I cannot get my add_button to work,
as the window fails to come up when creating it.
from tkinter import *
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = 0
self.input2 = 0
input1 = Entry(master)
input2 = Entry(master)
input1.grid(row = 0, column = 1)
input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_buton = Button(master, text = "Add", command = self.add())
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
return self.input1.get() + self.input2.get()
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
#-------------------------------------------------
Welcome to Stack!
I've looked through you code I've been able to do what you are asking. There were a few errors within your code:
a) you had self.add_buton and self.add_button which caused an error.
b) self.input1 = 0 and self.input2 = 0 are not required.
c) You were calling self.add() as the command and you should be calling self.add. When calling it as a command you do not need ()
d)input1 = Entry(master) should be self.input1 = tk.Entry(master)
e) You should convert your input values into int or float as otherwise it will just one value onto the end of the other. (Eg, 1 + 5 = 15 whereas int(1) + int(5) = 6
Here is your code with the entry boxes working as they should. I have import tkinter as tk hence why it is tk.Entry
from tkinter import *
import tkinter as tk
class Calculator:
#-------------------------------------------------
def __init__(self, master):
self.master = master
master.title("Calculator")
self.close_button = Button(master, text = "Close", command = master.destroy)
Label(master, text = "First Digit").grid(row = 0)
Label(master, text = "Second Digit").grid(row = 1)
self.input1 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input2 = tk.Entry(bd=5, width=35, background='gray35', foreground='snow')
self.input1.grid(row = 0, column = 1)
self.input2.grid(row = 1, column = 1)
self.close_button.grid(row = 2, column = 0)
self.add_button = tk.Button(master, text = "Add", command = self.add)
self.add_button.grid(row = 2, column = 1)
master.configure(background = 'grey')
return
#-------------------------------------------------
def add(self):
val = self.input1.get()
print(val)
#-------------------------------------------------
#-------------------------------------------------
root = Tk()
calc = Calculator(root)
root.mainloop()
This should now work how you wanted it too. The variables within the entry can be changed to suit. You were correct in calling the value of the entry with self.input1.get().
Hope this has helped.

got Exception in Tkinter callback when do getter setter

so, I want to pass a value between two classes with sparated file by creating a new class as connector between them (getter and setter)
so, there're all of my code:
UIinput.py
from tkinter import *
from getset import getset
from restRFID import restRFID
class UIinput:
varInput = ""
varIN = ""
sset = getset()
def inputDat():
global varIN
ui = Tk()
ui.geometry("300x300")
ui.title("Input Data")
frame1 = Frame(ui)
frame1.pack()
frame2 = Frame(ui)
frame2.pack()
label1 = Label(frame1, text = "Masukkan nama: ")
label1.pack(side = LEFT)
textbox1 = Entry(frame1, bd = 5, width = 20)
textbox1.pack(side = LEFT)
varIN = textbox1.get()
Button1 = Button(ui, text = "Input", command = lambda: UIinput.process(textbox1.get()))
Button1.place(x = 150,y = 50)
ui.mainloop()
def process(dat):
UIinput.sset.set(str(dat))
restRFID.getDat()
UIinput.inputDat()
restRFID.py
from tkinter import *
from getset import getset
class restRFID:
getdat = getset()
def getDat():
ui = Tk()
ui.geometry("300x300")
frame1 = Frame(ui)
ui.title("Get Data")
frame1.pack()
frame2 = Frame(ui)
frame2.pack()
dat = StringVar()
dat.set(str(restRFID.getdat.get()))
label1 = Label(frame1, textvariable = dat)
label1.pack(side = LEFT)
ui.mainloop()
and the last is my code that I use as a setter getter for all the code above this code
getset.py
class getset(object):
def set(self, x):
self.inputdata = x
def get(self):
return self.inputdata
but when I try to compile it I got an error exception:
AttributeError: 'getset' object has no attribute 'inputdata'
but if try implemnt the getter and setter method in getset.py class, it's run succesfully without any errors.

Error with tkinter class [duplicate]

This question already has an answer here:
Why do my Tkinter widgets get stored as None? [duplicate]
(1 answer)
Closed 6 years ago.
I am making a basic temperture converter, I have it so you can convert celcius to farenheight, and now im trying to make it so you can switch. I have this code:
from tkinter import *
bool1 = True
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.x = Label(frame, text = 'Celcius:').grid(row = 0, column = 0)
self.c_var = DoubleVar()
Entry(frame, textvariable = self.c_var).grid(row = 0, column = 1)
self.z = Label(frame, text = 'Farenheight:').grid(row = 1, column = 0)
self.result_var = DoubleVar()
Label(frame, textvariable = self.result_var).grid(row = 1, column = 1)
b1 = Button(frame, text = 'Switch', command = self.switch)
b1.grid(row = 2, columnspan = 2)
button = Button(frame, text = 'Convert', command = self.convert)
button.grid(row = 3, columnspan = 2)
return None
def convert(self):
c = self.c_var.get()
c = c * (9/5) + 32
self.result_var.set(c)
def switch(self):
global bool1
if bool1 == True:
bool1 = False
self.x.config(text = 'Farenheight:')
else:
bool1 = True
self.z['text'] = 'Celcius:'
root = Tk()
root.wm_title('Temp Converter')
app = App(root)
root.mainloop()
The error message I am getting is:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\keith\AppData\Local\Programs\Python\Python35- 32\lib\tkinter\__init__.py", line 1550, in __call__
return self.func(*args)
File "C:\Users\keith\Desktop\tkinter.py", line 26, in switch
self.x.config(text = 'Farenheight:')
AttributeError: 'NoneType' object has no attribute 'config'
The problem comes from the fact that you assigned the x and z attributes (self.x, self.z) not to the tkinter labels but to whatever the Tkinter.Label.grid() function returns, which is None.
Instead, separate the declaration of the label and their grid configuration onto two lines that first declares the variables and then calls the grid function on them, thereby assigning x and z to the labels themselves.
from tkinter import *
bool1 = True
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.x = Label(frame, text = 'Celcius:')
self.x.grid(row = 0, column = 0)
self.c_var = DoubleVar()
Entry(frame, textvariable = self.c_var).grid(row = 0, column = 1)
self.z = Label(frame, text = 'Farenheight:')
self.z.grid(row = 1, column = 0)
self.result_var = DoubleVar()
Label(frame, textvariable = self.result_var).grid(row = 1, column = 1)
b1 = Button(frame, text = 'Switch', command = self.switch)
b1.grid(row = 2, columnspan = 2)
button = Button(frame, text = 'Convert', command = self.convert)
button.grid(row = 3, columnspan = 2)
return None
def convert(self):
c = self.c_var.get()
c = c * (9/5) + 32
self.result_var.set(c)
def switch(self):
global bool1
if bool1 == True:
bool1 = False
self.x.config(text = 'Farenheight:')
else:
bool1 = True
self.z['text'] = 'Celcius:'
root = Tk()
root.wm_title('Temp Converter')
app = App(root)
root.mainloop()

Categories