tkinter - A toplevel class getting a value from the main/parent class? - python

Below is a program that solves quadratic equations and graphs them. I was wondering what i needed to put where the comment is located in the code in order to get a value a parent class (quadratics) and use it in a Toplevel class. Any help would be appreciated.
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
from tkinter import *
class home():
def __init__(self,master):
self.master = master
self.master.geometry('400x450')
self.master.title('Mathsolver')
Button(self.master, text='Quadratics', command = self.open_quadratics).pack()
def open_quadratics(self):
quadratics(Toplevel(self.master))
class quadratics():
def __init__(self, master):
self.master = master
self.vara = DoubleVar()
self.varb = DoubleVar()
self.varc = DoubleVar()
self.master.geometry("500x300")
self.master.title("Quadratic Equations")
Label(self.master, text="Enter coefficients of x below in the form ax² + bx + c = 0").grid(row=1,column=1)
Label(self.master, text="a:").grid(row=2,column=1)
Entry(self.master, textvariable = self.vara).grid(row=2,column=2)
Label(self.master, text="b:").grid(row=3,column=1)
Entry(self.master, textvariable = self.varb).grid(row=3,column=2)
Label(self.master, text="c:").grid(row=4,column=1)
Entry(self.master, textvariable = self.varc).grid(row=4,column=2)
Button(self.master, text="Solve", command = self.calculate_quadratic).grid(row=5,column=2)
Button(self.master, text='Graph', command = self.grapher, bg='green').grid(row=5,column=2)
def grapher(self):
quadratic_grapher(Toplevel(self.master))
def calculate_quadratic(self):
global x
a = self.vara.get()
b = self.varb.get()
c = self.varc.get()
mp = (-b) / 2 * a
y = a * mp**2 + b * mp + c
d = b**2-4*a*c
if d < 0:
Label(self.master, text="No Solution for %.0fx² + %.0fx + %.0f = 0" % (a, b, c,)).grid(row=6,column=1)
elif d == 0:
x = (-b+d**0.5/2*a)
Label(self.master, text="One Solution for %.0fx² + %.0fx + %.0f = 0" % (a, b, c,)).grid(row=7,column=1)
Label(self.master, text="x= %f" % x).grid(row=8,column=1)
else:
x1 = ((-b)+(((b*b)-(4*a*c))**0.5))/(2*a)
x2 = ((-b)-(((b*b)-(4*a*c))**0.5))/(2*a)
Label(self.master, text="Two Solutions for %.0fx² + %.0fx + %.0f = 0:" % (a, b, c)).grid(row=9,column=1)
Label(self.master, text="x = %f" % x1).grid(row=10,column=1)
Label(self.master, text="x = %f" % x2).grid(row=11,column=1)
Label(self.master, text="Line of Symmetry: x = %f" % mp).grid(row=12,column=1)
Label(self.master, text="Vertex = (%f, %f)" % (mp, y)).grid(row=13,column=1)
class quadratic_grapher(quadratics):
def __init__(self, master):
self.master = master
self.a_coefficient = #what needs to be here to get the vara, varb and varc values in the quadratics class?
self.b_coefficient =
self.c_coefficient =
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
self.x1 = []
self.y1 = []
self.x2 = []
self.y2 = []
self.x_positive_increment = 1
self.x_negative_decrement = -1
self.x_positive = 0
self.x_negative = 0
for plotPoints in range(0, 10):
self.y_positive = self.a_coefficient * self.x_positive**2 + self.b_coefficient * self.x_positive + self.c_coefficient
self.y_negative = self.a_coefficient * self.x_negative**2 + self.b_coefficient * self.x_negative + self.c_coefficient
self.x1.append(self.x_positive)
self.x2.append(self.x_negative)
self.y1.append(self.y_positive)
self.y2.append(self.y_negative)
self.x_positive = self.x_positive + self.x_positive_increment
self.x_negative = self.x_negative + self.x_negative_decrement
a.plot(self.x1, self.y1)
a.plot(self.x2, self.y2)
self.canvas = FigureCanvasTkAgg(f, master=master)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, master )
self.toolbar.update()
self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
def main():
root = Tk()
home(root)
root.mainloop()
if __name__ == '__main__':
main()

Unlike some other languages - python does not automatically call the constructor of the super classes, so you will need your quadratic_grapher class to explicitly call the constructor of the quadratics class :
Put this on the first line of your init method of your quadratic_grapher class
super(quadratic_grapher, self).__init__(master)
and now - since quadratic_grapher is also an instance of quadratic you can access the variables just by using self - so your commented lines become :
self.a_coefficient = self.vara
self.b_coefficient = self.varb
self.c_coefficient = self.varc

Related

How to select a color in Tkinter?

I have a program written in Python, that makes a window where you can draw, using Tkinter. Every time you left-click your mouse, you make a point in your canvas. When you double-click, a polygon is made, filled with the color you chose. I found a way to change the colors from the boxes, when you right-click a box, but the problem is that the selected color is not saved and i cannot make it replace the previous one. Does anyone know how to solve this problem?
import tkinter as tk
from tkinter import colorchooser
class Point():
def __init__(self, canvas, x, y):
self.x = x
self.y = y
canvas.create_oval(x-2, y-2, x+2, y+2, fill='white')
class Poly():
def __init__(self, canvas, board, p_list=[] ):
self.p_list = p_list
self.canvas = canvas
self.board = board
def draw_poly(self):
points = []
for p in self.p_list:
points.extend([p.x, p.y])
points.extend(points[:2])
self.canvas.create_polygon(points, fill=self.board.current_color, outline=self.board.current_color)
def add_point(self, p):
self.p_list.append(p)
if len(self.p_list)>1:
p1 = self.p_list[-1]
p2 = self.p_list[-2]
self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill="white", width=2)
class Palette():
def __init__(self, frame, board, colors):
self.colors = colors
self.board = board
self.allColors = []
for color in self.colors:
f = tk.Frame(frame, bg='lightgrey', bd=3)
f.pack(expand=1, fill='both', side='left')
if self.board.current_color == color: f.config(bg='red')
self.allColors.append(f)
l = tk.Label(f, bg=color)
l.pack(expand=1, fill='both', padx=2, pady=2)
l.bind("<1>", self.set_color)
l.bind("<Button-3>", self.do_popup)
def do_popup(self, event):
clsheet = tk.colorchooser.askcolor()
self.current_color = clsheet[1]
def set_color(self, e):
self.board.current_color = e.widget['bg']
self.selected_color(e.widget.master)
def selected_color(self, colorFrame):
for f in self.allColors: f.config(bg = 'lightgrey')
colorFrame.config(bg="red")
class Board():
def __init__(self, root):
self.colors = ['#B4FE98', '#77E4D4', '#F4EEA9', '#F0BB62', '#FF5F7E', "#9A0680"]
self.root = root
self.current_color = self.colors[0]
self.f1 = tk.Frame(self.root)
self.f1.pack(expand=1, fill='both', padx=5)
self.f2 = tk.Frame(self.root)
self.f2.pack(expand=1, fill='both')
self.canvas = tk.Canvas(self.f2, bg="#000D6B", height=550)
self.canvas.pack(expand=1, fill='both', padx=5, pady=5)
self.pallette = Palette(self.f1, self, self.colors )
self.canvas.bind("<1>", self.draw_point)
self.canvas.bind("<Double-Button-1>", self.draw_poly)
self.poly = None
def draw_point(self, evnt):
if self.poly: self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
else: self.poly = Poly(self.canvas, self, [Point(self.canvas, evnt.x, evnt.y)])
def draw_poly(self, evnt):
if self.poly and len(self.poly.p_list) > 2:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
self.poly.draw_poly()
self.poly = None
else: self.draw_point(evnt)
#main program
root = tk.Tk()
root.title('my program')
root.geometry("600x700")
root.resizable(0,0)
Board(root)
tk.mainloop()
To fix the part where right-clicking a color was not working i changed two things in your script:
You stored your frame widgets and their sub-widget labels in Palette.allColors. I handed over the index of the selected color to the do_popup event by using partial. Then you can simply iterate over all widgets in Palette.allColors and if the index from the event matches the index in the list, you access the children and further the !label key of those and change the background color to the selected color.
I matched Board.current_color and Palette.current_color
Most changes were made in Palette.do_popup(). Might not be the most elegant solution but it looks like its working like you intend. Full code:
import tkinter as tk
from tkinter import colorchooser
from functools import partial
class Point():
def __init__(self, canvas, x, y):
self.x = x
self.y = y
canvas.create_oval(x - 2, y - 2, x + 2, y + 2, fill='white')
class Poly():
def __init__(self, canvas, board, p_list=[]):
self.p_list = p_list
self.canvas = canvas
self.board = board
def draw_poly(self):
points = []
for p in self.p_list:
points.extend([p.x, p.y])
points.extend(points[:2])
self.canvas.create_polygon(points, fill=self.board.current_color, outline=self.board.current_color)
def add_point(self, p):
self.p_list.append(p)
if len(self.p_list) > 1:
p1 = self.p_list[-1]
p2 = self.p_list[-2]
self.canvas.create_line(p1.x, p1.y, p2.x, p2.y, fill="white", width=2)
class Palette():
def __init__(self, frame, board, colors):
self.colors = colors
self.board = board
self.allColors = []
for idx, color in enumerate(self.colors):
f = tk.Frame(frame, bg='lightgrey', bd=3)
f.pack(expand=1, fill='both', side='left')
if self.board.current_color == color: f.config(bg='red')
self.allColors.append(f)
l = tk.Label(f, bg=color)
l.pack(expand=1, fill='both', padx=2, pady=2)
l.bind("<1>", self.set_color)
l.bind("<Button-3>", partial(self.do_popup, idx))
def do_popup(self, idx, event):
clsheet = tk.colorchooser.askcolor()
self.current_color = clsheet[1].upper()
print(f"You chose: {self.current_color}")
self.board.current_color = self.current_color # required?
self.selected_color(event.widget.master)
for frm_idx, frm in enumerate(self.allColors):
if frm_idx == idx:
frm.children["!label"].config(bg=self.current_color)
def set_color(self, e):
self.board.current_color = e.widget['bg']
self.selected_color(e.widget.master)
def selected_color(self, colorFrame):
for f in self.allColors: f.config(bg='lightgrey')
colorFrame.config(bg="red")
class Board():
def __init__(self, root):
self.colors = ['#B4FE98', '#77E4D4', '#F4EEA9', '#F0BB62', '#FF5F7E', "#9A0680"]
self.root = root
self.current_color = self.colors[0]
self.f1 = tk.Frame(self.root)
self.f1.pack(expand=1, fill='both', padx=5)
self.f2 = tk.Frame(self.root)
self.f2.pack(expand=1, fill='both')
self.canvas = tk.Canvas(self.f2, bg="#000D6B", height=550)
self.canvas.pack(expand=1, fill='both', padx=5, pady=5)
self.pallette = Palette(self.f1, self, self.colors)
self.canvas.bind("<1>", self.draw_point)
self.canvas.bind("<Double-Button-1>", self.draw_poly)
self.poly = None
def draw_point(self, evnt):
if self.poly:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
else:
self.poly = Poly(self.canvas, self, [Point(self.canvas, evnt.x, evnt.y)])
def draw_poly(self, evnt):
if self.poly and len(self.poly.p_list) > 2:
self.poly.add_point(Point(self.canvas, evnt.x, evnt.y))
self.poly.draw_poly()
self.poly = None
else:
self.draw_point(evnt)
# main program
root = tk.Tk()
root.title('my program')
root.geometry("600x700")
root.resizable(0, 0)
Board(root)
tk.mainloop()

How can I fix Attribute error in python for real time plotting in GUI?

My aim to is to plot real time data coming from Arduino to a GUI in python. I have developed everything required for it. I want to see some of the values, so defined labels accordingly to display varying input data beside the plotting. I did around 3, but the aim is to do 9 values. But when I try to include the 4th one, am getting an Attribute error.
import copy
from threading import Thread
from tkinter import Frame
import tkinter as Tk
import tkinter.font
import serial
import time
import collections
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import struct
from PIL import ImageTk
from PIL import Image
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from tkinter import Text
import math
import pandas as pd
A=0
B=0
C=0
D=0
Sum = 0
Az = 0
El = 0
angle = 0
ang = 0
Ang = 0
Ta = 0
Tb = 0
Va = 0
Vb = 0
cond = False
class serialPlot:
def __init__(self, serialPort='com7', serialBaud=38400, plotLength=100, dataNumBytes=4, numPlots=9):
self.port = serialPort
self.baud = serialBaud
self.plotMaxLength = plotLength
self.dataNumBytes = dataNumBytes
self.numPlots = numPlots
self.rawData = bytearray(numPlots * dataNumBytes)
self.dataType = None
if dataNumBytes == 2:
self.dataType = 'h' # 2 byte integer
elif dataNumBytes == 4:
self.dataType = 'f' # 4 byte float
self.data = []
self.privateData = None # for storing a copy of the data so all plots are synchronized
for i in range(numPlots): # give an array for each type of data and store them in a list
self.data.append(collections.deque([0] * plotLength, maxlen=plotLength))
self.isRun = True
self.isReceiving = False
self.thread = None
self.plotTimer = 0
self.previousTimer = 0
self.started = False
self.csvData = []
print('Trying to connect to: ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
try:
self.serialConnection = serial.Serial(serialPort, serialBaud, timeout=4)
print('Connected to ' + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
except:
print("Failed to connect with " + str(serialPort) + ' at ' + str(serialBaud) + ' BAUD.')
def readSerialStart(self):
if self.thread == None:
self.thread = Thread(target=self.backgroundThread)
self.thread.start()
# Block till we start receiving values
while self.isReceiving != True:
time.sleep(0.1)
def getSerialData(self, frame, lines, lineValueText, lineLabel, timeText, pltNumber):
global cond
if cond == True:
# if pltNumber == 0: # in order to make all the clocks show the same reading
if not self.started:
currentTimer = time.perf_counter()
self.plotTimer = int((currentTimer - self.previousTimer) * 1000) # the first reading will be erroneous
self.previousTimer = currentTimer
self.started = True
self.privateData = copy.deepcopy(
self.rawData) # so that the 4 values in our plots will be synchronized to the same sample time
timeText.set_text('Plot Interval = ' + str(self.plotTimer) + 'ms')
data = self.privateData[(pltNumber * self.dataNumBytes):(self.dataNumBytes + pltNumber * self.dataNumBytes)]
value, = (struct.unpack(self.dataType, (data)))
self.data[pltNumber].append(value) # we get the latest data point and append it to our array
lines.set_data(range(self.plotMaxLength), self.data[pltNumber])
lineValueText.set_text('[' + lineLabel + '] = ' + str(value))
# self.csvData.append([self.data[0][-1], self.data[1][-1], self.data[2][-1]])
if lineLabel == 'Detector A':
global A
A = float(value)
if lineLabel == 'Detector B':
global B
B = float(value)
if lineLabel == 'Detector C':
global C
C = float(value)
if lineLabel == 'Detector D':
global D
D = float(value)
if lineLabel == 'Temp Detector':
global Ta
Ta = float(value)
if lineLabel == 'Temp Servo':
global Tb
Tb = float(value)
if lineLabel == 'Voltage Servo':
global Va
Va = float(value)
if lineLabel == 'Voltage Detector':
global Vb
Vb = float(value)
if lineLabel == 'Angle':
global Ang
Ang = float(value)
Sum = (A + B + C + D)
Az = (A + D - C - B)
El = (A + B - C - D)
def backgroundThread(self): # retrieve data
time.sleep(0.8) # give some buffer time for retrieving data
self.serialConnection.reset_input_buffer()
while (self.isRun):
self.serialConnection.readinto(self.rawData)
self.isReceiving = True
def Sum(self):
global A, B, C, D
return '%.6f' % (A + B + C + D)
def Az(self):
global A, B, C, D
return '%.6f' % (A - B - C + D)
def El(self):
global A, B, C, D
return '%.6f' % (A + B - C - D)
def A(self):
global A
return '%.6f' % (A)
def B(self):
global B
return '%.6f' % (B)
def C(self):
global C
return '%.6f' % (C)
def D(self):
global D
return '%.6f' % (D)
def Ang(self):
global Ang
return '%.6f' % (Ang)
def TA(self):
global Ta
return '%.6f' % (Ta)
def TB(self):
global Tb
return '%.6f' % (Tb)
def VA(self):
global Va
return '%.6f' % (Va)
def VB(self):
global Vb
return '%.6f' % (Vb)
''''
def m1(self):
x = A - B - C + D
y = A + B - C - D
if x > 0 and y > 0:
angle = math.degrees(math.atan(y / x))
elif (x < 0 and y > 0) or (x < 0 and y < 0):
angle = math.degrees(math.atan(y / x)) + 180
elif x > 0 and y < 0:
angle = math.degrees(math.atan(y / x)) + 360
elif x == 0:
angle = 0
return int(angle)
def m1(self):
angle=0
global A,B,C,D
x = A-B-C+D
y = A+B-C-D
if x > 0 and y > 0:
angle = math.degrees(math.atan(y / x))
elif (x < 0 and y > 0) or (x < 0 and y < 0):
angle = math.degrees(math.atan(y / x)) + 180
elif x > 0 and y < 0:
angle = math.degrees(math.atan(y / x)) + 360
elif x==0:
angle=0
return angle
def m2(self):
angle1=0
global A,B,C,D
x1 = math.log10((A + D) / (B + C))
y1 = math.log10((A + B) / (D + C))
if x1==0 or (B+C)==0 or (D+C)==0:
angle1=0
elif x1 > 0 and y1 > 0:
angle1 = math.degrees(math.atan(y1 / x1))
elif (x1 < 0 and y1 > 0) or (x1 < 0 and y1 < 0):
angle1 = math.degrees(math.atan(y1 / x1)) + 180
elif x1 > 0 and y1 < 0:
angle1 = math.degrees(math.atan(y1 / x1)) + 360
return angle1
'''''
def close(self):
self.isRun = False
self.thread.join()
self.serialConnection.close()
print('Disconnected...')
# df = pd.DataFrame(self.csvData)
# df.to_csv('/home/Abhinav Kumar/Desktop/data.csv')
def plot_start():
global cond
cond = True
def plot_stop():
global cond
cond = False
def makeFigure(xLimit, yLimit, title):
xmin, xmax = xLimit
ymin, ymax = yLimit
fig = plt.figure(dpi=100)
fig.set_figheight = 1
fig.set_figwidth = 3
ax = plt.axes(xlim=(xmin, xmax), ylim=(int(ymin - (ymax - ymin) / 10), int(ymax + (ymax - ymin) / 10)))
ax.set_title(title)
ax.set_xlabel("Time")
ax.set_ylabel("Detector Output")
ax.grid(True)
return fig, ax
class Window(Frame):
def __init__(self, flist, master, SerialReference):
Frame.__init__(self, master)
self.entry = None
self.setPoint = None
self.master = master # a reference to the master window
self.serialReference = SerialReference # keep a reference to our serial connection so that we can use it for bi-directional communicate from this class
self.initWindow(flist) # initialize the window with our settings
def initWindow(self, flist):
self.master.title("Detector Data")
p = {1: [50, 120], 2: [480, 120], 3: [900, 120], 4: [50, 430], 5: [480, 430], 6: [900, 430], 7: [50, 750],
8: [480, 750], 9: [900, 750]}
x = 1
for item in flist:
canvas = FigureCanvasTkAgg(item, master=self.master)
# toolbar = NavigationToolbar2TkAgg(canvas, self.master)
canvas.get_tk_widget().place(x=p[x][0], y=p[x][1], width=400, height=300)
canvas.draw()
x += 1
def main():
portName = 'COM7'
# portName = '/dev/ttyUSB0'
baudRate = 38400
maxPlotLength = 100 # number of points in x-axis of real time plot
dataNumBytes = 4 # number of bytes of 1 data point
numPlots = 9 # number of plots in 1 graph
s = serialPlot(portName, baudRate, maxPlotLength, dataNumBytes, numPlots) # initializes all required variables
s.readSerialStart() # starts background thread
# plotting starts below
pltInterval = 1 # Period at which the plot animation updates [ms]
lineLabelText = ['Detector A', 'Detector B', 'Detector C', 'Detector D', 'Temp Detector', 'Temp Servo',
'Voltage Servo', 'Volatge detector', 'Angle']
title = ['Detector A', 'Detector B', 'Detector C', 'Detector D', 'Temp Detector', 'Temp Servo', 'Voltage Servo',
'Volatge detector', 'Angle']
xLimit = [(0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength),
(0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength), (0, maxPlotLength)]
yLimit = [(0, 3), (0, 3), (0, 3), (0, 3), (0, 60), (0, 60), (0, 8), (0, 8), (-120, 120)]
style = ['r-', 'g-', 'b-', 'y-', 'r-', 'g-', 'b-', 'y-', 'r-'] # linestyles for the different plots
# anim = []
root = Tk.Tk()
image = Image.open("kalyani(3).gif")
test = ImageTk.PhotoImage(image)
label = Tk.Label(image=test)
label.image = test
label.place(x=25, y=25)
image = Image.open("a.gif")
test = ImageTk.PhotoImage(image)
label = Tk.Label(image=test)
label.image = test
label.place(x=1350, y=40)
image = Image.open("b.gif")
test = ImageTk.PhotoImage(image)
label = Tk.Label(image=test)
label.image = test
label.place(x=1650, y=40)
image = Image.open("c.gif")
test = ImageTk.PhotoImage(image)
label = Tk.Label(image=test)
label.image = test
label.place(x=1400, y=170)
root.configure(background='light blue')
# root.geometry('1920x1080')
w = Tk.Label(root, text="LASER SEEKER GUI", fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="Arial Bold", size=40, weight='bold')
w.configure(font=desired_font)
w.pack(pady=15)
labelf = Tk.Label(root, text='A:', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
labelf.configure(font=desired_font)
labelf.place(x=1350, y=450)
label4 = Tk.Label(root, text='ELE', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
label4.configure(font=desired_font)
label4.place(x=1500, y=450)
def a():
label4.config(text=s.A())
root.after(1, a)
a()
labels = Tk.Label(root, text='SUM:', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
labels.configure(font=desired_font)
labels.place(x=1350, y=300)
label1 = Tk.Label(root, text='SUM', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
label1.configure(font=desired_font)
label1.place(x=1500, y=300)
def sum():
label1.config(text=s.Sum())
root.after(1, sum)
sum()
labela = Tk.Label(root, text='AZ:', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
labela.configure(font=desired_font)
labela.place(x=1350, y=350)
label2 = Tk.Label(root, text='AZ', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
label2.configure(font=desired_font)
label2.place(x=1500, y=350)
def az():
label2.config(text=s.Az())
root.after(1, az)
az()
labele = Tk.Label(root, text='ELE:', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
labele.configure(font=desired_font)
labele.place(x=1350, y=400)
label3 = Tk.Label(root, text='ELE', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
label3.configure(font=desired_font)
label3.place(x=1500, y=400)
def el():
label3.config(text=s.El())
root.after(1, el)
el()
start = Tk.Button(root, width=10, height=3, activebackground='green', fg='black', text="START",
font=('calibri', 12), command=lambda: plot_start())
start.place(x=1800, y=600)
# root.update();
stop = Tk.Button(root, width=10, height=3, activebackground='red', text="STOP", fg='black', font=('calibri', 12),
command=lambda: plot_stop())
stop.place(x=1800, y=700)
# root.update()
exit = Tk.Button(root, width=10, height=3, activebackground='yellow', fg='black', text="EXIT", font=('calibri', 12),
command=root.destroy)
exit.place(x=1800, y=900)
flist = []
axlist = []
a = []
b = []
c = []
anim = []
for i in range(9):
fig, ax = makeFigure(xLimit[i], yLimit[i], title[i])
lines = ax.plot([], [], style[i], label=lineLabelText[i])[0]
timeText = ax.text(0.40, 0.95, '', transform=ax.transAxes)
lineValueText = ax.text(0.40, 0.90, '', transform=ax.transAxes)
flist.append(fig)
axlist.append(axlist)
a.append(lines)
b.append(timeText)
c.append(lineValueText)
app = Window(flist, root, s)
for i in range(9):
anim.append(animation.FuncAnimation(flist[i], s.getSerialData, frames=200,
fargs=(a[i], c[i], lineLabelText[i], b[i], i),
interval=pltInterval)) # fargs has to be a tuple
# plt.legend(loc="upper left")
# plt.show()
root.mainloop()
s.close()
if __name__ == '__main__':
main()
Am getting error for the A label. How do I solve this? Thanks in advance.
The error is happening for this part of code:
labelf = Tk.Label(root, text='A:', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
labelf.configure(font=desired_font)
labelf.place(x=1350, y=450)
label4 = Tk.Label(root, text='ELE', fg='black', bg='light blue')
desired_font = tkinter.font.Font(family="calibri", size=25, weight='bold')
label4.configure(font=desired_font)
label4.place(x=1500, y=450)
def a():
label4.config(text=s.A())
root.after(1, a)
a()
And the traceback is this:
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 814, in callit
func(*args)
File "C:\Users\Abhinav Kumar\PycharmProjects\realtimemultiple\Nag2.py", line 351, in a
root.after(1, a)
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 820, in after
callit.__name__ = func.__name__
AttributeError: 'list' object has no attribute '__name__'
When you do this:
def a():
label4.config(text=s.A())
root.after(1, a) a()
You defined a as an function that is callable to your interpreter.
But later in your code you define a as a list that isn't callable.
a = []
So you basically have overwritten your variable and you try to access the older content of that variable which isn't possible. So when you do this:
a = 1
a = 2
then a will become 2 and 1 is gone except you would resign it to 1.
Got it?

Python Tkinter & matplotlib - RuntimeError

Okay so I wrote this code...
#!/usr/bin/env
import sys
import time
import subprocess
from Tkinter import *
import numpy
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import matplotlib.pyplot as plt
import threading
CDatei = subprocess.Popen("/home/pi/meinc++/Spi")
print("Hallo")
i = 0
x = 0
def GetValue():
with open("/home/pi/meinc++/BeispielDatei.txt","r") as Datei:
for line in Datei:
time.sleep(0.01)
return line
def WithoutNull(input):
ReturnValue = input
while ReturnValue is None:
ReturnValue = GetValue()
return ReturnValue
def UebergabeWert():
while x == 0:
WholeString = WithoutNull(GetValue())
StringVar, DatumVar = WholeString.strip().split(' - ')
IntStringVar = [int(v) for v in StringVar.split()]
return IntStringVar, DatumVar
def MinutenWert():
Maximum = 0
Minimum = 0
i = 0
LaengeArray = 0
Multiplikator = 10000
ArrayValue = [-999999]*Multiplikator
AlteZeit = time.time()
while 1:
CompleteValue, Trash = UebergabeWert()
ArrayValue[i] = CompleteValue[0]
i = i + 1
ArrayFilter = filter(lambda c: c != -999999,ArrayValue)
ArraySumme = numpy.sum(ArrayFilter)
LaengeArray = len(ArrayFilter)
Mittelwert = ArraySumme/LaengeArray
ArraySortierung = sorted(ArrayFilter)
Maximum = ArraySortierung[LaengeArray-1]
Minimum = ArraySortierung[0]
NeueZeit = time.time()
if NeueZeit-AlteZeit >= 60:
AlteZeit = time.time()
ArrayValue[i:Multiplikator] = [-999999]*(Multiplikator-i)
i = 0
yield Mittelwert
yield Maximum
yield Minimum
yield LaengeArray
yield ArrayFilter
def UebergabeTkinter():
while 1:
Mittelwert = next(MinutenWertYield)
Maximum = next(MinutenWertYield)
Minimum = next(MinutenWertYield)
LaengeArray = next(MinutenWertYield)
ArrayFilter = next(MinutenWertYield)
CompleteValue, DatumVar = UebergabeWert()
Variable1.set(CompleteValue[0])
Variable2.set(CompleteValue[1])
Variable3.set(CompleteValue[2])
Variable4.set(CompleteValue[3])
VariableMittelwert.set(Mittelwert)
VariableMaximum.set(Maximum)
VariableMinimum.set(Minimum)
t = threading.Thread(target = Grafik)
t.start()
root.update()
def Grafik():
GrafikAnfang = time.time()
Array = 0
ArrayGrafik = [0]*20
GrafikEnde = 1
while 1:
CompleteValue, DatumVar = UebergabeWert()
ArrayGrafik[Array] = CompleteValue[0]
LaengeArrayGrafik = len(ArrayGrafik)
fig = Figure(figsize = (3, 3))
axis = fig.add_subplot(111)
axis.legend()
axis.grid()
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.get_tk_widget().grid(row=10,column=0,rowspan=2,columnspan=2)
LinienBreite = numpy.linspace(1,LaengeArrayGrafik,LaengeArrayGrafik)
axis.plot(LinienBreite,ArrayGrafik,'b-')
axis.set_xticks(LinienBreite)
DatumArray = [DatumVar]
axis.set_xticklabels(DatumArray)
canvas.draw()
fig.clear()
print Array
if GrafikEnde-GrafikAnfang < 600:
Array = Array + 1
GrafikEnde = time.time()
if GrafikEnde-GrafikAnfang >= 600:
del ArrayGrafik[0]
def Exit():
root.destroy()
return
try:
MinutenWertYield = MinutenWert()
root = Tk()
Leiste = Menu(root)
root.config(menu = Leiste)
DateiMenu = Menu(Leiste)
Leiste.add_cascade(label = "datei", menu = DateiMenu)
DateiMenu.add_command(label = "Exit", command = Exit)
EditMenu = Menu(Leiste)
Leiste.add_cascade(label = "edit", menu = EditMenu)
Variable1 = IntVar()
Variable2 = IntVar()
Variable3 = IntVar()
Variable4 = IntVar()
VariableMittelwert = IntVar()
VariableMaximum = IntVar()
VariableMinimum = IntVar()
Ausgang = 0
for column in range(0,8,2):
String1 = "Ausgang "
String1 += `Ausgang`
Ausgang = Ausgang + 1
Label(text = String1).grid(row=0,column=column)
Ausgang = 0
for column in range(0,8,2):
String1 = "Der Wert von "
String2 = " ist: "
String1 += `Ausgang`
Ausgang = Ausgang + 1
String3 = String1+String2
Label(text = String3).grid(row=2,column=column)
Label(text = "Der Mittelwert ist: ").grid(row=4,column=0)
Label(text = "Das Maximum ist: ").grid(row=5,column=0)
Label(text = "Das Mimimum ist: ").grid(row=6,column=0)
Label1 = Label(root, textvariable = Variable1)
Label1.grid(row = 2, column = 1)
Label2 = Label(root, textvariable = Variable2)
Label2.grid(row = 2, column = 3)
Label3 = Label(root, textvariable = Variable3)
Label3.grid(row = 2, column = 5)
Label4 = Label(root, textvariable = Variable4)
Label4.grid(row = 2, column = 7)
LabelMittelwert = Label(root, textvariable = VariableMittelwert)
LabelMittelwert.grid(row = 4, column = 1)
LabelMaximum = Label(root, textvariable = VariableMaximum)
LabelMaximum.grid(row = 5, column = 1)
LabelMinimum = Label(root, textvariable = VariableMinimum)
LabelMinimum.grid(row = 6, column = 1)
UebergabeTkinter()
print "Hallo"
root.mainloop()
except KeyboardInterrupt:
CDatei.kill()
root.quit()
root.destroy()
and when i run it, it says "RuntimeError: main thread is not in the main loop".
Short explanation of the code: It's a code to read out sensor data from a text file -
GetValue().
If the Data is Null it'll read out again - WithoutNull().
The Data is then splitted into data and timestamp (cause it has the format val1, val2, val3, val4, time) - UebergabeWert.
Then the maxima, minima and average of the data will be measured - MinutenWert()
After this, the values are set as labels and go their way into Tkinter - UebergabeTkinter()
The Tkinter build is mainly in Try:
What I wanted to do there, is to implement a graph to Tkinter, but because of the fast changing values it got tremendously slow so i decided to put the graph build in a thread and run it parallel to Tkinter. Unfortunately, it doesn't seem to work and I don't know why
Any suggestions?

Why does my canvas image disappear even though I keep a reference?

The idea is to have the user click on the color bar and the entry field on the left will get a number from 0 to 100 entered for the user. The problem is the color bar image is blanked, even though I try to keep a reference to it so that it doesn't get garbage collected.
import Tkinter as Tk
class Test(Tk.Frame):
'''Test color bar for user input'''
def __init__(self, parent):
Tk.Frame.__init__(self, parent)
photo_color_bar_01 = Tk.PhotoImage(file = 'color_bar_blue_to_red_020.GIF')
pic_width = photo_color_bar_01.width()
pic_height = photo_color_bar_01.height()
shift_x_01 = 0 # 10
shift_y_01 = 0 # 10
pic_width_plus_border = pic_width + shift_x_01
pic_height_plus_border = pic_height + shift_y_01
x_center = (pic_width_plus_border) / 2.0
y_center = (pic_height_plus_border) / 2.0
My_Labels = ["Input_One", "Input_Two", "Input_Three", "Input_Four"]
Labels = []
variables = []
entrys = []
pic_frames = []
canvases = []
label_row = 0
entry_row = 1
for index in range(len(My_Labels)):
Labels.append(Tk.Label(root, text=My_Labels[index]))
Labels[-1].grid(padx=0, pady=0, row=label_row, column=0)
variables.append(Tk.StringVar())
entrys.append(Tk.Entry(root, textvariable =variables[index]))
entrys[-1].grid(padx=0, pady=0, row=entry_row, column=0)
entrys[-1].delete(0, Tk.END)
entrys[-1].insert(0, "50.00")
pic_frames.append(Tk.Frame(root, bd=4, relief=Tk.RAISED))
pic_frames[-1].grid(padx=0, pady=0, row=entry_row, column=2)
canvases.append(Tk.Canvas(pic_frames[-1], width=pic_width, height=pic_height))
canvases[-1].create_image(x_center, y_center, image=photo_color_bar_01, anchor = Tk.CENTER)
# keep a reference
# http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm
canvases[-1].image = photo_color_bar_01 # keep a reference
canvases[-1].config(cursor="X_cursor")
canvases[-1].grid(padx=0, pady=0, row=entry_row, column=3)
canvases[-1].bind("<ButtonPress-1>", lambda event, arg=index: self.pick_LMB(event, index))
canvases[-1].bind("<ButtonPress-2>", self.pick_MMB)
label_row += 2
entry_row += 2
def pick_LMB(self, event, index):
print "\nindex = " + str(index)
canvas = event.widget
x = canvas.canvasx(event.x)
width_x = 180.0
scaled_x = x/width_x * 100.0
print "scaled_x = " + '{0:.2f}'.format(scaled_x)
#entrys[index].delete(0, Tk.END)
#entrys[index].insert(0, '{0:.2f}'.format(scaled_x))
def pick_MMB(self, event):
canvas = event.widget
x = canvas.canvasx(event.x)
print "\nx = " + str(x)
width_x = 180.0
scaled_x = x/width_x * 100.0
print "scaled_x = " + '{0:.2f}'.format(scaled_x)
if __name__ == "__main__":
root = Tk.Tk()
Test(root)
root.mainloop()
I forgot the .create_image command, so it wasn't a problem with the reference after all.

Python Tkinter layout using pack()

I am new to Tkinter. I'd like to write simple program and organize it using pack() method. Here is my code:
import Tkinter as tk
from Tkinter import *
import xlrd, os, sys, json
class Main():
def __init__(self):
global col, col1
self.master = tk.Tk()
self.master.title("Zliczanie ilosci spraw")
self.master.minsize(width=800, height=600)
plik = 'Aktualnie wybrany plik to: ' + 'Rejestr'
text = Label(self.master, text = plik)
text.pack(pady = 20)
self.wyswietlanie()
def wyswietlanie(self):
'''Funkcja, ktora zlicza i wyswietla ilosc spraw pracownikow'''
policzone_1 = []
policzone_2 = []
z = 0
dzial1 = {
"Pracownik1": "PRAC1",
"Pracownik2": "PRAC2"}
dzial2 = {
"Pracownik12": "PRAC12",
"Pracownik22": "PRAC22"}
for nazw in dzial1:
x = dzial1[nazw] #nazwisko z pliku excela
nazwisko = 0
policzone_1.append((nazw, nazwisko))
for nazw in dzial2:
x = dzial2[nazw] #nazwisko z pliku excela
nazwisko = 0
policzone_2.append((nazw, nazwisko))
posortowane1 = sorted(policzone_1,key=lambda x:x[1], reverse=True)
posortowane2 = sorted(policzone_2,key=lambda x:x[1], reverse=True)
dzial3 = Label(self.master)
dzial3.pack(side = LEFT)
dzial4 = Label(self.master)
dzial4.pack(side = LEFT)
for i in posortowane1:
wynik = '%s: %s' % (i[0], i[1])
dzial1 = Label(self.master, text = wynik, font = "Verdana 10 bold")
dzial1.pack(in_ = dzial3, padx = 200)
for i in posortowane2:
wynik = '%s: %s' % (i[0], i[1])
dzial2 = Label(self.master, text = wynik)
dzial2.pack(in_ = dzial4, padx = 200)
def run(self):
self.master.mainloop()
glowne = Main()
glowne.run()
Result is as on image below:
Why dzial1 and dzial2 are in these places (far from "text")? How can I organize dzial1, dzial2 (set them closer to each other)?

Categories

Resources