Qt - czasochłonna operacja a brak płynności GUI

0

Nie tak dawno temu założyłem temat w którym prosiłem o pomoc w poprawnym użyciu wątku w Qt. Zrozumiałem na czym to polega i w swoim programie pewną czasochłonną operacje wrzucam właśnie do nowego wątku i teraz...

Odpalam funkcje w nowym wątku, GUI nie jest zablokowane - świetnie ;) ale gdy odpalam przy tym procesie dodatkowe okno np QProgressDialog żeby pokazać w jakiś sposób postęp prac to automatycznie moje GUI traci "płynność". Rozumiem że ten QProgressDialog działa w tym samym wątku co główne GUI ale żeby od razu tracić płynność? to nie jest aż tak skomplikowany program...

Czy możecie podsunąć mi jakiś pomysł jak mogę to rozwiązać? być może problemem jest słaby komputer i nic z tym zrobić się po prostu nie da ale może...

0

Przeciez znasz już odpowiedź. Niech ten dialog leci w nowym wątku...

0

Powinieneś z wątku roboczego przesyłać tylko informację o postępie a okno wyświetlać z wątku głównego.

0

No jest to jakieś rozwiązanie ale zastanawiam się czy aby właściwe bo ten dialog ma "tylko" pokazywać postęp pracy funkcji która już jest w innym wątku więc wyszło by na to że dla tej jednej operacji potrzebuje już 2 wątków ( jedna na wykonywanie funkcji druga na progressdialog ) a gdybym w trakcie tej operacji i wyświetlania dialogu chciał skorzystać z głównego GUI i tam sobie robić coś jeszcze innego to na ta kolejna operacje / kolejne otwarte okienko musiałbym tworzyć kolejny wątek...

Czy takie podejście jest właściwe? Albo inaczej czy to normalne że tak szybko tracę płynność okna jak teraz np po otwarciu QProgressDialog? Bo nie ukrywam że to dziwne trochę.

0

Nie jest to normalne. W jaki sposób aktualizujesz ten status? Bo mam nadzieje że nie masz tam magicznej pętli while(true) która pobiera status i go wyświetla? Jest tam jaki observer?

0

Najpierw tworze sobie ten Dialog

QProgressDialog progressDialog;
progressDialog.setWindowModality( Qt::WindowModal );
progressDialog.setCancelButtonText(tr("&Cancel"));
progressDialog.setRange( 0, mcapacity );
progressDialog.setWindowTitle(tr("Proccess"));
progressDialog.setMinimum( 0 );
progressDialog.setMaximum( 0 );

i "pętelka"

for( unsigned int i = 0; i < mcapacity; ++i ) {

            progressDialog.setValue( i );
            progressDialog.setLabelText(tr("Process...") );

            if( progressDialog.wasCanceled() )
                break;

            qApp->processEvents();
        }
2

Nie wiem co to za koda pokazałeś i jak to się ma do wątku, który przetwarza dane, ale wygląda to dziwnie i raczej nieprawidłowo.

To powinno być tak: wątek powinien emitować sygnały informujące o postępie przetwarzania a QProgressDialog powinien je tylko odbierać (przy standardowym połączeniu dane powinny być automatycznie przekazywane pomiędzy wątkami, więc nie ma co się martwić o główny wątek).
Jeśli tak zrobiłeś i nadal to ci przytyka główny wątek to oznacza, tylko tyle, że emitujesz za dużo sygnałów o aktualizacji postępu prac i w ten sposób zapychasz event loopa głównego wątku. Czyli musisz jedynie ograniczyć ilość emitowanych sygnałów.
Podejść jest kilka:

  • ja preferuję ograniczyć całkowita ilość aktualizacji - 1000 a nawet 100 aktualizacji to juz bardzo dużo i w przypadku QProgressBar użytkownik i tak nie zauważy pojędyńczej zmiany, więc nie ma sensu pokazywać tak częstych uaktualnień
  • można też nałożyć wymóg czasowy, że od ostatniej aktualizacji musi minąć np 0.2 sekundy (częściej niż 60Hz i tak nie ma sensu bo i tak monitor nie nadąży)
0

Okazało się że jak odpalę ten program poza Qt to działa płynnie tak jak powinno... tylko odpalając program bezpośrednio pod Qt łapie takie rzeczy.
MarekR22 masz racje, niepotrzebnie emituje sygnał w każdym przebiegu pętli. Zastosuje się do tego co napisałeś dzięki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1