2010-05-10 23 views
6

Il mio primo ingenuo ad aggiornare la mia barra di avanzamento è stato quello di includere le seguenti righe nel mio ciclo che sta facendo l'elaborazione, fare qualcosa di simile a questo:QProgressBar non mostra progressi?

while(data.hasMoreItems()) 
{ 
    doSomeProcessing(data.nextItem()) 

    //Added these lines but they don't do anything 
    ui->progressBar->setValue(numberProcessed++); 
    ui->progressBar->repaint(); 
} 

ho pensato di aggiungere il repaint() renderebbe la pausa di esecuzione, mentre l'aggiornamento continuo la GUI, ma a quanto pare non è così semplice. Dopo aver guardato le domande:

QProgressBar Error
Progress bar is not showing progress

sembra che ho intenzione di mettere il trattamento dei dati in un thread diverso e poi collegare un segnale dal thread di elaborazione dei dati al thread GUI per aggiornare la barra di avanzamento. Sono piuttosto inesperto con GUI e thread e mi chiedevo se qualcuno potesse semplicemente indicarmi la direzione giusta, cioè quali classi di Qt dovrei considerare per questo. Direi che ho bisogno di un oggetto QThread, ma ho esaminato la documentazione di QProgressBar ma non viene visualizzato l'argomento del threading.

risposta

9

Come @rjh e @Georg hanno sottolineato, ci sono essenzialmente due diverse opzioni: trattamento

  1. Forza di eventi utilizzando QApplication::processEvents() O
  2. Creare un thread che emette segnali che possono essere usati per modificare la barra di avanzamento

Se si sta eseguendo qualsiasi elaborazione non banale, si consiglia di spostare l'elaborazione su un thread.

La cosa più importante da sapere sui thread è che, ad eccezione del thread GUI principale (che non viene avviato o creato), non è possibile aggiornare la GUI direttamente da una thread.

L'ultimo parametro di QObject::connect() è un enum Qt::ConnectionType che per impostazione predefinita prende in considerazione se i thread sono coinvolti.

Pertanto, si dovrebbe essere in grado di creare un semplice sottoclasse di QThread che fa del trattamento:

class DataProcessingThread : public QThread 
{ 

public: 
    void run(); 
signals: 
    void percentageComplete(int); 
}; 

void MyThread::run() 
{ 
    while(data.hasMoreItems()) 
    { 
     doSomeProcessing(data.nextItem()) 
     emit percentageCompleted(computePercentageCompleted()); 
    } 
} 

E poi da qualche parte nel codice GUI:

DataProcessingThread dataProcessor(/*data*/); 
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int)); 
dataProcessor.start(); 
1

È possibile creare una sottoclasse di QThread che emette un segnale progressChanged, che si connette allo QProgressBar.

connect() rende le connessioni auto connections per impostazione predefinita. Ciò significa che il meccanismo dello slot del segnale si occupa già dei problemi di threading, quindi non devi preoccuparti di questo.

3

È necessario chiamare periodicamente lo QApplication::processEvents() all'interno del ciclo di elaborazione per consentirne la gestione degli eventi dell'interfaccia utente.

Come dice Georg, Qt è un ambiente multitasking cooperativo a thread singolo. Hai il pieno controllo del tuo processo fino a quando non lo cessi volontariamente con processEvents() - fino a quando non lo fai, Qt non può aggiornare gli elementi dell'interfaccia utente, gestire richieste HTTP asincrone, gestire input, o praticamente qualsiasi altra cosa. Spetta a te assicurarti che tutto ciò si trasformi in un timeslice mentre sei in un lungo ciclo di elaborazione.