Etichetta in PyQt4 GUI non si aggiorna con ogni ciclo di loop

Sto avendo un problema, in cui vorrei eseguire diversi riga di comando funzioni di un programma in python che utilizza una GUI. Non so se il mio problema è specifico per PyQt4 o se ha a che fare con il mio cattivo uso di codice python.

Quello che voglio fare è avere un’etichetta sul mio GUI cambiare il suo valore di testo per informare l’utente che il comando viene eseguito. Il mio problema però sorge quando devo eseguire diversi comandi utilizzando un per loop. Vorrei l’etichetta di aggiornare ad ogni ciclo, tuttavia, il programma non è di aggiornare la GUI etichetta con ogni ciclo, invece, si aggiorna solo una volta il intero per ciclo è completato, e visualizza solo l’ultimo comando eseguito.

Sto usando PyQt4 per il mio ambiente con interfaccia grafica. E ho stabilito che la variabile di testo per l’etichetta è in fase di aggiornamento con ogni ciclo, ma non è in realtà mostrando visivamente nella GUI.

C’è un modo per me per forza l’etichetta di aggiornarsi? Ho provato il update() e repaint() metodi all’interno del ciclo, ma non fanno alcuna differenza.

Vorrei davvero apprezzare qualsiasi aiuto.
Grazie.

Ronny.

Qui è il codice che sto usando:

# -*- 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_())
InformationsquelleAutor Ronny | 2010-03-20



3 Replies
  1. 13

    L’etichetta viene aggiornato di tutti i diritti, ma l’interfaccia grafica non è ridisegnato prima della fine del ciclo.

    Ecco cosa si può fare al riguardo:

    • Spostare il lungo in esecuzione in loop per un thread secondario, disegnare la GUI sta accadendo nel thread principale.

    • Chiamata app.processEvents() nel ciclo. Questo dà Qt la possibilità di elaborare gli eventi e ridisegnare la GUI.

    • Rompere il ciclo e farlo funzionare utilizzando un QTimer con un timeout di 0.

    Con un filo è l’opzione migliore, ma richiede un po ‘ di lavoro in più, che solo chiamando processEvents. Farlo con un timer è alla vecchia maniera e non è raccomandato più. (vedere la documentazione)

    • Grazie mille! Ho trovato questa app.processEvents() solo cambiato l’etichetta dopo ogni comando era già stato completato, che era troppo tardi, e anche saltato un paio di comandi altoghether. Quello che ha funzionato è stata la creazione di un nuovo QThread oggetto con un metodo di esecuzione, e di chiamare il metodo run quando il pulsante viene premuto. È questo quello che volevi dire? Ecco il codice che ho usato. Non ho mai imparato circa la filettatura prima, quindi la prego di dirmi se ho applicato sbagliato. classe RunCommands(Core.QThread): def run(self): per i comandi: vincere.label1.setText(i) os.sistema(mi)
    • Oh, accidenti, il commento non stampare con le nuove linee e le schede io avevo inserito il 🙁
    • Che suona circa la destra, ma si dovrebbe chiamare start() invece di run().
    • Ops, sì. Grazie 🙂
  2. 2

    Si dispone di una incomprensione di base di come una GUI funziona. Qt GUI deve eseguire in un ciclo di eventi della propria. Il ciclo viene eseguito invece, e la GUI non può fare il suo lavoro tra le esecuzioni del ciclo. Che è, mentre il for ciclo è in esecuzione il codice GUI non avere il tempo di CPU e non di aggiornamento.

    È possibile impostare un timer con un evento, ed eseguire il codice gestori di questo evento un periodo di tempo – questo risolverà il tuo problema.

    • Grazie per la spiegazione nel 1 ° paragrafo del tuo reply. Ora mi dà un po ‘di più di una comprensione di ciò che sta succedendo, e mi aiuta a capire il ragionamento dietro di Georg risposta un po’ meglio. Comunque, non capisco la soluzione che lei propone. Io sono un principiante nella programmazione. Forse un semplice schizzo del codice che sarebbero coinvolti sarebbe utile. Anche se ora ho trovato una soluzione che sembra funzionare, sarei molto curioso di conoscere i tuoi alternativa proposta così.
    • conoscere QTimer e guardare alcuni esempi del suo utilizzo, penso che sarà chiaro a voi

Lascia un commento