Counter über einen Taster hochzählen lassen

Fragen zu Tkinter.
Antworten
The_Cartman
User
Beiträge: 1
Registriert: Mittwoch 24. Februar 2021, 18:32

Hallo liebe Forumgemeinde,

Ich bin neu was die Sachen Programmierungen angeht. Ich weis mein Problem gibt es mehrere Lösungsansätze und ich würde auch nicht schreiben wenn ich nicht langsam am Ende wäre.

Kurzer Ausflug über mein Projekt: Ich möchte die alte Münzzählmaschine meines Dads wieder in Gang bringen. Dies funktioniert über eine Lichtschranke für die jeweilige Münze, sortiert wird rein mechanisch (im Endeffekt auch egal) ich bin schon soweit gekommen das ich meinen Zähler aufaddieren lasse und ihn auch in dem richtigen Format mit "print" anzeigen lasse, allerdings möchte ich das auch noch gerne über ein Display das das ganze Grafisch anzeigt wie viel von jeder Münze gezählt wurde inklusive den Wert in Euro.

Ich habe mal zum Test zwei Spalten erstellt und versucht meine "Counter" anzeigen zu lassen aber ich bekomme es einfach nicht gebacken.

Das der Raspberry für diese "einfache" Aufgabe auch völlig überdimensioniert ist weis ich auch aber ich habe einfach Spaß am basteln aber beim "Programm" schreiben bin ich einfach nicht so gut.

Ich möchte hier keine Bilderbuchlösung ich habe mir schon alles etwas zusammegfrickelt und bräuchte vielleicht nur einen Denkanstoß da ich mich mit meinem Problem schon über 2 Wochen beschäftige.

Meine Lichtschranken habe ich als Button verwendet weil ich so am einfachsten zurecht komme. Die "pressed" und "hold" Thematik kommt daher das bei "pressed" addiert wird und bei "hold" soll die Maschine aufhören zu sortieren da es sonst zu einem Stau auf der Münzrutsche kommt, daher auch die kurze hold.time von 0.2.

Die Led's dienen aktuell nur dazu um die Zustände (pressed und hold) sichtbar zu machen.

Beste Grüße
Alex

Code: Alles auswählen

import time
from gpiozero import Button, LED
from signal import pause
from tkinter import Frame, Label, Tk, Text

root = Tk()
root.wm_title("Münzzähler") 
root.config(background = "black") 
root.geometry('1024x600')
root.resizable(width=0, height=0)

counter = 0
counter2 = counter 

was_held = False

white = LED(15)
red = LED(21)
btn = Button(14, hold_time=0.2)

def count():
    global counter
    global counter2
    counter += 1
    counter2 = counter * 0.5
    print ('0.50 Euro: {a:8.2f}'.format(a=counter2), counter)


def held():
    global was_held
    was_held = True
    red.on()

def released():
    (white.off(), red.off())
    global was_held
    if not was_held:
        pressed()
        white.off()
    was_held = False

def pressed():
    white.on()
    count()

Frame1 = Frame(root)
Frame1.grid(row=1, column=1, padx=12, pady=5)

Label1 = Label(Frame1, text='   Anzahl   ')
Label1.grid(row=1, column=0, padx=12, pady=5, sticky='e')
Label2 = Label(Frame1, textvariable=counter)
Label2.grid(row=2, column=0, padx=15, pady=5, sticky='e')



Frame2 = Frame(root)
Frame2.grid(row=1, column=2, padx=12, pady=5)

Label1 = Label(Frame2, text='     Währung     ')
Label1.grid(row=1, column=0, padx=15, pady=5, sticky='e')
Label2 = Label(Frame2, textvariable=counter2)
Label2.grid(row=2, column=0, padx=15, pady=5, sticky='w')



btn.when_held = held
btn.when_released = released




root.mainloop()

pause()
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Benutze keine Abkürzungen, wenn Du lichtschranke meinst, nenne es nicht btn.
Vergiss gleich wieder, dass es global gibt, alles was eine Funktion braucht, muß sie über ihre Argumente bekommen.
counter und counter2 müssen IntVar-Objekte sein, weil Du sie ja unten als textvariable benutzen willst.
Ausführbarer Code auf oberster muß in eine Funktion wandern. das pause am Schluß ist unsinnig, da mainloop ja schon den Programmfluß aufhält.
In `released` erzeugst Du ein Tuple, mit dem Du dann nichts machst. Warum?

Code: Alles auswählen

import time
from gpiozero import Button, LED
from tkinter import Frame, Label, Tk, Text, IntVar
from functools import partial

def count(counter, counter2):
    amount = counter.get() + 1
    counter.set(amount)
    counter2.set(amount * 0.5)
    print('0.50 Euro: {a:8.2f}'.format(a=counter2.get()), counter)

def held(red):
    red.on()

def released(white, red, counter, counter2):
    white.off()
    red.off()
    white.on()
    count(counter, counter2)
    white.off()


def main():
    white = LED(15)
    red = LED(21)
    lichtschranke = Button(14, hold_time=0.2)

    root = Tk()
    root.wm_title("Münzzähler") 
    root.config(background = "black") 
    root.geometry('1024x600')
    root.resizable(width=0, height=0)

    counter = IntVar(root)
    counter2 = IntVar(root)

    frame1 = Frame(root)
    frame1.grid(row=1, column=1, padx=12, pady=5)
    Label(frame1, text='   Anzahl   ').grid(row=1, column=0, padx=12, pady=5, sticky='e')
    Label(frame1, textvariable=counter).grid(row=2, column=0, padx=15, pady=5, sticky='e')

    frame2 = Frame(root)
    frame2.grid(row=1, column=2, padx=12, pady=5)
    Label(frame2, text='     Währung     ').grid(row=1, column=0, padx=15, pady=5, sticky='e')
    Label(frame2, textvariable=counter2).grid(row=2, column=0, padx=15, pady=5, sticky='w')

    lichtschranke.when_held = partial(held, red)
    lichtschranke.when_released = partial(released, white, red, counter, counter2)
    root.mainloop()

if __name__ == "__main__":
    main()
Benutzeravatar
__blackjack__
User
Beiträge: 12984
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das mag ”funktionieren” aber hier wird der Zustand vom Tcl/Tk-Interpreter von verschiedenen Threads aus gleichzeitig verändert, der ist aber nicht thread-sicher. `IntVar` & Co sind ja im Grunde GUI-Code und die Rückrufe der `when_*`-Attribute erfolgen aus einem anderen Thread. Da müsste man also noch die übliche Queue + `after()` einbauen wenn man das thread-sicher haben will.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Natürlich, Button ist ja kein tkinter.Button, sondern ein gpiozero.Button.
Macht die Sache auch noch deutlich übersichtlicher:

Code: Alles auswählen

import time
from gpiozero import Button, LED
from tkinter import Frame, Label, Tk, Text, IntVar
from queue import Queue
from functools import partial

def held(queue):
    queue.put("held")

def released(queue):
    queue.put("release")

def count(counter, counter2):
    amount = counter.get() + 1
    counter.set(amount)
    counter2.set(amount * 0.5)
    print('0.50 Euro: {a:8.2f}'.format(a=counter2.get()), counter)

def update(root, queue, white, red, counter, counter2):
    while not queue.empty():
        if queue.get() == "hold":
            red.on()
        else:
            white.off()
            red.off()
            white.on()
            count(counter, counter2)
            white.off()
    root.after(100, update, root, queue, white, red, counter, counter2)

def main():
    queue = Queue()
    white = LED(15)
    red = LED(21)
    lichtschranke = Button(14, hold_time=0.2)
    lichtschranke.when_held = partial(held, queue)
    lichtschranke.when_released = partial(released, queue)

    root = Tk()
    root.wm_title("Münzzähler") 
    root.config(background = "black") 
    root.geometry('1024x600')
    root.resizable(width=0, height=0)

    counter = IntVar(root)
    counter2 = IntVar(root)

    frame1 = Frame(root)
    frame1.grid(row=1, column=1, padx=12, pady=5)
    Label(frame1, text='   Anzahl   ').grid(row=1, column=0, padx=12, pady=5, sticky='e')
    Label(frame1, textvariable=counter).grid(row=2, column=0, padx=15, pady=5, sticky='e')

    frame2 = Frame(root)
    frame2.grid(row=1, column=2, padx=12, pady=5)
    Label(frame2, text='     Währung     ').grid(row=1, column=0, padx=15, pady=5, sticky='e')
    Label(frame2, textvariable=counter2).grid(row=2, column=0, padx=15, pady=5, sticky='w')

    root.after(100, update, root, queue, white, red, counter, counter2)
    root.mainloop()

if __name__ == "__main__":
    main()
Antworten