Seite 1 von 1

Probleme mit Vererbung während Threading

Verfasst: Dienstag 31. Juli 2018, 15:48
von DMD-OL
hallo
ich weiß nicht, ob das überhaupt möglich ist.
ich habe zwei verschiedene klassen, die ich je getrennt voneinander als Thread laufen lasse.
die class_1 verarbeitet daten. während diese das tut, soll eine prozessbar aus class_2 den fortschritt des verlaufs anzeigen.
damit das möglich ist, muß die class_1 also die class_2 erben (denk ich), damit die prozessbar (bzw. die variable der prozessbar "self.progress_var")
aus der class_2 auch in class_1 angesprochen werden kann.
ist das überhaupt möglich und wenn ja, how???

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'DMD-OL'


from Tkinter import Tk, Toplevel, Label, Button, StringVar, DoubleVar
import ttk
import threading
import os
import time


class Class_1(threading.Thread):

    update_datei = "C:\Users\DMD-OL\Documents\Python\Handy-Datenbank\DATANORM\DATANORM.002"
    filesize = int(os.path.getsize(update_datei))
    size = 49152

    def __init__(self, ident, name, instance):
        threading.Thread.__init__(self)
        self.id = ident
        self.name = name
        self.instance = instance

    def run(self):

        for hallo in range(100):
            print hallo
            print self.filesize
            print self.size
            # self.progress_var.set(hallo)
            time.sleep(1)
            if runString is False:
                break

        self.instance.closing()
        print "Finished"


class Class_2(threading.Thread):

    def __init__(self, ident, name):
        threading.Thread.__init__(self)
        self.id = ident
        self.name = name

        self.second = Toplevel()
        self.second.title("Second window")
        self.second.geometry("%dx%d+%d+%d" % (300, 150, 600, 250))
        self.var = StringVar()
        self.var.set("Gestartet von:\n'{}', ID: '{}'".format(self.name, self.id))

        self.label = Label(self.second, textvariable=self.var)
        self.label.place(relx=.5, rely=.25, anchor="c")

        self.progress_var = DoubleVar()
        self.progress_bar = ttk.Progressbar(self.second, variable=self.progress_var, length=250)
        self.progress_bar.place(relx=.5, rely=.5, anchor="c")

        self.break_button = Button(self.second, text="ABBRECHEN", width=15, command=self.stopping)
        self.break_button.place(relx=.5, rely=.8, anchor="c")

        self.close_button = Button(self.second, text="CLOSE", width=15, command=self.second.quit)

    def stopping(self):
        global runString
        runString = False
        self.var.set("Der Vorgang wurde\nabgebrochen!")
        self.label.place(relx=.5, rely=.25, anchor="c")
        self.progress_bar.destroy()
        self.break_button.destroy()
        self.close_button.place(relx=.5, rely=.7, anchor="c")

    def closing(self):
        self.var.set("Der Vorgang wurde\nabgeschlossen!")
        self.label.place(relx=.5, rely=.25, anchor="c")
        self.break_button.destroy()
        self.close_button.place(relx=.5, rely=.8, anchor="c")


class MyFirstGUI:

    def __init__(self):

        self.first = Tk()
        self.first.title("First window")
        self.first.geometry("%dx%d+%d+%d" % (200, 100, 600, 250))
        self.label = Label(self.first, text="This is my first GUI!")
        self.label.place(relx=.2, rely=.2, anchor="w")
        self.start_button = Button(self.first, text="START", width=15, command=self.start)
        self.start_button.place(relx=.2, rely=.5, anchor="w")
        self.close_button = Button(self.first, text="CLOSE", width=15, command=self.first.quit)
        self.close_button.place(relx=.2, rely=.8, anchor="w")
        self.first.mainloop()

    def start(self):
        self.first.withdraw()
        self.first.update_idletasks()
        thread_2 = Class_2(0, "Christian")
        thread_1 = Class_1(0, "Christian", thread_2)
        thread_2.start()
        thread_1.start()


runString = True
MyFirstGUI()

Re: Probleme mit Vererbung während Threading

Verfasst: Dienstag 31. Juli 2018, 16:29
von Sirius3
@DMD-OL: nein, Vererbung ist falsch, denn das Verarbeiten von Daten IST ja kein Processbar. Für Vererbung muß immer eine IST EINE Relation vorliegen.
Class_1 und Class_2 sind schlechte Namen, weil sie nichts aussagen. GUI-Elemente dürfen immer nur vom Hauptthread aus geändert werden, so dass Class_2 kein Thread sein darf, was er ja auch nicht ist, weil es keine run-Methode gibt. Es ist unüblich von threading.Thread abzuleiten, statt dessen nimmt man eine Funktion, die man threading.Thread als target-Argument übergibt.
Die Kommunikation zwischen Threads muß gesichert sein, dafür nimmt man eine passende Datenstruktur, üblicherweise Queues, hier vielleich auch ein threadsicherer Counter. Im Hauptprozess weist man die GUI per after an, zu regelmäßigen Zeitpunkten die Queue/den Counter abzufragen und entsprechend die Processbar upzudaten.
Vergiss generell dass es `global` gibt, und nutze es auf keinen Fall bei Threads, das führt nur zu unberechenbarem Verhalten. Um Informationen an den Thread wieder zurückzugeben, muß man eine threadsichere Datenstruktur benutzen, z.B. threading.Event.

Re: Probleme mit Vererbung während Threading

Verfasst: Donnerstag 2. August 2018, 17:42
von DMD-OL
ich hab jetzt mal versucht das umzusetzen.
hab aber einiges noch nicht ganz verstanden....:)
z.b. Im Hauptprozess weist man die GUI per after an, zu regelmäßigen Zeitpunkten die Queue/den Counter abzufragen und entsprechend die Processbar upzudaten.
d. h. was du meinst zwar schon, aber nicht wie es umgesetzt werden kann...

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

__author__ = 'DMD-OL'


from Tkinter import Tk, Toplevel, Label, Button, StringVar, DoubleVar
import ttk
from Queue import Queue
from threading import Thread
import threading

def working(queue):
    for x in range(100):
        queue.put(x+1)
        # print queue.get()


class MySecondGUI(threading.Thread):

    def __init__(self, ident, name, queue):
        threading.Thread.__init__(self)
        self.id = ident
        self.name = name
        self.queue = queue

        self.second = Toplevel()
        self.second.title("MySecondGUI")
        self.second.geometry("%dx%d+%d+%d" % (300, 150, 600, 250))
        self.var = StringVar()
        self.var.set("Gestartet von:\n'{}', ID: '{}'".format(self.name, self.id))

        self.label = Label(self.second, textvariable=self.var)
        self.label.place(relx=.5, rely=.25, anchor="c")

        self.progress_var = DoubleVar()
        self.progress_bar = ttk.Progressbar(self.second, variable=self.progress_var, maximum=100, length=250)
        self.progress_bar.place(relx=.5, rely=.5, anchor="c")

        self.break_button = Button(self.second, text="ABBRECHEN", width=15, command=self.stopping)
        self.break_button.place(relx=.5, rely=.8, anchor="c")

        self.close_button = Button(self.second, text="CLOSE", width=15, command=self.second.quit)

        self.print_queue()

    def print_queue(self):
        while True:
            print self.queue.get()
            self.queue.task_done()

    def stopping(self):
        global runString
        runString = False
        self.var.set("Der Vorgang wurde\nabgebrochen!")
        self.label.place(relx=.5, rely=.25, anchor="c")
        self.progress_bar.destroy()
        self.break_button.destroy()
        self.close_button.place(relx=.5, rely=.7, anchor="c")

    def closing(self):
        self.var.set("Der Vorgang wurde\nabgeschlossen!")
        self.label.place(relx=.5, rely=.25, anchor="c")
        self.break_button.destroy()
        self.close_button.place(relx=.5, rely=.8, anchor="c")


class MyFirstGUI:

    def __init__(self):

        self.first = Tk()
        self.first.title("MyFirstGUI")
        self.first.geometry("%dx%d+%d+%d" % (300, 150, 600, 250))
        self.label = Label(self.first, text="This is my first GUI!")
        self.label.place(relx=.5, rely=.2, anchor="c")
        self.start_button = Button(self.first, text="START", width=15, command=self.start)
        self.start_button.place(relx=.5, rely=.5, anchor="c")
        self.close_button = Button(self.first, text="CLOSE", width=15, command=self.first.quit)
        self.close_button.place(relx=.5, rely=.8, anchor="c")
        self.first.mainloop()

    def start(self):
        self.first.withdraw()
        self.first.update_idletasks()

        queue = Queue(maxsize=0)

        MySecondGUI(0, "Christian", queue).start()
        thread = Thread(target=working, args=(queue,))
        thread.setDaemon(True)
        thread.start()


runString = True
MyFirstGUI()

Re: Probleme mit Vererbung während Threading

Verfasst: Freitag 3. August 2018, 22:38
von Sirius3
Dass `MySecondGUI` von `Thread` erbt, macht immer noch keinen Sinn. Weder in __init__ noch in einem GUI-Programm sollte es Endlosschleifen geben. mainloop sollte in der Hauptfunktion aufgerufen werden, nicht in `__init__`. Vergiss schnellstens, dass es `global` gibt, das macht selten etwas Gutes.

Hast Du Dir schon Beispiele angesehen, in denen after benutzt wird? Gibts zu Hauf hier im Forum.