Tkinter Programm nebenläufig

Fragen zu Tkinter.
Antworten
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Hallo

ich finde eure Hilfe super. Jetzt kommt ein Problem mit Tkinter. Ich wollte vom Hauptprogramm Tkinter ausführen wo die Funktion werte ausgeführt wird und die Variaben aufgerufen werden. Das Problem ist jedoch dass ich das Programm schließen muss bevor ich die Werte bekomme und das Hauptprogramm die Werte weiter verarbeiten kann. So habe ich es mir vorgestellt es funktioniert nicht perfekt. Muss ich das mit threading lösen oder habt ihr eine bessere bzw. andere Problemlösung?

Danke!

Hauptprogramm

Code: Alles auswählen

import probe_gui

werte=probe_gui.Window().werte(None)

wert1=werte[0]
wert2=werte[1]
wert3=werte[2]

print(wert1, wert2, wert3)

while(True):
    #Funktionen
    pass
GUI

Code: Alles auswählen

import tkinter as tk

class Window():
    def __init__(self): 

        self.root = tk.Tk()
        self.root.geometry("600x400")        

        self.entries=[]
        for column in range(0,4):
            self.entry=tk.Entry(self.root, width=5)
            self.entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(self.entry)
        
        self.button=tk.Button(self.root, text='Auslesen', command=self.werte)
        self.button.pack()
        
        self.root.bind('<Return>', self.werte)
                  
    def werte(self, event):
        auslesen=self.auslesen()
        funktion1=self.funktion1()
        funktion2=self.funktion2()
        #print('Werte wurde gedrückt')
        #print(auslesen, funktion1, funktion2)
        return auslesen, funktion1, funktion2
            
    def auslesen(self):   
        liste=[]
        for x in self.entries: 
            #print(x)
            #print(x.get())
            x=x.get()
            liste.append(x)
        #print(liste)
        return liste
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2
   
            
graph=Window()
graph.root.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ichbins: Du ziehst das von der falschen Seite her auf. Die GUI-Hauptschleife ist das Hauptprogramm. Das ist das was man ausführt. Da muss sich Dein Code entweder direkt integrieren lassen, oder *der* läuft in einem Thread und die GUI kommuniziert per Queue(s) und `after()`-Methode mit dem Code. Die Geschäftslogikt ruft keinen GUI-Code auf.

Beim Importieren von Modulen darf kein Code ablaufen der mehr macht als Konstanten, Funktionen, und Klassen zu definieren. Bei Dir wird da sogar eine GUI ausgeführt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Ich bin gerade am Überlegen ob es sich auszahlt in Thread und Queue einzuarbeiten oder ob es doch besser wäre sich in ein Webframework einzuarbeiten. Wird bei einem Webframework auch Thread und Queue benötigt oder geht es auch ohne.
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Problem ist doch das selbe: Du hast eine Ebene mit Benutzerinteraktion und parallel dazu irgendeine Berechnung. Also brauchst Du Threads und Queues.
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Irgendwie fehlt mir der Ansatz wie ich die Threads bei zwei Klassen bzw. zwei Dateien lösen kann. Habt ihr da ein Bsp. oder paar Tipps. Beim Start bleibt es in der Klasse Messinstrumente hängen.

LG

GUI

Code: Alles auswählen

import tkinter as tk
import probe_hauptprogramm
from threading import Thread


class Window():
    def __init__(self): 

        self.root = tk.Tk()
        self.root.geometry("600x400")        

        self.entries=[]
        for column in range(0,4):
            self.entry=tk.Entry(self.root, width=5)
            self.entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(self.entry)
        
        self.button=tk.Button(self.root, text='Auslesen', command=self.werte)
        self.button.pack()
        
        #self.root.bind('<Return>', self.werte)
                  
    def werte(self):
        auslesen=self.auslesen()
        funktion1=self.funktion1()
        funktion2=self.funktion2()
        probe_hauptprogramm.Messinstrumente(auslesen, funktion1, funktion2)

            
    def auslesen(self):   
        liste=[]
        for x in self.entries: 
            #print(x)
            #print(x.get())
            x=x.get()
            liste.append(x)
        #print(liste)
        return liste
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2
    

if __name__=='__main__':            
    graph=Window()
    graph.root.mainloop()
    x = Thread(graph)
    x.start()

Messprogramm

Code: Alles auswählen

from time import sleep
from threading import Thread

class Messinstrumente:
    def __init(self, auslesen, funk1, funk2):
        self.lesen=auslesen
        self.function1=funk1
        self.function2=funk2
        print(self.lesen, self.function1, self.function2)
    
    x = Thread()
    x.start()
   
    #Hauptprogramm
    while(True):
        #Funktionen
        print('programm wird ausgeführt´')
        sleep(4)

        try:
            print(self.lesen)
            print(self.function1)
            print(self.function2)
        except:
            print('Fehler')
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ichbins: Das sieht nach programmieren nach raten aus. Ein `Thread`-Objekt erstellen dem weder ein `target` mitgegeben wurde noch die `run()`-Methode überschrieben wurde macht einfach gar nichts wenn man diesen Thread mit `start()` startet. Also da wird ein Thread gestartet der dann auch gleich wieder beendet ist, weil der ja nix macht.

Und dann folgt auf Modulebene eine Endlosschleife bei der Du die Ausnahme die da unweigerlich auftritt, weil `self` nirgends definiert ist, über ein nacktes ``except:`` in eine absolut nicht hilfreiche Ausgabe des Wortes "Fehler" behandelst. Keine nackten ``except:``\s es sei denn man protokolliert die Ausnahme samt Traceback und es ist tatsächlich sinnvoll möglich an der Stelle *alle* Ausnahmen einfach zu ignorieren und so weiter zu machen, als wäre nichts passiert.

Das ganze passiert schon beim importieren von `probe_hauptprogramm` weil Code auf Klassenebene ausgeführt wird wenn die ``class``-Anweisung ausgeführt wird.

Ich sehe auch noch nicht so ganz ob/warum das eine Klasse sein muss.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Da es nicht so funktioniert hat wie ich dachte, war es bisschen programmieren nach raten. Deswegen habe ich gemeint ein Bsp. wäre nicht schlecht. Ich habe es bisschen geändert, aber bei tkinter bleibt der Button noch immer blockiert.

Du hast gemeint ein Modul sollte immer eine Klasse oder Funktion bzw. Konstante sein. Letztendlich ist es das Hauptprogramm jedoch wird die Grafik zum Hauptprogramm. Ich könnte die 400 Zeilen in eine Funktion packen. Aber es kommt mir vor als ob es bisschen viele Zeilen für eine Funktion wären. Vielleicht könnte man das Programm noch in mehrere Funktionen unterteilen. Bzw. wie hast du dir das vorgestellt.

Code: Alles auswählen

import tkinter as tk
import probe_hauptprogramm
from threading import Thread


class Window():
    def __init__(self): 

        self.root = tk.Tk()
        self.root.geometry("600x400")        

        self.entries=[]
        for column in range(0,4):
            self.entry=tk.Entry(self.root, width=5)
            self.entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(self.entry)
        
        self.button=tk.Button(self.root, text='Auslesen', command=self.werte)
        self.button.pack()
        
        #self.root.bind('<Return>', self.werte)
                  
    def werte(self):
        auslesen=self.auslesen()
        funktion1=self.funktion1()
        funktion2=self.funktion2()
        probe_hauptprogramm.messinstrumente(auslesen, funktion1, funktion2)

            
    def auslesen(self):   
        liste=[]
        for x in self.entries: 
            #print(x)
            #print(x.get())
            x=x.get()
            liste.append(x)
        #print(liste)
        return liste
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2
    

if __name__=='__main__':            
    graph=Window()
    graph.root.mainloop()
    x = Thread(target=graph)
    x.start()
    y = Thread(target=probe_hauptprogramm.messinstrumente)
    y.start()

Code: Alles auswählen

from time import sleep
from threading import Thread

def messinstrumente(auslesen, funk1, funk2):

    #Hauptprogramm
    while(True):
        #Funktionen
        print('programm wird ausgeführt´')
        sleep(4)

        print(auslesen)
        print(funk1)
        print(funk2)
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@ichbins: dass self.entry falsch ist, wurde Dir schon gesagt, dass `x` ein sehr schlechter Variablenname ist, wurde Dir schon gesagt.

Wenn Du von einem Thread mit einer GUI kommunizieren willst, brauchst Du eine Queue.
`messinstrumente` übergibst Du Funktionen, was nicht sein darf, weil aus Threads heraus keine GUI angesprochen werden darf.
Was hast Du Dir bei x = Thread(target=graph) gedacht? graph ist doch nicht ausführbar.
Nach mainloop darf kein Code mehr kommen.

Code: Alles auswählen

import tkinter as tk
from threading import Thread
from queue import Queue

def messinstrumente(queue):
    print('programm wird ausgeführt´')
    while True:
        werte = queue.get()
        print(werte)

class Window():
    def __init__(self, queue): 
        self.queue = queue
        self.root = tk.Tk()
        self.entries = []
        for column in range(4):
            entry=tk.Entry(self.root, width=5)
            entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(entry)
        tk.Button(self.root, text='Auslesen', command=self.werte_uebertragen).pack()

    def werte_uebertragen(self):   
        werte = [entry.get() for entry in self.entries]
        self.queue.put(werte)

def main():
    queue = Queue()
    mess_thread = Thread(target=messinstrumente, args=(queue,))
    graph = Window(queue)
    graph.root.mainloop()

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

@ichbins: Natürlich blockiert das, Du rufst da bei einem Klick auf die Schaltfläche eine Funktion auf die eine Endlosschleife enthält, also nie wieder zur GUI-Hauptschleife zurück kehrt.

Die Funktion macht auch nicht so wirklich Sinn, denn da werden alle vier Sekunden die gleiche Werte per `print()` ausgegeben.

Was ebenfalls blockiert ist die GUI-Hauptschleife, solange das Fenster angezeigt wird. Nach dem schliessen des Fensters versuchst Du das `Tk`-Objekt in einem Thread auszuführen, was nicht geht weil das nicht aufrufbar ist. Und die `probe_hauptprogramm.messinstrumente()`-Funktion ebenfalls in einem Thread auszuführen, was aber nicht klappen wird, weil die ja drei Argumente erwartet, die aber nicht bekommt. Und wie gesagt, sinnvoll ist das auch nicht bis in alle Ewigkeit alle vier Sekunden die gleichen Werte auszugeben.

Die Namensgebung ist auch teilweise sehr verwirrend. `auslesen` ist eine Liste und `funktion1` und `funktion2` sind ganze Zahlen — das ist extrem irreführend. Wie man an der Antwort von Sirius3 sehen kann. Bei `messinstrumente()` dann `funk1` und `funk2` macht es nicht besser. Auf welchen Frequenzen wird denn da gesendet? Auch `messinstrumente()` geht als Name nicht. Funktionsnamen beschreiben die Tätigkeit die von der Funktion (oder Methode) ausgeführt wird. `messinstrumente` ist keine Tätigkeit.

Ich habe nicht gemein ein Modul sollte immer eine Klasse, Funktion, oder Konstante sein. Also ”sein” schon mal gar nicht, denn ein Modul ist ein Modul. Der Code auf Modulebene sollte nur Konstanten, Funktionen, und Klassen definieren. Da sollte kein Code stehen der globale Variablen definiert oder gar das Hauptprogramm. Man muss ein Modul importieren können, ohne das dabei mehr passiert als eben jene Definitionen von Konstanten, Funktionen, und Klassen.

Wenn Du da 400 Zeilen stehen hast die etwas anderes machen, dann ist das definitiv falsch. Und definitiv nichts was man mit einer GUI verbinden/-wenden kann. Dazu muss das mindestens in Funktionen stehen, wenn nicht sogar auch eine eigene Klasse sein wenn es Zustand gibt, der über meherere Aufrufe von der GUI hinweg gemerkt werden muss. Vielleicht ginge auch eine Funktion die in einem Thread läuft und über Queues mit der GUI kommuniziert.

Die 400-Zeilen-Aussage macht mir so ein bisschen sorgen. Denn für GUI-Programmierung braucht man Klassen. Für Klassen muss man Funktionen drauf haben. Und Funktionen heisst kleine globalen Variablen. Und jetzt kommst Du und sagst Du hast da 400 Zeilen Code die offenbar nicht einmal in *einer* Funktion stecken. Dann hast Du erst einmal noch gar kein Problem mit GUI-Programmierung, denn da ist noch überhaupt nicht dran zu denken.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Danke für die ausführlichen Antworten.

@Sirius3: Kann es sein dass am Code irgendetwas nicht stimmt? Es wird 'while True' nicht ausgeführt bzw. keine Ausgabe.

@Blackjack: funk1 und funk2 sind die Funktionen 1 und 2. Es geht darum die Werte die in den ganzen Entry Widgets sind, in der Funktion messinstrumente aufzurufen.

Es gibt das Hauptprogramm mit 400 Zeilen was man noch in Funktionen aufteilen könnte und ein Modul aus Funktionen mit ca. 600 Zeilen. Man kann ein Programm immer verschönern jedoch ist mir zuerst wichtig dass ich die Eingaben im GUI im Hauptprogramm aufrufen kann.
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ichbins: `funk1` und `funk2` sind keine Funktionen sondern die ganzen Zahlen 1 und 2. Zahlen sind keine Funktionen. Darum ist das echt verwirrend die so zu benennen. Die Werte in den Entries kann man auch nicht ”aufrufen”. Aufrufen ist einen Ausdruck zu schreiben der etwas aufrufbares ergibt und dann dahinter runde Klammern, optional mit Argumenten. *Das* ist ein Aufruf. Das geht mit Zeichenketten (die stehen in den Entries) oder Zahlen nicht.

Es geht hier nicht ums verschönern. Sauber auf echte Funktionen aufteilen und keine globalen Variablen zu verwenden ist nicht irgendwie schön, sondern der normale Grundzustand. Wenn man nicht einmal da ist, macht es keinen Sinn darüber nachzudenken wie man da eine GUI drauf setzt, denn das geht schlicht nicht. Eine GUI kann nicht Code aufrufen der auf Modulebene steht, dazu *muss* der mindestens in Funktionen stecken. Und da man für die GUI sowieso Klassen braucht, gibt es auch keinerlei Ausreden woanders globale Variablen zu verwenden.

Falls Dein Hauptprogramm in einem eigenen Thread läuft muss das auch mindestens in einer Funktion stecken, denn Code auf Modulebene kann man nicht in einem anderen Thread laufen lassen (es sei denn man macht noch mehr Sachen die man einfach nicht macht!).

Der Code in dem Thread kann auch nicht einfach so auf die GUI zugreifen, der muss threadsicher mit dem Thread in dem die GUI läuft kommunizieren. Was in der Regel am einfachsten über Queues geht.

Bei dem was Du da gezeigt hast ist aber nicht ganz klar was Du überhaupt erreichen willst. Wenn nur alle vier Sekunden *kurz* irgend etwas gemacht werden soll, dann braucht man keine Threads sondern kann einfach die `after()`-Methode verwenden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Ich möchte erreichen dass beim Start des Programms die GUI angezeigt wird und das Hauptprogramm blockiert. Nachdem ich den Button drücke sollen die ganzen Werte aus den Entry Widgets an das Hauptprogramm übergeben werden und das Hauptprogramm starten. Somit kommt auch das Hauptprogramm in eine while True Schleife und läuft die ganze Zeit. Die GUI ist nur nebenbei offen. Falls ich wieder auf den Button drücke sollen die Aktualisierten Werte wieder an das Hauptprogramm übergeben werden und von neu starten bzw. einfach nur die aktualisierten Werte übernehmen und damit weiter rechnen bzw. das Hauptprogramm bearbeiten. Es sind auch Wartezeiten in der while Schleife die mehrere Sekunden machen aber es läuft die ganze Zeit. Das Problem ist halt wenn das Hauptprogramm läuft dass die GUI blockiert. Bei diesem Bsp. war ja bei sleep() der Button blockiert. Somit war auch die Rede dass ich Threads brauche und Queues kamen auch zu Wort.

Ich habe das Programm vom Sirius probiert aber es lief nicht ganz nach meiner Vorstellung. Wenn ich auf "Ausführen" drücke erschienen nie die Werte von print(werte).
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Da fehlt ja auch ein `mess_thread.start()`.
Und bei GUIs mußt Du umdenken. Das "Hauptprogramm" wie Du es nennst, läuft nebenbei, denn GUIs betrachten sich immer selbst als Hauptprogramm. Daran kann man nichts ändern. Und so wie Du das beschreibst, ist es ungefähr das, was ich geschrieben habe: Das Messprogramm läuft in einem Thread und kann regelmäßig die Queue abfragen, ob neue Werte eingetragen wurden.
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Hallo

bei diesem Bsp. ist ja stop_thread eine Globale Variable. Wenn das Hauptprogramm in der selben Datei steht dann funktioniert es. Jedoch wenn ich das Hauptprogramm in eine eigene Datei schreibe nimmt es nicht den Wert aus dem main-Programm obwohl es eine Globale Variable ist. Wieso ist das so?

LG


gui_probe_threading

Code: Alles auswählen

class Window():
    def __init__(self, queue): 
        self.queue=queue
        self.root = tk.Tk()
        self.root.geometry("600x400")        

        self.entries=[]
        for column in range(0,4):
            self.entry=tk.Entry(self.root, width=5)
            self.entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(self.entry)
        
        self.button=tk.Button(self.root, text='Auslesen', command=self.werte)
        self.button.pack()
        
        #self.root.bind('<Return>', self.werte)
                  
    def werte(self):
        werte=[]
        werte.append(self.auslesen())
        werte.append(self.funktion1())
        werte.append(self.funktion2())
        self.queue.put(werte)
 

            
    def auslesen(self):   
        liste=[]
        for x in self.entries: 
            #print(x)
            #print(x.get())
            x=x.get()
            liste.append(x)
        #print(liste)
        return liste
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2
         
global stop_thread
stop_thread=False  

if __name__=='__main__':
    queue=Queue()  
    my_thread=Thread(target=gui_probe_hauptprogramm.messprozess, args=(queue, ))        
    my_thread.start()    
    graph=Window(queue) 
    graph.root.mainloop()
    stop_thread=True
gui_probe_hauptprogramm

Code: Alles auswählen

def messprozess(queue):
    werte = queue.get()
    print('programm wird ausgeführt´')
    while True:       
        print(werte)
        sleep(3)
        if queue.empty() == False:
            print('Empty voll')
            werte=queue.get()
        if gui_probe_threading.stop_thread!=False:
            break
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ichbins: Vergiss bitte ``global``. Auf Modulebene hat das zudem sowieso keinerlei Effekt.

Warum rufst Du `queue.get()` vor der Schleife auf? Der Aufruf sollte nur einmal, in der Schleife stehen. Und auch grundsätzlich, nicht nur wenn `empty()` den Wert `False` liefert. Das beenden macht man dann nicht über eine extra Variable sondern man schickt über die Queue einen Wert der signalisiert, dass der Thread sich beenden soll.

Vergleiche mit literalen Wahrheitswerten macht man nicht. Da kommt nur wieder ein Wahrheitswert bei heraus. Entweder der den man sowieso schon hatte — dann kann man den auch gleich verwenden — oder das Gegenteil. Für den Fall gibt es ``not``.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

queue.get ruf ich vor der Schleife auf um zu blockieren und alle Daten zu bekommen wie z.B. eine csv Datei zu erstellen bzw. fortzusetzen usw. In der while True Schleife verwende ich queue.get falls die Daten aktualisiert werden. Danach wird if queue.empty() verwendet damit queue.get nur blockiert falls neue Werte gesetzt wurden und Auslesen betätigt wird.

Wenn ich lese if queue.empty, habe ich mir manchmal die Frage gestellt was verglichen wird. Mit den literalen Wahrheitswerten war es irgendwie leserlicher für mich.
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ichbins: Tja rethorische Fragen. 🙂 Ich wollte eigentlich nicht wissen warum Du das aufrufst, *Du* solltest Dich das fragen und zu dem Schluss kommen, dass das unsinnig ist. Die Queue ist zur Kommunikation da, damit man keine globalen Variablen benutzen muss. Wenn Du da nebenher dann doch wieder noch eine globale Variable rein bastelst über die parallel zur Queue etwas kommuniziert werden soll, dann hätte man sich die Queue sparen können.

Bei ``if queue.empty()`:`` wird gar nichts verglichen. Da muss auch nichts verglichen werden. Darum muss man da auch wirklich nichts vergleichen. Es macht keinen Sinn. Es macht den Code nicht klarer. Da muss ein Ausdruck stehen der zu „wahr“ oder „falsch“ ausgewertet wird. Das muss kein Vergleich sein. Wenn man das liest, heisst das „Falls Queue leer, dann …“. Das ist IMHO ziemlich deutlich.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
ichbins
User
Beiträge: 40
Registriert: Samstag 5. September 2020, 07:07

Mir ist noch nicht ganz klar wie Threads und Queue angewendet werden. Wieso ist es unsinnig? Ich habe es versucht mit diesem Code aber es passt nicht.

Code: Alles auswählen

import tkinter as tk
import gui_probe_hauptprogramm
from threading import Thread
from queue import Queue
import os
from time import sleep



class Window():
    def __init__(self, queue):        
        self.queue=queue
        self.root = tk.Tk()
        self.root.geometry("600x400")  
        

        self.entries=[]
        for column in range(0,4):
            self.entry=tk.Entry(self.root, width=5)
            self.entry.pack(side=tk.LEFT, anchor=tk.W)
            self.entries.append(self.entry)
        
        self.button=tk.Button(self.root, text='Auslesen', command=self.werte)
        self.button.pack()
        
        #self.root.bind('<Return>', self.werte)
                  
    def werte(self):
        werte=[]
        werte.append(self.auslesen())
        werte.append(self.funktion1())
        werte.append(self.funktion2())
        self.queue.put(werte)
 

            
    def auslesen(self):   
        liste=[]
        for x in self.entries: 
            #print(x)
            #print(x.get())
            x=x.get()
            liste.append(x)
        #print(liste)
        return liste
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2
    




if __name__=='__main__':  
    stop_thread=False
    queue=Queue()  
    my_thread=Thread(target=gui_probe_hauptprogramm.messinstrumente, args=(queue, stop_thread))        
    my_thread.start()  
    graph=Window(queue)
    #graph.root.protocol('WM_DELETE_WINDOW', thread_stop)   
    graph.root.mainloop()   
    stop_thread=True
    queue.put(stop_thread)

Code: Alles auswählen

def messinstrumente(queue, stop_thread):
    #print(werte)
    werte=queue.get()
    print(werte)
    print('programm wird ausgeführt´')
    #Hauptprogramm
    while(True):
        #Funktionen
        print(werte[0], werte[1], werte[2])
        sleep(4)
        
        if not queue.empty():
            print('if wird ausgeführt')
            werte=queue.get()
            
            if stop_thread:
                print('while wird abgebrochen')
                break
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Das Problem ist, dass wir Dein messinstrument nicht kennen, und so der Code halt wenig Sinn macht.

Ein Modul gui_probe_hauptprogramm zu nennen, das explizit ja nichts mit der GUI zu tun haben soll, ist komisch.
Ein Modul gui_probe_hauptprogramm zu nennen, das explizit nicht das Hauptprogramm ist, sondern nebenläufig, ist komisch.
In __init__: wie oft soll ich noch schreibe, dass das Binden eines Wertes an ein Attribut innerhalb einer for-Schleife selten sinnvoll ist. entry ist und bleibt und wird immer eine lokale Variable bleiben.
In Methode werte: eine Methode sollte nicht wie eine Variable heißen. Wenn die Anzahl der Elemente einer Liste fix ist, dann erzeugt man gleich die Liste mit Elementen.
In auslesen: x ist ein schlechter Name für ein Entry und das bleibt es auch, egal wie oft Du das noch nicht berücksichtigst.
Das Argument stop_thread ist unsinnig, weil es immer False ist. my_ ist ein unsinniges Präfix.

Code: Alles auswählen

import tkinter as tk
from threading import Thread
from queue import Queue
from time import sleep

def messinstrumente(queue):
    should_stop, werte = queue.get()
    print(werte)
    print('programm wird ausgeführt´')
    while True:
        #Funktionen
        print(werte[0], werte[1], werte[2])
        sleep(4)

        if not queue.empty():
            print('if wird ausgeführt')
            should_stop, werte = queue.get()
            if should_stop:
                print('while wird abgebrochen')
                break

class Window():
    def __init__(self, queue):        
        self.queue = queue
        self.root = tk.Tk()
        self.entries = []
        for column in range(0,4):
            entry = tk.Entry(self.root, width=5)
            entry.pack(side=tk.LEFT, anchor=tk.W)
            entries.append(entry)
        tk.Button(self.root, text='Auslesen', command=self.sende_werte).pack()

    def sende_werte(self):
        werte = [self.auslesen(), self.funktion1(), self.funktion2()]
        self.queue.put((False, werte))
 
    def auslesen(self):   
        return [
            entry.get()
            for entry in self.entries
        ]
    
    def funktion1(self):
        #print('Funktion1')
        return 1
    
    def funktion2(self):
        #print('Funktion2')
        return 2


if __name__=='__main__':
    queue = Queue()  
    messinstrumente_thread = Thread(target=gui_probe_hauptprogramm.messinstrumente, args=(queue, ))        
    messinstrumente_thread.start()
    graph = Window(queue)
    graph.root.mainloop()   
    queue.put((True, None))
Antworten