2010-03-20 3 views
6

Ich habe ein Problem, wo ich mehrere Befehlszeilenfunktionen aus einem Python-Programm mit einer GUI ausführen möchten. Ich weiß nicht, ob mein Problem spezifisch für PyQt4 ist oder ob es mit meiner schlechten Verwendung von Python-Code zu tun hat.Label in PyQt4 GUI nicht mit jeder Schleife der FOR-Schleife aktualisieren

Was ich tun möchte, ist eine Beschriftung auf meiner GUI ändern Sie den Text Wert, um den Benutzer zu informieren, welcher Befehl ausgeführt wird. Mein Problem tritt jedoch auf, wenn ich mehrere Befehle unter Verwendung einer für Schleife ausführen. Ich möchte, dass sich das Label mit jeder Schleife selbst aktualisiert, das Programm aktualisiert jedoch nicht die GUI-Beschriftung mit jeder Schleife, sondern aktualisiert sich erst, wenn die Schleife vollständig ist und zeigt nur den letzten Befehl an das wurde ausgeführt.

Ich verwende PyQt4 für meine GUI-Umgebung. Und ich habe festgestellt, dass die Textvariable für das Label tatsächlich mit jeder Schleife aktualisiert wird, aber es wird nicht wirklich visuell in der GUI angezeigt.

Gibt es eine Möglichkeit für mich, das Etikett zu aktualisieren? Ich habe versucht, die update() und repaint() Methoden innerhalb der Schleife, aber sie machen keinen Unterschied.

Ich würde wirklich jede Hilfe zu schätzen wissen. Danke.

Ronny. Hier

ist der Code, ich verwende:

# -*- coding: utf-8 -*- 
import sys, os 
from PyQt4 import QtGui, QtCore 
Gui = QtGui 
Core = QtCore 

# ================================================== CREATE WINDOW OBJECT CLASS 
class Win(Gui.QWidget): 
    def __init__(self, parent = None): 
     Gui.QWidget.__init__(self, parent) 

     # --------------------------------------------------- SETUP PLAY BUTTON 
     self.but1 = Gui.QPushButton("Run Commands",self) 
     self.but1.setGeometry(10,10, 200, 100) 

     # -------------------------------------------------------- SETUP LABELS 
     self.label1 = Gui.QLabel("No Commands running", self) 
     self.label1.move(10, 120) 

     # ------------------------------------------------------- SETUP ACTIONS 
     self.connect(self.but1, Core.SIGNAL("clicked()"), runCommands) 


# ======================================================= RUN COMMAND FUNCTION 
def runCommands(): 
    for i in commands: 
     win.label1.setText(i)  # Make label display the command being run 
     print win.label1.text()  # This shows that the value is actually 
            # changing with every loop, but its just not 
            # being reflected in the GUI label 
     os.system(i) 

# ======================================================================== MAIN 

# ------------------------------------------------------ THE TERMINAL COMMANDS 
com1 = "espeak 'senntence 1'" 
com2 = "espeak 'senntence 2'" 
com3 = "espeak 'senntence 3'" 
com4 = "espeak 'senntence 4'" 
com5 = "espeak 'senntence 5'" 
commands = (com1, com2, com3, com4, com5) 

# --------------------------------------------------- SETUP THE GUI ENVIRONMENT 
app = Gui.QApplication(sys.argv) 
win = Win() 
win.show() 

sys.exit(app.exec_()) 

Antwort

10

Das Label alles in Ordnung aktualisiert wird, aber die GUI ist nicht vor Ende der Schleife neu gezeichnet.

Hier ist, was Sie dagegen tun können:

  • Bewegen Sie die Langlaufschleife zu einem sekundären Thread, zeichnen die GUI im Hauptthread geschieht.

  • Rufen Sie app.processEvents() in Ihrer Schleife. Dies gibt Qt die Möglichkeit, Ereignisse zu verarbeiten und die GUI neu zu zeichnen.

  • Ihren Loop Break up und lassen Sie es ein QTimer mit einem Timeout von 0.

Mit einem Thread ausgeführt verwendet, ist die beste Option, ist aber mit einem bisschen mehr Arbeit als nur process Aufruf . Es ist altmodisch und wird nicht mehr empfohlen. (Siehe die Dokumentation)

+0

Vielen Dank! Ich fand diese App.processEvents() änderte die Beschriftung nur, nachdem jeder Befehl bereits abgeschlossen wurde, was zu spät war, und übersprang auch einige Befehle. Woran arbeitete work ein neues QThread-Objekt mit einer run-Methode und rief die run-Methode auf, wenn die Schaltfläche gedrückt wurde. Hast du das gemeint? Hier ist der Code, den ich verwendet habe. Ich habe noch nie etwas über das Threading erfahren, also sag mir bitte Bescheid, wenn ich es unklug angewendet habe. Klasse RunCommands (Core.QThread): def laufen (self): für i in Befehle: win.label1.setText (i) os.system (i) – Ronny

+0

Ohh, meine Güte, knapp über der Kommentar auszudrucken mit die neuen Linien und Tabs, die ich eingegeben hatte :( – Ronny

+0

@Ronny: Das klingt nach rechts, aber Sie sollten 'start()' anstelle von 'run()' anrufen. –

2

Sie haben ein grundlegendes Missverständnis, wie eine solche GUI funktioniert. Eine Qt-GUI muss in einer eigenen Ereignisschleife laufen. Ihre Schleife wird stattdessen ausgeführt, und die GUI kann ihre Arbeit zwischen den Ausführungen Ihrer Schleife nicht ausführen. Das heißt, während Ihre for Schleife ausgeführt wird, erhält der GUI-Code keine CPU-Zeit und wird nicht aktualisiert.

Sie können einen Timer mit einem Ereignis einrichten und Ihren Code in den Handlern dieses Ereignisses eine bestimmte Zeit lang ausführen - damit wird Ihr Problem gelöst.

+1

Danke für die Erklärung in der erste Absatz Ihrer Antwort. Es gibt mir jetzt ein bisschen mehr Verständnis dafür, was vor sich geht, und hilft mir, die Gründe hinter Georgs Antwort ein wenig besser zu verstehen. Ich verstehe jedoch nicht die tatsächliche Lösung, die Sie vorschlagen. Ich bin ein sehr Anfänger in der Programmierung. Vielleicht wäre eine einfache Skizze des Codes hilfreich. Obwohl ich jetzt eine Lösung gefunden habe, die zu funktionieren scheint, wäre ich sehr neugierig, Ihre vorgeschlagene Alternative auch zu erfahren. – Ronny

+0

@Ronny: Informieren Sie sich über QTimer und sehen Sie sich einige Beispiele seiner Verwendung an - ich denke, es wird Ihnen klar werden –

Verwandte Themen