Seite 1 von 1

tkinter und pyttsx3

Verfasst: Sonntag 4. November 2018, 20:48
von Septias
Ich bin dabei ein Text-adventure-spiel zu programmieren. Dafür erstelle ich bei Klicken auf einen Button immer neue Buttons und lösche die Alten, außerdem verändere den Text eines Texfeldes. Jetzt möchte ich, dass der Text des Texfeldes bei Erscheinen des aktualiesierten Windows mit tts ausgegeben wird. Das Problem ist jetzt, dass der Text erst von pyttsx3 vollkommen ausgegben wird, bevor tkinter einen neuen Schleifendurchlauf starten kann, und somit das Fenster neu zeichnet. Das resultiert darin, dass man immer noch den alten Text sieht, wenn der Neue ausgegeben wird.

Wie kann ich es hinbekommen, dass erst das Fenster aktualisiert wird, und dann der Text ausgegeben ?

Ich habe es schon mit Multiprocessing versucht, aber wenn ich es so mache:

Code: Alles auswählen

        p = multiprocessing.Process(target=engine.runAndWait)
        p.start()
bekomme ich diesen Fehler:

Code: Alles auswählen

        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
Ich schätze mal, das hängt damit zusammen, dass Tkinter auch noch multiprogressing verwendet. Weil in meinem Code wird erst nach dem Drücken eines Knopfes ein weitere Text und somit ein weitere Prozess gestartet.

Re: tkinter und pyttsx3

Verfasst: Sonntag 4. November 2018, 21:04
von Sirius3
@Septias: zeig doch den Code, der was mit dem Problem zu tun hat. Wo wird welcher Text geändert und was bleibt dann noch stehen?

Re: tkinter und pyttsx3

Verfasst: Sonntag 4. November 2018, 21:10
von __blackjack__
@Septias: Ich würde für die Sprachausgabe einen eigenen Thread starten (`threading`-Modul) und über eine `Queue` die Texte die gesprochen werden sollen an diesen Thread kommunizieren.

Re: tkinter und pyttsx3

Verfasst: Sonntag 4. November 2018, 21:36
von Septias
Hier der Code für das Setzen des Textes:

Code: Alles auswählen

    def set_text(self, text):
        self.text.config(state=tk.NORMAL)
        self.text.delete(1.0, tk.END)
        self.text.insert(1.0, text)
        self.text.config(state=tk.DISABLED)
        engine.say(text)
        p = multiprocessing.Process(target=engine.runAndWait)
        p.start()
@__blackjack__: Was soll mir das Code-Beispiel sagen ?

Re: tkinter und pyttsx3

Verfasst: Sonntag 4. November 2018, 22:45
von __blackjack__
@Septias: Welches Code-Beispiel? Meine Signatur? Das ist die Einschaltmeldung vom besten Computersystem ever. :-D

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 07:49
von Sirius3
Threads gehen so:

Code: Alles auswählen

from threading import Thread
from queue import Queue
def say_loop(queue):
    engine = pyttsx3.init()
    while True:
        text = queue.get()
        engine.say(text)
        engine.runAndWait()

# somewhere in __init__:
#   def __init__(self):
        self.text_queue = Queue()
        say_thread = Thread(target=say_loop, args=(self.text_queue,))
        say_thread.deamon = True
        say_thread.start()

    def set_text(self, text):
        self.text.config(state=tk.NORMAL)
        self.text.delete(1.0, tk.END)
        self.text.insert(1.0, text)
        self.text.config(state=tk.DISABLED)
        self.text_queue.put(text)

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 14:09
von Septias
Okay, vielen Dank ! Hat alles super funktioniert :)

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 15:22
von Septias
Okay, doch noch nicht vorbei... beim weiteren Testen ist mir aufgefallen, dass der Text weiter vorgelesen wird, wenn ich auf einen Button drücke. Eigentlich sollte das Vorlesen dann abgebrochen werde, und der neue Text gestartet.
Theoretisch könnte ich ja einfach die Queue raus lassen, und für jedes Sprechen einen eigenen Thread starten, und den dann vorzeitig zerstören, wenn auf einen Knopf gedrückt wird. Diese Methode scheint mir aber nicht richtig, weil sonst hätte man ja auch bei dem Beispiel oben einfach die Queue raus lassen können. Kann ich das trotzdem so machen, oder gibt es einen besseren Weg das zu realisieren ?

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 15:29
von __blackjack__
@Septias: Bietet pyttsx3 denn überhaupt einen Weg die Ausgabe abzubrechen? Threads vorzeitig zerstören, so wie Du das beschreibst, geht jedenfalls nicht.

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 15:46
von Sirius3
@Septias: man kann wohl was mit startLoop und endLoop machen. Aber da das hier kein Programmierservice ist, mußt Du Dich selbst in die Bibliothek einlesen und ausprobieren, wie das gemacht werden kann.

Re: tkinter und pyttsx3

Verfasst: Montag 5. November 2018, 21:05
von Septias
@__blackjack__: Da hab ich tatsächlichlich auch dran gedacht... nur nach dem Stellen der Frage... Also ja, so eine Funktion gibt es, und die habe ich auch dann verwendet.

Vielen Danke für die ganze Hilfe !