2016-04-15 5 views
1

3 Sub-Fragen:
[1] Python GUIs sind Abfrage basiert?
Es scheint mir, dass sowohl tk als auch qtpy polling-basiert sind, wenn die GUI eine Funktion aufruft, die eine Weile braucht, um die gesamte GUI zu hängen.
Ich habe vor langer Zeit über Gui gelernt, erinnerte ich mich, dass moderne GUI sollte Interrupt-basierte sein, auch wenn Gui etwas großes ausgeführt, sollte Gui die ganze Zeit reagieren. gui kann das Ergebnis aus diesen großen Berechnungen nicht angezeigt werden, aber es wird reagieren Taste, um die Größe, zeigen Sie auf Animation usw. Also meine Frage ist, gibt es eine Option, wie:
Python3, Verstehen der "GUI-Schleife" wie in tkinter-Hauptschleife() oder QtPy-exec_()

#psuedo code 
    root=tkinter.Tk() 
    root.setInterruptMode(True) 

[2] Ist Tk.mainloop() nur eine gigantische Schleife?
Wenn meine erste Frage ein Pipe-Traum ist, und ich nur über Threading und Multiprozess erfahren muss, dann ist meine nächste Frage über root.mainloop() (oder qtpys exec_()).
Mein Eindruck ist, dass Mainloop() nicht wirklich einen Thread oder irgendetwas in Python startet, es packt einfach eine gigantische und unsichtbare Tkinter's GUI-Polling + Malschleife in meine Hauptzeile. Ist mein Eindruck richtig?

[3] warum Hauptleitung in Hauptleitung setzen?
Muss sich mainloop() in der Hauptleitung befinden? kann ich es fädeln/multiprocessing? damit sich meine Main-Linie auf große Berechnungen konzentrieren kann und die Main-Linie die GUI-Prozesse und IO-Prozesse regelt. Alle Beispiele, die ich gefunden habe, haben mainloop() in der Hauptleitung, ich bin nicht sicher, dass es ein empfohlener Ansatz ist oder was die Vorteile sind.

Im Folgenden wird der Code, den ich schrieb bei dem Versuch, über Python gui zu lernen:

import tkinter 
    import random 

    class myGUI(): 
     def __init__(self, arg_tkroot): 
      self.GUI_display = tkinter.Label(arg_tkroot, text='init-ed') 
      self.GUI_button = tkinter.Button(arg_tkroot, text='click') 
      self.GUI_display.pack() 
      self.GUI_button.pack() 

      self.GUI_button.bind('<Button-1>', self.handle_user_interaction) 
      self.list_bigData = [] 

     #handles GUI interaction, and call bigData_and_bigCalculation() 
     def handle_user_interaction(self, arg_event): 
      print(arg_event, ' detected by myGUI') 
      strResult_toFeedbackToUser = self.bigData_and_bigCalculation() 
      self.GUI_display.config(text=strResult_toFeedbackToUser) 
      print('finished handling user interact') 

     # slow calculations and memory consuming operations 
     def bigData_and_bigCalculation(self): 
      self.list_bigData[:]=[] 
      for i in range(500000): 
       self.list_bigData.append(''.join(random.choice('asdfas') for k in range(10))) 
      return self.list_bigData[-1] 
    # Main() 
    if __name__ == '__main__': 
     root = tkinter.Tk() 
     mygui = myGUI(root) 
     root.mainloop() 
+1

Nun, wenn Sie einen langen Job im GUI-Thread ausführen, wird die GUI einfrieren. Um dies zu vermeiden, erstellen Sie verschiedene Threads für verschiedene Jobs. – ForceBru

+0

interessante Frage; Ich habe über 10 kleine und eine durchschnittliche Größe App in Tk geschrieben (keine in Qt) hatte nie Reaktionsfähigkeit Isues und dachte nie über eine Art und Weise Tk ist es GUI :) Ich empfehle ForceBru adwise im Allgemeinen zu folgen; und übrigens habe ich Kivy für meine GUI-Apps verwendet, kann empfehlen, es ist flexibler als Tk und funktioniert auch gut auf Android und iOS. – Drako

+0

Ich hatte Angst, Threading und Multiprozess zu verwenden ist unvermeidlich. Aber in meiner ersten Teilfrage, was ich vorher über "interrupt" -basiertes gui (Java-Applet damals) gelernt habe, habe ich nie auf gui freeze zurückgegriffen, das war ein falscher Eindruck, weil wir nie große Berechnungen gemacht haben, während wir diese Dinge gelernt haben? – YunliuStorage

Antwort

1

[1] GUIs werden Polling basiert?

GUIs sind ereignisbasiert - alles, was in einer GUI passiert, ist eine Reaktion auf ein Ereignis. Wie die Anwendung das Ereignis behandelt, hängt von der Anwendung ab. Wenn die Behandlung des Ereignisses in einigen hundert Millisekunden oder weniger stattfinden kann, kann es im Hauptthread behandelt werden. Wenn es länger dauert, sollte die Anwendung den Code in einem separaten Thread oder Prozess ausführen.

Im Falle von Tkinter ist Tkinter für die Ausführung in einem einzigen Thread ausgelegt. Das bedeutet nicht, dass Sie keine Threads verwenden können, sondern dass alle Zugriffe auf tkinter-Objekte in einem einzigen Thread sein sollten. Die übliche Vorgehensweise besteht darin, dass andere Threads über eine Thread-sichere Warteschlange mit der GUI kommunizieren und der GUI-Thread dafür zuständig ist, diese Warteschlange regelmäßig zu überprüfen.

Also meine Frage ist, gibt es eine Option, wie [root.setInterruptMode(True)]

In tkinter, nein, es gibt keine Möglichkeit, einen speziellen "Interrupt" Modus zu gelangen.

[2] Es ist nur eine gigantische Schleife?

Ich nehme an mit "it" meinen Sie den Anruf an mainloop. Ja, es ist eine gigantische Schleife. Oder vielleicht genauer, es ist eine kleine Schleife. Es wartet nur auf ein Ereignis, dann sucht es den Handler für das Ereignis und führt den Handler aus.

Mein Eindruck ist, dass mainloop() nicht wirklich einen Thread oder etwas in Python

Richtig starten. Es wird die Ereignisschleife im aktuellen Thread ausgeführt.

[3] warum putting loop in Main line?

Sie müssten die ursprünglichen Entwickler fragen. Wahrscheinlich ist es, weil das alles ist, was für einen sehr, sehr großen Prozentsatz von Anwendungen notwendig ist (vielleicht mehr, als das Toolkit erfunden wurde, als es jetzt ist).

Tkinter ist nichts als ein Wrapper um einen Tcl Interpreter mit dem tk Toolkit im Interpreter geladen. tcl/tk wurde entwickelt, um in andere Anwendungen eingebettet zu werden, also musste es leicht sein und auf Systemen laufen können, die Threads nicht unterstützen (tcl ist alt genug, dass Thread-Unterstützung nicht auf jeder Plattform garantiert war)

Muss sich die Hauptschleife() in der Hauptleitung befinden? kann ich es fädeln/multiprocessing?

mainloop() muss in demselben Thread ausgeführt werden, der das Stammfenster erstellt hat. Wenn Sie Threads benötigen (und das wiederum ist sehr wahrscheinlich, dass Sie das nicht tun), können Sie Ihre Event-Handler sicherlich in einem separaten Thread ausführen. Es fügt Komplexität hinzu, aber es ist da, wenn Sie es brauchen. Für eine große Klasse von Programmen gibt es einfach nicht so viel Komplexität.

Sie sollten in der Lage sein, einen Worker-Thread zu erstellen und Ihre GUI von dort zu erstellen und auszuführen. Ich habe es nie versucht, aber ich sehe keinen Grund, warum es nicht funktionieren würde. Tkinter ist es egal, dass es der Hauptthread ist, nur dass der gesamte tkinter-Code im selben Thread läuft.

Alle Beispiele, auf die ich gestoßen bin, haben eine Hauptschleife() in der Hauptleitung, ich bin mir nicht sicher, ob es ein empfohlener Ansatz ist oder welche Vorteile es hat.

Aufruf von mainloop im Haupt-Thread ist wie tkinter entwickelt wurde, um zu arbeiten. Wenn Sie lange Berechnungen ausführen, sollten Sie diese Berechnungen in einem separaten Thread oder Prozess ablegen.

+0

Vielen Dank für die Schritt für Schritt Antwort, ich werde auf jeden Fall Threads oder Prozesse benötigen, ich habe zu viele IOs und Obscene Menge an großen Datenstrukturen.Was mich interessiert, ist, dass Sie in Ihrer vorherigen Antwort auf eine ähnliche Frage, die von anderen Helfern hier zitiert wurde, erwähnt haben, dass Sie nicht im Thread-Modus laufen können. aber du scheinst jetzt zu sagen, es ist in Ordnung, es zu tun. – YunliuStorage