After Methode tkinter

Fragen zu Tkinter.
Antworten
SeesternMare
User
Beiträge: 6
Registriert: Dienstag 1. August 2017, 07:57

Hallo,


ich habe mal wieder ein Problem :C

Ich habe demletzt schon eine Frage gestellt. Da wurde mir eine "after" Methode vorgeschalgen. Ich habe mich da mal eingelsen und es mir so zusammen gebastelt:

Code: Alles auswählen

from tkinter import *
import RPi.GPIO as gpio
import time

Fenster=Tk()
Fenster.title("Auswertung")
pin1=7
pin2=8

def abfrage():
    global pin1
    global pin2
    global Test1
    global Test2
    global Test3
    global Test4
    print(Test1)

    if gpio.input(pin1) == prev_state:
        if prev_state == 1:
            Test1 = 1          
            if Test1 == 1 or Test1 == 2:
                Test2 = 1
                if Test2 == 1 or Test2 ==2:
                    Test3 = 1
                    if Test3 == 1 or Test3 == 2:
                        Test4 = 1
                        
 
    if gpio.input(pin2) == prev_state:
        if prev_state == 1:
            Test1 = 2          
            if Test1 == 1 or Test1 == 2:
                Test2 = 2
                if Test2 == 1 or Test2 == 2:
                    Test3 = 2
                    if Test3 == 1 or Test3 == 2:
                        Test4 = 2
   

    
    Fenster.after(1000, abfrage)
def Anzeige():                                                                                      
    Label(Fenster, text="Test1")
    if Test1 == 1:
        Label(Fenster, text="Bestanden")
    if Test1 == 2:
        Label(Fenster, text="Nicht bestanden")
    Label(Fenster, text="Test2")
    if Test2 == 1:
        Label(Fenster, text="Bestanden")
    if Test2 == 2:
        Label(Fesnter, text="Nicht bestanden")
    Label(Fenster, text="Test3")
    if Test3 == 1:
        Label(Fenster, text="Bestanden")
    if Test3 == 2:
        Label(Fenster, text="Nicht bestanden")
    Label(Fenster, text="Test4")
    if Test4 == 1:
        Label(Fenster, text="Bestanden")
    if Test4 == 2:
        Label(Fenster, text="Nicht bestanden")
    
    Fenster.pack()
    Fenster.after(0, abfrage)
    Fenster.mainloop()

Doch ich glaube ich habe dort einen ziemlich dummen Fehler drinne :K :K

Kann da wer etwas auf den ersten Blick etwas erkennen?
Zuletzt geändert von Anonymous am Samstag 19. August 2017, 11:53, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@SeesternMare: Was passiert denn? Und wie weicht das von Deinen Erwartungen ab? Und warum? Gibt es eine Ausnahme? Wenn ja, welche? Und wo? Wie sieht der Traceback aus?

Was man so sieht ist das Du ``global`` und nummerierte Namen verwendest, das solltest Du beides ganz dringend sein lassen und erst einmal die Grundlagen von Python lernen, also beispielsweise Schleifen, die Grunddatentypen mit denen man sich Datenstrukturen aufbaut, und für GUI-Programmierung auch objektorientierte Programmierung (OOP).
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

SeesternMare hat geschrieben:Hallo,

Ich habe demletzt schon eine Frage gestellt. Da wurde mir eine "after" Methode vorgeschalgen. Ich habe mich da mal eingelsen und es mir so zusammen gebastelt:

Doch ich glaube ich habe dort einen ziemlich dummen Fehler drinne :K :K

Kann da wer etwas auf den ersten Blick etwas erkennen?
Ja stimmt. Da hast Du eine Funktion abfrage und eine Funktion Auswertung. Aber aufrufen davon tust Du nichts. Ich würde eben die Funktion Auswertung aufrufen, damit das Programm anfängt. Aber auch dann rührt sich nichts.

Denn was nützt es, wenn Du bei der Abfrage etwas in irgendeine Variable schreibst. Da wird doch deshalb nichts angezeigt.

Du mußt eine Variable von tkinter nehmen. nämlich so etwas wie:

Test1 = tk.StringVar()

Und so eine Variable mußt Du mich einem Label verbinden:

Label(Fenster,textvariable = Test1, usw.)

Und dann auf das root Fenster sollst die ganz bestimmt kein pack machen. Aber auf die Label schon, sonst sieht man sie nämlich nicht.

Ach so, Werte an diese Stringvariablen weist man nicht mit = zu sondern mit der Methode set(wert)

Und was nützt es, wenn Du am Anfang eine Auswertung machst, wo etwas noch gar nicht da ist. Wenn Du jedes Mal eine Auswertung machen willst, dann mußt Du in der Schleife schon abfrage() und Auswertung() zusammen aufrufen. Ist klar, dass dann aber das mit den Labeln erzeugen und dem mainloop, dann nicht in die Auswertung hineingehört, oder?

Du hast also nicht nur einen dummen Fehler gemacht. Es stimmt einfach überhaupt nichts.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

SeesternMare hat geschrieben: Doch ich glaube ich habe dort einen ziemlich dummen Fehler drinne :K :K
Kann da wer etwas auf den ersten Blick etwas erkennen?
Da ist auf den ersten Blick zu erkennen, dass das alles nichts ist.

Aber so wird etwas draus:

Code: Alles auswählen

# -*- coding: utf-8 -*-

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk

class Application(tk.Tk):

    def __init__(self,**kwargs):
        tk.Tk.__init__(self,**kwargs)
        # widget definitions ===================================
        self.label_test1 = tk.Label(self,font='TkDefaultFont 30 {}', text='Test 1: ')
        self.label_test1.grid(row=0)
        self.label_ergebnis1 = tk.Label(self,font='TkDefaultFont 20 {}', text='bestanden')
        self.label_ergebnis1.grid(row=0, column=1)
        self.label_test2 = tk.Label(self,font='TkDefaultFont 30 {}', text='Test 2: ')
        self.label_test2.grid(row=1)
        self.label_test3 = tk.Label(self,font='TkDefaultFont 30 {}', text='Test 3: ')
        self.label_test3.grid(row=2)
        self.label_ergebnis2 = tk.Label(self,font='TkDefaultFont 20 {}', text='bestanden')
        self.label_ergebnis2.grid(row=1, column=1)
        self.label_ergebnis3 = tk.Label(self,font='TkDefaultFont 20 {}', text='bestanden')
        self.label_ergebnis3.grid(row=2, column=1)
        self.labelFrame_pins = LabelframePins(self)
        self.labelFrame_pins.grid(row=4, sticky='nesw', columnspan=2)
        self.label_test4 = tk.Label(self,font='TkDefaultFont 30 {}', text='Test 4: ')
        self.label_test4.grid(row=3)
        self.label_ergebnis4 = tk.Label(self,font='TkDefaultFont 20 {}', text='bestanden')
        self.label_ergebnis4.grid(row=3, column=1)

        self.test1 = 0
        self.test2 = 0
        self.test3 = 0
        self.test4 = 0

        self.loop()


    def loop(self):
        self.abfrage()
        self.auswertung()
        self.after(100,self.loop)

    def auswertung(self):
        self.label_ergebnis1['text'] = 'Bestanden' if self.test1 else 'Nicht bestanden'
        self.label_ergebnis2['text'] = 'Bestanden' if self.test2 else 'Nicht bestanden'
        self.label_ergebnis3['text'] = 'Bestanden' if self.test3 else 'Nicht bestanden'
        self.label_ergebnis4['text'] = 'Bestanden' if self.test4 else 'Nicht bestanden'

    def abfrage(self):

        # Bitte Logik selber machen, ich habe keine Ahnung, was es soll

        self.test1 = self.input_pin1()    
        self.test2 = self.input_pin2()
        self.test3 = self.input_pin3()
        self.test4 = self.input_pin4()


    def input_pin1(self):
        return self.labelFrame_pins.pin1_var.get()

    def input_pin2(self):
        return self.labelFrame_pins.pin2_var.get()

    def input_pin3(self):
        return self.labelFrame_pins.pin3_var.get()

    def input_pin4(self):
        return self.labelFrame_pins.pin4_var.get()


class LabelframePins(tk.LabelFrame):

    def __init__(self,master,**kwargs):
        tk.LabelFrame.__init__(self,master,**kwargs)
        self.config(text='Pins')
        # widget definitions ===================================

        self.pin1_var = tk.IntVar()
        self.pin2_var = tk.IntVar()
        self.pin3_var = tk.IntVar()
        self.pin4_var = tk.IntVar()

        self.pin1 = tk.Checkbutton(self,text='pin1',variable=self.pin1_var)
        self.pin2 = tk.Checkbutton(self,text='pin2',variable=self.pin2_var)
        self.pin3 = tk.Checkbutton(self,text='pin3',variable=self.pin3_var)
        self.pin4 = tk.Checkbutton(self,text='pin4',variable=self.pin4_var)
        self.pin1.pack(side='left', expand=1)
        self.pin2.pack(side='left', expand=1)
        self.pin3.pack(side='left', expand=1)
        self.pin4.pack(side='left', expand=1)


if __name__ == '__main__':
    Application().mainloop()
Deine Logik mußt Du allerdings noch implementieren, denn ich weiß nicht, worum es dabei geht.
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

@SeesternMare: Du schreibst Dein Programm wie ein seriellen Ablauf, so funktioniert aber ein ereignisgesteuerte GUI-Programm nicht. Was willst Du eigentlich erreichen? Aus dem Programm und den unsinnigen Test-Variablen wird das nicht klar.
BlackJack

@SeesternMare: Die Reihenfolge der Programmentwicklung scheint auch ungünstig gewählt zu sein. Normalerweise entwickelt man die Programmlogik und testet die, und schreibt sie gegebenenfalls so um, dass der Programmfortschritt von ”aussen” angetrieben werden kann, denn das braucht man für die ereignisbasierten Programmabläufe die einem von GUI-Rahmenwerken vorgegeben werden.

Und wenn das soweit läuft und getestet ist, setzt man erst eine GUI oben drauf.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:Und wenn das soweit läuft und getestet ist, setzt man erst eine GUI oben drauf.
Da muss ich widersprechen. Was ist dieses Programm eigentlich? Es fragt zwei Pins ab, wertet diese aus und gibt das dann in der GUI aus. Es ist jedenfalls verkehrt, gleich alles zu implementieren von Hardware IO Abfrage bis zu Ausgabe in der GUI. Außerdem kann dann auch keiner etwas helfen, der diese Hardware nicht hat.

Wo es hapert, ist die Implementierung der GUI. Da werden bei jeder Ausgabe, die hier nicht stattfindet, neue Labels angelegt. Das ist völlig verkehrt. Es ist genau richtig, mit der GUI anzufangen, die durchzuchecken und erst danach mit Hardwareabfrage zu verknüpfen.

Und was hier zu empfehlen ist, mit der GUI ganz am Anfang anzufangen, nämlich wie mache ich einen Label, und wie verändere ich den Text, wie mache ich ihn überhaupt sichtbar - da fehlte schließlich der pack und dann sollte man auch erst einmal kapieren, dass man für einen veränderten Labeltext keinen neuen Label anlegt.

Jedenfalls ist es richtig, nicht das ganze Programm zu implementieren, sondern erst einen Teil und das kann genauso auch die GUI sein. Aber bitte nicht so, dass man alles zusammen hat und nichts von dem funktioniert. Immer erst einen Teil zum Funktionieren bringen. Das kann auch IO Abfrage sein mit Ausgabe als Printanweisung, das geht auch oder das kann die GUI sein mit simulierten Pins. Da kann man dann auch später die Pinabfrage reinsetzen. Die Logik hat jedenfalls mit Hardware nichts zu tun. Daher die Logik und die Anzeige erst einmal ohne Hardwareanbindung implementieren. Zwei Pins abfragen ist schließlich Pipifax. Kann man zum Schluß ganz leicht einfügen.

Mein Tipp. Schritt für Schritt das Programm entwickeln. Das wäre etwa, da ist ein Ergebnis 0 oder 1 und der Text eines Labels soll daraufhin geändert werden. Wenn Du das implementiert hast, bist Du einen Schritt weiter und dann kommt der nächste Schritt.

Das ganze Programm hinschreiben und alles ist Quark bringt überhaupt nichts.

Es gibt auch solche Empfehlungen wie: jede geschriebene Zeile Code auch gleich testen, ob das funktioniert,

Wer mehr Erfahrung hat, kann auch mehr Zeilen hinschreiben, bevor er testet. Wenn ich eine GUI mache, schreibe ich überhaupt keinen Code, sondern nehme meinen GuiDesigner: https://github.com/AlfonsMittelmeyer/py ... -messaging

Bin ich denn blöd, dass ich eine Menge Zeilen tippe und da ein Menge Fehler mache, bevor die GUI geht. Nein, die erstelle ich einfach mit dem GuiDesigner und exportiere sie. Brauch ich mich gar nicht drum kümmern, wie und wo etwas hingehört und ob das richtig geschrieben ist.

Mein Tipp: bevor etwas nicht geht, schreibt man nicht weiter
BlackJack

@Alfons Mittelmeyer: Hier ist eine GUI ohne das man überhaupt weiss was das Programm macht/machen soll, also kann man da schlecht mit der GUI anfangen. GUI ist für den Anfang okay wenn man das braucht um sich über die Anforderungen an die Funktionalität klar zu werden, aber dann programmiert und testet man die Programmlogik ohne GUI und setzt die am Ende da erst drauf. Du magst das anders machen, wie Du ja generell gerne alles anders machst, aber gerade für Anfänger kommt ein besseres Programm am Ende heraus wenn sie die Programmlogik tatsächlich komplett separat von der GUI schreiben, und so gar nicht erst in die Versuchung kommen das nicht sauber zu trennen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:@Alfons Mittelmeyer: Hier ist eine GUI ohne das man überhaupt weiss was das Programm macht/machen soll, also kann man da schlecht mit der GUI anfangen. GUI ist für den Anfang okay wenn man das braucht um sich über die Anforderungen an die Funktionalität klar zu werden, aber dann programmiert und testet man die Programmlogik ohne GUI und setzt die am Ende da erst drauf. Du magst das anders machen, wie Du ja generell gerne alles anders machst, aber gerade für Anfänger kommt ein besseres Programm am Ende heraus wenn sie die Programmlogik tatsächlich komplett separat von der GUI schreiben, und so gar nicht erst in die Versuchung kommen das nicht sauber zu trennen.
Man kann freilich gerade mit der GUI anfangen. Die GUI hat acht Label, nämlich label_test1, label_test2, label_test3 und label_test4 und dann die Ergebnisse: label_ergebnis1, label_ergebnis2, label_ergebnis3 und label_ergebnis4 und abhängig von Ergebnissen test1, test2, test3 und test4 sollen dann die Label für die Ergebnisse 'Bestanden' oder 'Nicht bestanden' zeigen.

Was dabei nur unklar ist, wie diese Ergebnisse aufgrund von 2 Pins zustande kommen. Das muß ja wohl der User wissen. Und die Hardware Pins muss man nicht anschließen. Zum Testen kann man auch Checkboxen nehmen.

Was willst Du ohne GUI testen? Es gibt zwei Pins, 4 Testergebnisse daraus und die Anzeige in der GUI. Dass es zwei Pins gibt, braucht man nicht testen. Ob das mit der Auswertung hinhaut aus zwei Pins könnte man auch ohne GUI testen. Aber die Hauptsache ist wohl, dass die Ergebnisse von Test1 bis Test4 in der GUI angezeigt werden und wie man die Pins pollt.

Die Logik kapiere ich allerdings überhaupt nicht. Wenn beide pins die gleichen Wert haben und wenn sich dieser Wert nicht geändert hat, dann gibt es aufgrund dieser Nichtänderung neue Ergebnisse, wobei dann die aufgrund von Pin2 das nachher abgefragt wird, das Gegenteil von dem aufgrund von Pin1 sind. Kapierst Du da irgendwelche Logik?
BlackJack

@Alfons Mittelmeyer: Ohne GUI testet man die Programmlogik. Was denn auch sonst.

Es gibt keine Logik zu kapieren, das was da steht funktioniert ja ganz grundsätzlich schon nicht weil `prev_state` nicht definiert ist. Und was was danach kommt ist im Falle von `pin1`: ``Test1 = Test2 = Test3 = Test4 = 1``, nur deutlich umständlicher geschrieben. Und bei `pin2` werden die Namen alle an den Wert 2 gebunden. Ich bin mir aber ziemlich sicher das das nicht das ist was der OP möchte, aber darauf kann auch keiner erraten was er denn tatsächlich möchte.

Und daraus folgt auch das Deine Beschreibung was man hier an GUI braucht, gar nicht aus dieser ”Logik” ableitbar ist, weswegen man damit auch nicht anfangen kann.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben: Und daraus folgt auch das Deine Beschreibung was man hier an GUI braucht, gar nicht aus dieser ”Logik” ableitbar ist, weswegen man damit auch nicht anfangen kann.
Die Logik ist nicht ableitbar, aber dass es mehrere Tests sein sollen, mit jeweils bestanden oder nicht bestanden, das ist ableitbar und dass man die Ergebnisse jeweils mit Hilfe eines Labels ausgeben will. Dass man Pins pollt und daher eine after Poll Schleife braucht, ist auch ableitbar.

Man könnte natürlich daraus auch etwas Sinnvolles machen, wie drei Tests und die AND, OR und EXOR nennen oder man macht ein 4 Bit Schieberegister oder einen binären Zähler mit Reset
Antworten