I'm trying to make et Game of life with tkinter. The matrix of the game is a canvas which every cell is a square (white = dead and green = alive).
I wanted to do some multithreading to avoid a too long process time when the matrix is big. But when I'm trying to modify the square color from the threads the window in not responding and I can't solve this problem. I tried a lot of things like putting a common lock in every thread when they are modifying the canvas but it's not working either.
Does someone have ideas to solve this problem or even why this appends?
Thanks by advance
Here's my code :
import tkinter as tk
import threading
import random
from functools import partial
class MainFrame(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
x_coord = int(self.winfo_screenwidth() / 2) - 600
y_coord = int(self.winfo_screenheight() / 2 - 390)
self.geometry("{}x{}+{}+{}".format(1200, 750, x_coord, y_coord))
"""Graphique elements"""
# Labels
self.labelcountgen = tk.Label(self, text="Generation 0", font=("Arial", 9))
self.labelcountgen.grid(row=0, column=1)
"""Graphique data"""
self.graphiquematrice = tk.Canvas(self, height=740, width=1000, bg='white')
self.windimention = [1200, 750]
self.generation = 100
"""Matrice"""
self.matrice = []
self.firstquarter = []
self.secondquarter = []
self.thirdquarter = []
self.fourthquarter = []
self.newmatrice = []
self.cellids = []
self.dimention = [70, 100]
self.density = 15
self.scale = 10
self.initmatrice()
self.launchtime()
"""Init Methodes"""
def initmatrice(self):
"""
initialisation du premier etat de la matrice
"""
self.dimention = [80, 100]
self.matrice = []
self.cellids = []
self.graphiquematrice.grid(row=1, column=1, rowspan=10)
for line in range(self.dimention[0]):
self.matrice.append([])
self.cellids.append([])
for col in range(self.dimention[1]):
chance = random.randrange(1, 100, 1)
if chance <= self.density:
self.matrice[line].append(1)
self.cellids[line].append(self.graphiquematrice.create_rectangle(col*self.scale, line*self.scale, (col+1)*self.scale, (line+1)*self.scale, outline='black', fill='green'))
else:
self.matrice[line].append(0)
self.cellids[line].append(self.graphiquematrice.create_rectangle(col*self.scale, line*self.scale, (col+1)*self.scale, (line+1)*self.scale, outline='black', fill='white'))
self.graphiquematrice.tag_bind(self.cellids[line][col], '<Button-1>', partial(self.changestateonclick, self.cellids[line][col]))
"""Calcul Next generation"""
def launchtime(self):
for i in range(self.generation):
self.labelcountgen.config(text="Generation " + str(i + 1))
self.evolve()
self.update()
def getneighboor(self, coord):
neighboor = []
for i in range(3):
lineindex = coord[0] + i - 1
if lineindex == -1:
lineindex = self.dimention[0] - 1
elif lineindex == self.dimention[0]:
lineindex = 0
for j in range(3):
colindex = coord[1] + j - 1
if colindex == -1:
colindex = self.dimention[1] - 1
elif colindex == self.dimention[1]:
colindex = 0
if lineindex != coord[0] or colindex != coord[1]:
neighboor.append(self.matrice[lineindex][colindex])
return neighboor
def nextcellstate(self, coord):
state = self.matrice[coord[0]][coord[1]]
neighboor = self.getneighboor(coord)
alive = 0
dead = 0
for one in neighboor:
if one == 0:
dead += 1
else:
alive += 1
if alive == 3:
return 1
elif alive == 2:
return state
else:
return 0
def nextfirstquarterstate(self, quarter, lock):
self.firstquarter = []
start = 0
for line in range(quarter):
self.firstquarter.append([])
for col in range(self.dimention[1]):
self.firstquarter[line].append(self.nextcellstate([line, col]))
with lock:
if self.firstquarter[line][col] == 0:
self.graphiquematrice.itemconfig(self.cellids[line][col], fill='white')
else:
self.graphiquematrice.itemconfig(self.cellids[line][col], fill='green')
def nextsecondquarterstate(self, quarter, lock):
self.secondquarter = []
start = quarter
for line in range(quarter):
self.secondquarter.append([])
for col in range(self.dimention[1]):
self.secondquarter[line].append(self.nextcellstate([line + start, col]))
with lock:
if self.secondquarter[line][col] == 0:
self.graphiquematrice.itemconfig(self.cellids[line][col], fill='white')
else:
self.graphiquematrice.itemconfig(self.cellids[line][col], fill='green')
def nextthirdquarterstate(self, quarter, lock):
self.thirdquarter = []
start = quarter * 2
for line in range(quarter):
self.thirdquarter.append([])
for col in range(self.dimention[1]):
self.thirdquarter[line].append(self.nextcellstate([line + start, col]))
with lock:
if self.thirdquarter[line][col] == 0:
self.graphiquematrice.itemconfig(self.cellids[line + start][col], fill='white')
else:
self.graphiquematrice.itemconfig(self.cellids[line + start][col], fill='green')
def nextfourthquarterstate(self, quarter, lock):
self.fourthquarter = []
start = quarter * 3
for line in range(quarter):
self.fourthquarter.append([])
for col in range(self.dimention[1]):
self.fourthquarter[line].append(self.nextcellstate([start + line, col]))
with lock:
if self.firstquarter[line][col] == 0:
self.graphiquematrice.itemconfig(self.cellids[start + line][col], fill='white')
else:
self.graphiquematrice.itemconfig(self.cellids[start + line][col], fill='green')
def evolve(self):
self.newmatrice = []
threads = []
lock = threading.Lock()
quarter = int(self.dimention[0] / 4) # Division de la matrice en 4 pour reduire le temps de calcul
threads.append(threading.Thread(target=self.nextfirstquarterstate, args=(quarter, lock))) # Premier quart
threads.append(threading.Thread(target=self.nextsecondquarterstate, args=(quarter, lock))) # Deuxieme quart
threads.append(threading.Thread(target=self.nextthirdquarterstate, args=(quarter, lock))) # 3eme quart
threads.append(threading.Thread(target=self.nextfourthquarterstate, args=(quarter, lock))) # 4eme quart
i = 0
for t in threads:
t.setDaemon(True)
try:
t.start() # Lancement des 4 threads
except:
print("Error: not able to lauch thread " + str(i))
i += 1
for t in threads:
t.join() # Attente de la fin de tous les calculs
self.matrice = self.firstquarter + self.secondquarter + self.thirdquarter + self.fourthquarter
"""Binding Methodes"""
def changestateonclick(self, idcell, event):
color = self.graphiquematrice.itemcget(idcell, 'fill')
if color == 'white':
self.graphiquematrice.itemconfig(idcell, fill='green')
else:
self.graphiquematrice.itemconfig(idcell, fill='white')
if __name__ == '__main__':
root = MainFrame()
root.mainloop()
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?
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?
I am a fairly novice programmer and through coffee, google, and an immense loss of hair and fingernails have managed to write a very messy code. I am asking anyone to help me simplify the code if possible.
from tkinter import ttk
from tkinter import *
from tkinter.ttk import *
one = 0
why = 'Total Number: {}'
no = 0
clack = 0
click = 'Clicks: {}'
s = ttk.Style()
s.theme_use('clam')
s.configure('red.Vertical.TProgressbar', foreground = 'red', background = 'red')
s.configure('green.Vertical.TProgressbar', foreground = 'green', background = 'green')
s.configure('TButton', relief = 'groove')
def iround(x):
y = round(x) - .5
return int(y) + (y > 0)
class Application(ttk.Frame):
def __init__(self, master = None):
ttk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
def Number(self):
global one
cost = 10*(self.w['to'])
if self.number['text'] == "Make Number go up":
self.number['text'] = one
if iround(self.w.get()) == 0:
one += 1
else:
one += iround(self.w.get())
self.number['text'] = one
if self.number['text'] >= cost:
self.buy['state'] = 'normal'
else:
self.buy['state'] = 'disabled'
self.number['text'] >= cost
self.progress['value'] = one
if self.number['text'] >= cost:
self.progress['style'] = 'red.Vertical.TProgressbar'
else:
self.progress['style'] = 'green.Vertical.TProgressbar'
def Buy(self):
global one
self.w['to'] += 1
cost = 10*(self.w['to'])
one = self.number['text'] = (one + 10 - cost)
self.buy['text'] = ('+1 to slider | Cost: {}'.format(cost))
if self.number['text'] < (cost):
self.buy['state'] = 'disabled'
self.progress['value'] = one
self.progress['maximum'] += 10
if self.number['text'] >= cost:
self.progress['style'] = 'red.Vertical.TProgressbar'
else:
self.progress['style'] = 'green.Vertical.TProgressbar'
def scaleValue(self, event):
self.v['text'] = 'Slider Bonus + ' + str(iround(self.w.get()))
def clicks(self, event):
global click
global clack
if self.Clicks['text'] == 'Clicks: 0':
clack += 1
self.Clicks['text'] = click.format(clack)
self.Clicks['text'] = click.format(clack)
clack += 1
def NumberVal(self, event):
global why
global no
if self.fun['text'] == "Total Number: 0":
self.fun['text'] = why.format(no)
if iround(self.w.get()) == 0:
no += 1
else:
no += iround(self.w.get())
self.fun['text'] = why.format(no)
def createWidgets(self):
self.number = Button(self, text = 'Make number go up', command = self.Number, width = 20, style = 'TButton')
self.number.grid(row = 1, column = 1)
self.number.bind('<ButtonRelease>', self.clicks, add = '+')
self.number.bind('<ButtonRelease>', self.NumberVal, add = '+')
self.buy = Button(self, text = '+1 to Slider | Cost: 10', command = self.Buy, width = 20, style = 'TButton')
self.buy.grid(row = 2, column = 1)
self.buy.config(state = 'disabled')
self.v = Label(self, text = 'Slider Bonus + 0', width = 20, anchor = 'center')
self.v.grid(row = 3, column = 3)
self.w = Scale(self, from_ = 0, to = 1, orient = 'horizontal')
self.w.grid(row = 3, column = 1)
self.w.bind('<Motion>', self.scaleValue)
self.progress = Progressbar(self, value = 0, orient = 'vertical', maximum = 10, mode = 'determinate')
self.progress.grid(row = 1, rowspan = 5, column = 2)
self.Clicks = Label(self, text = 'Clicks: 0', width = 20, anchor = 'center')
self.Clicks.grid(row = 1, column = 3)
self.fun = Label(self, text = 'Total Number: 0', width = 20, anchor = 'center')
self.fun.grid(row = 2, column = 3)
app = Application()
app.master.title('Number')
app.mainloop()
At first, I was suggested to differentiate between two codes under the name operation..so, I change the self.operation into self.operation1. After that I get another error self.operatio1_pending and I was suggested to introduce the self.operation_pending in init(). However I still get another error.
Here is the written codes with a hashtags to let you know where I have done the changes (and I added operation="" in init() since it gave me an error for not defined) Note: I also changed all self.operation in different methods into self.operation1.
from Tkinter import*
class Calculator():
def __init__ (self):
self.total = 0
self.current = ""
self.newnumber = True
self.operation1 = ""#
self.operation1_pending = False#
operation = ""#
self.equal = False
def PressedNumber(self, number):
self.equal = False
t = text_box.get()
n = str(number)
if self.newnumber:
self.current = n
self.newnumber = False
else:
if n == '.':
if n in t:
return
self.current = t + n
self.Display(self.current)
def TotalCalculated(self):
self.equal = True
self.current = float(self.current)
if self.operation1_pending == True:
self.calc_sum()
else:
self.total = float(text_box.get())
def Display(self, value):
text_box.delete(0, END)
text_box.insert(0, value)
def calc_sum(self):
if self.operation1 == "subtract":
self.total -= self.current
if self.operation1 == "add":
self.total += self.current
if self.operation1 == "divide":
self.total /= self.current
if self.operation1 == "multiply":
self.total *= self.current
self.newnumber = True
self.operation1_pending = False
self.Display(self.total)
def operation(self, operation1):
self.current = float(self.current)
if self.operation1_pending:
self.calc_sum()
elif not self.equal:
self.total = self.current
self.newnumber = True
self.operation1_pending = True
self.operation1 = operation
self.equal = False
def cancel(self):
self.equal = False
self.current = "0"
self.Display(0)
self.newnumber = True
def Cancelation_forEverything(self):
self.cancel()
self.total = 0
def sign(self):
self.equal = False
self.current = -(float(text_box.get()))
self.Display(self.current)
summ = Calculator()
root = Tk()
Calculator = Frame(root)
Calculator.grid()
root.title("Calculator")
root.configure(bg="Khaki")
root.minsize(width=220, height=20)
root.resizable(width=FALSE, height= FALSE)
text_box = Entry(Calculator, justify=RIGHT)
text_box.grid(row = 0, column = 0, columnspan=3, pady = 8, sticky=W+E)
text_box.insert(0, "0")
Numbers = "789456123"
a = 0
bttn = []
for r in range(1,4):
for c in range(3):
bttn.append(Button(Calculator, text = Numbers[a], font="Candara,20"))
bttn[a].grid(row = r, column = c, padx= 15, pady = 15)
bttn[a]["command"] = lambda x = Numbers[a]: summ.PressedNumber(x)
a += 1
bttn_0 = Button(Calculator, text = " 0 ", font="Candara,20")
bttn_0["command"] = lambda: summ.PressedNumber(0)
bttn_0.grid(columnspan = 5, sticky=N+W, padx= 20, pady = 20)
bttn_division = Button(Calculator, text = chr(247), font="Candara,20")
bttn_division["command"] = lambda: summ.operation("divide")
bttn_division.grid(row = 1, column = 3, pady = 10)
bttn_multiply = Button(Calculator, text = "x", font="Candara,20")
bttn_multiply["command"] = lambda: summ.operation("multiply")
bttn_multiply.grid(row = 2, column = 3, sticky=N, pady = 10)
bttn_subtract = Button(Calculator, text = "-", font="Candara,20")
bttn_subtract["command"] = lambda: summ.operation("subtract")
bttn_subtract.grid(row = 3, column = 3, pady = 10)
bttn_point = Button(Calculator, text = ".", font="Candara,20")
bttn_point["command"] = lambda: summ.PressedNumber(".")
bttn_point.grid(row = 4, column = 1, padx = 10, pady = 10)
bttn_addition = Button(Calculator, text = "+", font="Candara,20")
bttn_addition["command"] = lambda: summ.operation("add")
bttn_addition.grid(row = 4, column = 3, pady = 10)
bttn_neg = Button(Calculator, text = "+/-", font="Candara,20")
bttn_neg["command"] = summ.sign
bttn_neg.grid(row = 5, column = 0, pady = 10)
clear = Button(Calculator, text = "C", font="Candara,20")
clear["command"] = summ.cancel
clear.grid(row = 5, column = 1, pady = 10)
all_clear = Button(Calculator, text = "AC", font="Candara,20")
all_clear["command"] = summ.Cancelation_forEverything
all_clear.grid(row = 5, column = 2, pady = 10)
equals = Button(Calculator, text = "=", font="Candara,20")
equals["command"] = summ.TotalCalculated
equals.grid(row = 5, column = 3, pady = 10)
root.mainloop()
And here is the error message I now get:
Exception in Tkinter callback
Traceback (most recent call last):
File "Q:\Python.001\lib\lib-tk\Tkinter.py", line 1403, in __call__
return self.func(*args)
File "\\centre-fsrv07\SSHome$\352767933\Grade 10 CS\Working progress\Tkinter\Calculator4.py", line 110, in <lambda>
bttn_multiply["command"] = lambda: summ.operation("multiply")
File "\\centre-fsrv07\SSHome$\352767933\Grade 10 CS\Working progress\Tkinter\Calculator4.py", line 60, in operation
self.operation1 = operation
NameError: global name 'operation' is not defined
Please help me with what I need to change with fully explanation and codes...If you know other ways to get the calculator work without the given codes please suggest them and I'll be grateful.
From your code:
def operation(self, operation1):
self.current = float(self.current)
if self.operation1_pending:
self.calc_sum()
elif not self.equal:
self.total = self.current
self.newnumber = True
self.operation1_pending = True
self.operation1 = operation # <-- You mean operation1
self.equal = False
Change
self.operation1 = operation
To
self.operation1 = operation1
To reflect your method's parameter.