Tkinter stalling due to keyboard.is_pressed function, maybe threading? - python

I'm new to the code and I'm experiencing with tkinter, and I'm making a money counter with tkinter and to make it happen on screen i need to make a Label change it's text properties form one text to another one with a button, the problem is that it works on console, but when I try to make it change on tkinter it freezes and doesn't change. The parts I'm talking about are, the ones highlighted with (----code----).
I know that the problem concerns threading, due to the fact that the programs runs when I remove the keyboard.is_pressed, but i don't actually know how to implement it.
from tkinter import *
import keyboard
import sys
import time
import winsound
raiz = Tk()
raiz.title("Contador de Divisas")
raiz.iconbitmap("MonedaContador.ico")
Total = 0
def contador_de_espacios(divisa, diccionario):
global lista
global Total
global posiciones_en_diccionario
Numero = ""
Contador = 0
Escape = 0
Cambiar = 0
Multiplicador = divisa * 5
Nombre = str(divisa)
suma_lista = 0
if divisa > 2:
Nombre = (" billetes de " + Nombre + " Euros.")
else:
Nombre = (" Monedas de " + Nombre + " Euro/s.")
eleccion.config(text = Nombre)----------------------------
while True:
if keyboard.is_pressed('space'):
Control = 0
Contador += 1
Numero = str(Contador)
Marcador.config(text = Numero)-------------------------------
winsound.Beep(2500, 200)
time.sleep(0.25)
def clasificador_de_divisa(boton):
global posiciones_en_lista
posicion = posiciones_en_lista.get(str(boton))
contador_de_espacios(boton, posicion)
myframe = Frame()
myframe.pack()
myframe.config(width = "650", height = "350")
explicacion = Label(myframe, text = "Esto es un contador de divisas en euros. Por cada grupo de 5 monedas/billetes le das una vez al espacio, cosa que añadirá 1 monton de 5 monedas/billetes al contador.")
explicacion.grid(row = 0, column = 0, padx = 10, pady = 30, columnspan = 9)
explicacion.config(font = (30))
eleccion = Label(myframe)--------------------------------------
eleccion.grid(row = 1, column = 2, padx = 10, pady = 30, columnspan = 5)
eleccion.config(font = (30))
Marcador = Label(myframe, text = "0")
Marcador.grid(row = 2, column = 3, pady = 30, columnspan = 3, rowspan = 1)
Marcador.config(font=("Arial",100), bg = "black", fg = "white")
boton1euro = Button(myframe, text = "1 Euro", width = 10, command = lambda:clasificador_de_divisa(1))
boton1euro.grid(row = 3, column = 0, padx = 10, pady = 30)
raiz.mainloop()
The expected output is the program changing the Label, but it doesn't and freezes.

Related

Write text into canvas python tkinter

I have all the gui configurations and all that stuff in my main.py and my algorithms to draw bubble sort and merge sort in another .py file. I'm trying to write the print functions into my canvas but I'm not sure how to do it, can anyone help? I tried using a ListBox() but it messes up the main canvas for some reason.
This is my code for my main file:
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from bubbleSort import bubbleSort
from mergeSort import mergeSort
tk = Tk()
tk.title('Examen Final')
tk.maxsize(900, 600)
tk.config(bg = 'black')
algoritmo = StringVar()
data = []
def dibujar(data, color):
c.delete("all")
cHeight = 380
cWidth = 600
algoWidth = cWidth / (len(data) + 1)
algoHeight = cWidth / (len(data) + 1)
offset = 20
spacing = 10
tamData = [i / max(data) for i in data]
for i, height in enumerate(tamData):
x0 = i * algoWidth + offset + spacing
y0 = cHeight - height * 50
x1 = (i+1) * algoWidth + offset
y1 = cHeight
c.create_oval(x0,y0,x1,y1, fill = color[i])
c.create_text(x0+2,y0, anchor = SW, text=str(data[i]))
tk.update_idletasks()
def Ordenar():
print("Se selecciono: " + algoritmo.get())
print("Iniciando algoritmo")
global data
if menu.get() == 'MERGE SORT':
mergeSort(data, dibujar)
elif menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar)
dibujar(data, ['green' for x in range(len(data))])
def agregar():
global data
input = int(inputVal.get())
inputVal.delete(0, END)
try:
print("valor input:")
print(input)
data.append((input))
print(str(data))
dibujar(data, ['red' for x in range(len(data))])
except:
messagebox.showerror("Error", "Ingrese un valor numerico")
def limpiar():
global data
data = []
c.delete("all")
print(data)
box = Frame(tk, width = 600, height = 200, bg = 'black' )
box.grid(row = 0, column = 0, padx=10, pady=5)
c = Canvas(tk, width = 600, height = 380, bg = 'grey')
c.grid(row = 1, column = 0, padx=10, pady=5)
c2 = Canvas(tk, width = 200, height = 380, bg = 'grey')
c2.grid(row = 1, column = 1, padx=10, pady=5)
label = Label(box, text='Lista Algoritmos: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=0,column=0, padx=5, pady=5, sticky = W)
menu = ttk.Combobox(box, textvariable = algoritmo, values=['BUBBLE SORT', 'MERGE SORT', 'HASH TABLES', 'ARBOL AVL', 'ARBOLES ROJO Y NEGRO'])
menu.grid(row=0, column=1, padx=5, pady=5)
menu.current(0)
botonStart = Button(box, text = 'Ordenar', command = Ordenar, bg = 'lime green')
botonStart.grid(row = 0, column = 2, padx = 5, pady = 5)
label = Label(box, text='Insertar valor: ', font = ("Arial",15), borderwidth=1, bg = "black" , fg = 'white')
label.grid(row=1,column=0, padx = 5, pady = 5, sticky = W)
inputVal = Entry(box)
inputVal.grid(row=1,column=1, padx = 5, pady = 5, sticky = W)
botonAdd = Button(box, text = 'Agregar', command = agregar, bg = 'lime green')
botonAdd.grid(row = 1, column = 2, padx = 5, pady = 5, sticky = W)
botonClear = Button(box, text = 'Limpiar', command = limpiar, bg = 'lime green')
botonClear.grid(row = 1, column = 3, padx = 5, pady = 5, sticky = W)
tk.mainloop()
and this is my bubbleSort.py
import time
def bubbleSort(data, dibujar):
for _ in range(len(data)-1):
for j in range(len(data)-1):
if data[j] > data[j+1]:
print(("El numero " + str(data[j]) + " es mayor que " + str(data[j+1])))
data[j],data[j+1] = data[j+1], data[j]
print(("Intercambiando de lugar " + str(data[j]) + " con " + str(data[j+1])))
dibujar(data,
[
'green'
if x == j or x == j+1
else 'red' for x in range(len(data))
]
)
time.sleep(1)
dibujar(data, ['green' for x in range(len(data))])
You can just pass in c2 to the function on the other file. So first define the parameter:
def bubbleSort(data, dibujar, cnv):
cnv.create_text(100,100,text='Trial Text')
....
Now each time you call this function, pass on c2 to it.
if menu.get() == 'BUBBLE SORT':
bubbleSort(data, dibujar, c2)
I did notice that you are using dynamic points for calculation, if so, make those points global, inside the function, then pass those onto the function by creating more parameter, while keeping in mind that the points have to defined before the function is called.

Game of life: I want to change some things

def next_turn():
global tab, tab2, x, y, test
test = test + 1
tab2 = [[0 for i in range(10)] for j in range(10)]
for y in range(10):
for x in range(10):
compter_cellules_voisines(y, x)
tab = tab2
adapte_dessin()
# Boutons sur la fenêtre pour faire un tour suivant sur la grille et pour nettoyer la grille
clr = Button(fen, text = 'Nettoyer le plateau', command = clear)
clr.pack(side = RIGHT, padx = 20, pady = 200)
etape = Button(fen, text = 'Tour suivant', command = next_turn)
etape.pack(side = RIGHT, padx = 10)
creation_lignes()
Canevas.bind('<Button-1>', Clic)
creer_tableau()
fen.mainloop()
I use this method for Game of Life but I would like to automatize the steps. I tried to change the next_step but it doesn't work.
Could you help me please?

Method requires self argument

I have this code right here, it's about a GUI app with Tkinter, pretty simple, but there is one error that I can't solve without breaking the code:
import tkinter as tk
class Sistema:
def __init__(self, g1 = 0, g2 = 0, g3 = 0, g4 = 0, media = 6):
self.g1 = g1
self.g2 = g2
self.g3 = g3
self.g4 = g4
self.media = media
resultCalc = (self.g1 + self.g2 + self.g3 + self.g4) / 4
self.resultCalc = resultCalc
Label_reply['text'] = Sistema.__str__()
def __str__(self):
if self.resultCalc < self.media:
return "Você não passou de ano! ╰(‵□′)╯"
elif self.resultCalc > self.media:
return "Você passou de ano!(~ ̄▽ ̄)~"
elif self.resultCalc == self.media:
return "Você passou de ano! Essa foi por pouco (。_。)"
else:
return "Erro fatal (╬▔皿▔)╯"
root = tk.Tk()
canvas = tk.Canvas(root, bg = "#159BA0", height = 500, width = 500)
canvas.pack()
Label1 = tk.Label(canvas, text = "Digite sua nota:")
Label1.place(x = 10,y = 10)
Entry1 = tk.Entry(canvas)
Entry1.place(x = 100,y = 10)
Label2 = tk.Label(canvas, text = "Digite sua nota:")
Label2.place(x = 10,y = 50)
Entry2 = tk.Entry(canvas)
Entry2.place(x = 100,y = 50)
Label3 = tk.Label(canvas, text = "Digite sua nota:")
Label3.place(x = 10, y = 90)
Entry3 = tk.Entry(canvas)
Entry3.place(x = 100, y = 90)
Label4 = tk.Label(canvas, text = "Digite sua nota:" )
Label4.place(x = 10, y = 130)
Entry4 = tk.Entry(canvas)
Entry4.place(x = 100, y = 130)
Label5 = tk.Label(canvas, text = "Média mínima: ")
Label5.place(x=10, y = 170)
Entry5 = tk.Entry(canvas)
Entry5.place(x=100, y = 170)
Button1 = tk.Button(canvas, text = "Enviar",
command = lambda : Sistema(float(Entry1.get()), float(Entry2.get()), float(Entry3.get()), float(Entry4.get()),
float(Entry5.get())))
Button1.place(x = 10, y = 210)
Label_reply = tk.Label(canvas)
Label_reply.place(x = 10, y = 240)
root.mainloop()
But, when I run it, it raises this exception:
TypeError: __str__() missing 1 required positional argument: 'self'
The error is at the 15 line.
I know what it means and why it happens, but I can't find a way to solve it without ruining the code, can someone help me?
Consider this line of code:
Label_reply['text'] = Sistema.__str__()
You are calling the __str__ method on the class rather than on an instance of the class. That is why it is asking for the self parameter.
I assume you want to call the __str__ method of the current object, which you can do by calling str(self):
Label_reply['text'] = str(self)
Delete this line:
Label_reply['text'] = Sistema.__str__()
This is an incorrect call to the __str__ function (it would need to be something more like str(self)), and it serves no purpose since there is no Label_reply within this scope anyway.
Instead, put the logic of updating Label_reply inside your command function:
Label_reply = tk.Label(canvas)
Label_reply.place(x = 10, y = 240)
def command():
s = Sistema(
float(Entry1.get()),
float(Entry2.get()),
float(Entry3.get()),
float(Entry4.get()),
float(Entry5.get())
)
Label_reply['text'] = str(s)
return s

How can i put data in the thinker entry from a loop (Python)

How can i use set() method or there is method to update data in widget. I get this error : AttributeError: 'Entry' object has no attribute 'set'
my example code:
from tkinter import *
Entradas = []
def convertir():
for entrada in Entradas:
print(float(entrada.get())/1024)
for entrada in Entradas:
entrada.set((float(entrada.get())/1024))
app= Tk()
app.resizable(0,0)
for i in range(3):
etiqueta = Label(app, text = "Numero " + str(i + 1) + " : ")
etiqueta.grid(row = i, column = 0, sticky = "w", padx = 5, pady = 5)
for i in range(3):
Numero = Entry(app, font = "Arial 8 bold")
Numero.grid(row = i, column = 1 , padx = 5, pady = 5)
Numero.config(justify="left", disabledforeground="white")
Entradas.append(Numero)
Button(app, text="Convertir", command=convertir,font = "Arial 10 bold").grid(row=3,column=0,padx=5,pady=5)
app.mainloop()
Thanks
You want to use insert() not set()
For entry fields you need specify the location as to where to insert the text and the text itself.
So instead of:
entrada.set((float(entrada.get())/1024))
Do this:
entrada.insert(0, (float(entrada.get())/1024))
Now if you want to make sure the entry field is cleared before your add text to it then you need to do this:
entrada.delete(0, "end")
entrada.insert(0, (float(entrada.get())/1024))

Plotting on python with matplotlib

I'm actually working on a schoolar project. We need to read and show the signals from 4 different sensors. I decided to make it using python instead matlab (simulink) because matlab doesn't recognize the raspberry pi 3. I already make a very simple guide whit Tkinter that read and show the values from sensor constantly and put it in a graph. The problem is that when I put the code to do the graphs it stops the refresh from the sensors and it shows the four values in one figure. The question(s) is(are):
How can I show the four values in four diferents graphs?
How can I make the refresh automatic?
How can in close all the figures using one button?
And if its possible can you tell me where can I found info to make more visual the graphics? How to customize de graphs.
Here is the code I have:
#IMPORTAR LIBRERIAS NECESARIAS
from Tkinter import *
from drawnow import *
import RPi.GPIO as GPIO
import matplotlib.pyplot as plt
import numpy
import tkFont
import time
import Adafruit_DHT
#Variables
trig = 16
echo = 18
pir = 15
distance = 0
distancia = 0
tiempo = 0
temp = 0
humd = 0
distanciaM = []
temperaturaM = []
presenciaM = []
humedadM = []
#DECLARAR ENTRADAS Y SALIDAS
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(trig, GPIO.OUT)
GPIO.setup(echo, GPIO.IN)
GPIO.setup(pir, GPIO.IN)
#VENTANAS
win = Tk()
plt.figure()
#TITULO DE LA VENTANA
win.title("Lectura sensores")
#DIMENSIONES DE INICIO
win.geometry('1050x500')
#FUENTES
myFont = tkFont.Font(family = 'Helvetica', size = 36)
titles = tkFont.Font(family = 'Helvetica', size = 50, weight = 'bold')
#FUNCIONES
##LEER SENSORES
def med():
###DISTANCIA
global distance
global distancia
global temp
global humd
GPIO.output(trig, False)
time.sleep(1)
GPIO.output(trig, True)
time.sleep(0.00001)
GPIO.output(trig, False)
while GPIO.input(echo)==0:
pulse_start = time.time()
while GPIO.input(echo)==1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
distance = pulse_duration * 17150
distance = round(distance, 2)
distancia.configure(text=str(distance))
distanciaM.append(str(distance))
print(distanciaM)
###PRESENCIA
i=GPIO.input(pir)
if i==1:
rb1.configure(text = str(i))
time.sleep(0.1)
else:
rb1.configure(text = str(i))
time.sleep(0.1)
presenciaM.append(str(i))
print (presenciaM)
###TEMPERATURA Y HUMEDAD
humidity, temperature = Adafruit_DHT.read_retry(11, 27)
temp = temperature
humd = humidity
templl.configure(text=str(temp))
humll.configure(text=str(humd))
temperaturaM.append(str(temp))
humedadM.append(str(humd))
print(temperaturaM)
print(humedadM)
###GRAFICAR
plt.plot(distanciaM, label ='Distancia','r')
plt.plot(presenciaM, label='Presencia', 'g')
plt.plot(temperaturaM, label='Temperatura', 'b')
plt.plot(humedadM, label='Humedad', 'y')
plt.show()
##LECTURA CONTINUA
def leccont():
med()
win.after(1000, leccont)
##SALIR DEL PROGRAMA
def exitProgram():
GPIO.cleanup()
win.quit()
#WIDGETS
##TITULO
titulo = Label(win, text="Lectura de cuatro sensores", font = titles)
titulo.grid(columnspan = 3)
##DISTANCIA
dist = Label(win, text = "Distancia:", font = myFont)
dist.grid(row = 1, column=0, sticky=W)
##ETIQUETA DISTANCIA
distancia = Label(win, text = "Distancia" , font=myFont)
distancia.grid(row=1, column=1)
##ETIQUETA UNIDADES DISTANCIA
cms=Label(win, text = "cms", font = myFont)
cms.grid(row = 1, column = 2)
##ETIQUETA PRESENCIA
pa=Label(win, text = "Presencia:", font = myFont)
pa.grid(row=2, column = 0, sticky=W)
##INDICADOR PRESENCIA
rb1 = Label(win, text = "No Presente", font = myFont)
rb1.grid(row = 2, column =1)
##TEMPERATURA
templ=Label(win, text="Temperatura:", font=myFont)
templ.grid(row=3,column=0,sticky=W)
##ETIQUETA TEMPERATURA
templl=Label(win, text="Temperatura", font=myFont)
templl.grid(row=3,column=1)
##ETIQUETA UNIDADES TEMPERATURA
tempu=Label(win, text = "C", font = myFont)
tempu.grid(row = 3, column = 2)
##HUMEDAD
huml=Label(win, text="Humedad relativa:", font=myFont)
huml.grid(row=4,column=0,sticky=W)
##ETIQUETA HUMEDAD
humll=Label(win, text="humedad", font=myFont)
humll.grid(row=4,column=1)
##ETIQUETA UNIDADES HUMEDAD
humu=Label(win, text = "HR", font = myFont)
humu.grid(row = 4, column = 2)
##MOSTRAR VALORES
medir=Button(win,text="Medir",font=myFont,command=med,height=1,width=6)
medir.grid(row=6,column=0)
##LECTURA CONTINUA
lecconti=Button(win, text="Medicion continua", font = myFont, command = leccont, height = 1, width = 15)
lecconti.grid(row = 6, column = 1)
##BOTON SALIR
exitButton = Button(win, text = "Salir", font = myFont, command = exitProgram, height = 1 , width = 6)
exitButton.grid(row = 6, column = 2)
mainloop()
I already solved it so here's the code:
# -*- coding: utf-8 -*-
#IMPORTAR LIBRERIAS NECESARIAS
from Tkinter import *
from drawnow import *
from matplotlib import style
import RPi.GPIO as GPIO
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy
import tkFont
import time
import Adafruit_DHT
#Variables
trig = 16
echo = 18
ldr = 15
distance = 0
distancia = 0
tiempo = 0
temp = 0
humd = 0
distanciaM = []
temperaturaM = []
resistenciaM = []
humedadM = []
style.use('fivethirtyeight')
#DECLARAR ENTRADAS Y SALIDAS
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
GPIO.setup(trig, GPIO.OUT)
GPIO.setup(echo, GPIO.IN)
GPIO.setup(ldr, GPIO.OUT)
#VENTANAS
win = Tk()
fig = plt.figure()
#TITULO DE LA VENTANA
win.title("Lectura sensores")
#DIMENSIONES DE INICIO
win.geometry('900x500')
#FUENTES
myFont = tkFont.Font(family = 'Helvetica', size = 36)
titles = tkFont.Font(family = 'Helvetica', size = 50, weight = 'bold')
#FUNCIONES
##LEER SENSORES
def med(i):
###DISTANCIA
global distance
global distancia
global temp
global humd
GPIO.output(trig, False)
time.sleep(1)
GPIO.output(trig, True)
time.sleep(0.00001)
GPIO.output(trig, False)
while GPIO.input(echo)==0:
pulse_start = time.time()
while GPIO.input(echo)==1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
distance = pulse_duration * 17150
distance = round(distance, 2)
distancia.configure(text=str(distance))
distanciaM.append(str(distance))
print(distanciaM)
###RESISTENCIA
count = 0
GPIO.setup(ldr, GPIO.OUT)
GPIO.output(ldr, GPIO.LOW)
time.sleep(0.1)
GPIO.setup(ldr, GPIO.IN)
while (GPIO.input(ldr) == GPIO.LOW):
count += 1
rb1.configure(text = str(count))
print count
resistenciaM.append(str(count))
print (resistenciaM)
###TEMPERATURA Y HUMEDAD
humidity, temperature = Adafruit_DHT.read_retry(11, 27)
temp = temperature
humd = humidity
templl.configure(text=str(temp))
humll.configure(text=str(humd))
temperaturaM.append(str(temp))
humedadM.append(str(humd))
print(temperaturaM)
print(humedadM)
###GRAFICAR
plt.plot(distanciaM, label ='Distancia',color='r')
plt.plot(resistenciaM, label='Resistencia', color='g')
plt.plot(temperaturaM, label='Temperatura', color='b')
plt.plot(humedadM, label='Humedad', color='k')
count = 0
##LECTURA CONTINUA
def leccont():
ani = animation.FuncAnimation(fig, med, interval=2000)
plt.legend()
plt.show()
win.after(1000, leccont)
##SALIR DEL PROGRAMA
def exitProgram():
GPIO.cleanup()
plt.close()
win.quit()
#WIDGETS
##TITULO
titulo = Label(win, text="Lectura de cuatro sensores", font = titles)
titulo.grid(columnspan = 3)
##DISTANCIA
dist = Label(win, text = "Distancia:", font = myFont)
dist.grid(row = 1, column=0, sticky=W)
##ETIQUETA DISTANCIA
distancia = Label(win, text = "Distancia" , font=myFont)
distancia.grid(row=1, column=1)
##ETIQUETA UNIDADES DISTANCIA
cms=Label(win, text = "Cms", font = myFont)
cms.grid(row = 1, column = 2)
##ETIQUETA RESISTENCIA
pa=Label(win, text = "Resistencia:", font = myFont)
pa.grid(row=2, column = 0, sticky=W)
##INDICADOR RESISTENCIA
rb1 = Label(win, text = "Resistencia", font = myFont)
rb1.grid(row = 2, column =1)
##ETIQUETA RESITENCIA
ohms=Label(win, text="Ohms", font = myFont)
ohms.grid(row=2, column = 2)
##TEMPERATURA
templ=Label(win, text="Temperatura:", font=myFont)
templ.grid(row=3,column=0,sticky=W)
##ETIQUETA TEMPERATURA
templl=Label(win, text="Temperatura", font=myFont)
templl.grid(row=3,column=1)
##ETIQUETA UNIDADES TEMPERATURA
tempu=Label(win, text = "C", font = myFont)
tempu.grid(row = 3, column = 2)
##HUMEDAD
huml=Label(win, text="Humedad relativa:", font=myFont)
huml.grid(row=4,column=0,sticky=W)
##ETIQUETA HUMEDAD
humll=Label(win, text="humedad", font=myFont)
humll.grid(row=4,column=1)
##ETIQUETA UNIDADES HUMEDAD
humu=Label(win, text = "HR", font = myFont)
humu.grid(row = 4, column = 2)
##LECTURA CONTINUA
lecconti=Button(win, text="Medicion", font = myFont, command = leccont, height = 1, width = 15)
lecconti.grid(row = 6, column = 0)
##BOTON SALIR
exitButton = Button(win, text = "Salir", font = myFont, command = exitProgram, height = 1 , width = 6)
exitButton.grid(row = 6, column = 2)
mainloop()

Categories