[QT4] Wątki i progressBar

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Macok
Sędziwy Jeż
Sędziwy Jeż
Posty: 85
Rejestracja: 12 sty 2008, 13:40
Płeć: Mężczyzna
Wersja Ubuntu: 7.04
Środowisko graficzne: GNOME

[QT4] Wątki i progressBar

Post autor: Macok »

Na podstawie artykułu z http://cc-team.org/index.php?name=artykuly&show=161 napisałem sobie funkcję "void * watek()".
W programie jest ona wykonywana jako wątek i co kilka sekund powinna zwiększać postęp paska postępu (progressBar).
Problem w tym, że aby mieć dostęp do tego progressBara funkcja "void * wątek()" musiałaby sie znajdować w klasie Form1.
Niestety nie moge utworzyć wątku z funkcji, która znajduje się w jakiejś klasie.
Jak rozwiązać ten problem?
Może należy użyć wątków z Qt, a nie linuksowych?
Z góry dzięki za odp!
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

Za wątki w Qt jest odpowiedzialna klasa QThread - poczytaj sobie jej dokumentację w QtAssistant.
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
Macok
Sędziwy Jeż
Sędziwy Jeż
Posty: 85
Rejestracja: 12 sty 2008, 13:40
Płeć: Mężczyzna
Wersja Ubuntu: 7.04
Środowisko graficzne: GNOME

Odp: [QT4] Wątki i progressBar

Post autor: Macok »

Dzieki, przepisałem wszystko tak żeby uzywało QThread ale dalej mam podobny problem.
Jest sobie taka klasa:

Kod: Zaznacz cały

         class MyThread : public QThread
         {
         public:
             void run();
         };

         void MyThread::run()
         {
	   while(1){
	     //TUTAJ ZWIEKSZANIE PROGRESSBARA
                        sleep(5);
	   }
             exec();
         }
No i wszystko fajnie, ale jak teraz z funkcji run(), która znajduje się w klasie MyThread dostać się do ProgressBara który jest chyba w klasie Form1?
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

No i wszystko fajnie, ale jak teraz z funkcji run(), która znajduje się w klasie MyThread dostać się do ProgressBara który jest chyba w klasie Form1?
Bardzo prosto. Możesz np. do klasy MyThread dodać pole QProgressBar *m_progressBar; oraz utworzyć konstruktor MyThread(QProgressBar *pb); w którym do pola m_progressBar przypiszesz wskaźnik pb. Wtedy tworząc wątek, jako argument podajesz wskaźnik paska postępu, a w klasie MyThread zwiększasz wartość paska postępu m_progressBar.
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
Macok
Sędziwy Jeż
Sędziwy Jeż
Posty: 85
Rejestracja: 12 sty 2008, 13:40
Płeć: Mężczyzna
Wersja Ubuntu: 7.04
Środowisko graficzne: GNOME

Odp: [QT4] Wątki i progressBar

Post autor: Macok »

Dzieki, chyba rozumiem.
Jeszcze tylko 3 małe pytania, jak czegoś nie będe jeszcze umiał zrobić to reszta wieczorem :)

1. Wskaźnik do paska postępu uzyskuje sie poprostu pisząc ui.progressBar?

2. Po co w funkcji run() w wątkach jest ta funkcja exec()?

3. Po uruchomieniu jakiegoś wątku w konsoli pojawia mi się coś takiego:
QThread: Destroyed while thread is still running
To normalne, czy jest jakiś błąd (niby wszystko działa poprawnie)?
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

1. Wskaźnik do paska postępu uzyskuje sie poprostu pisząc ui.progressBar?
Jeśli formatkę robiłeś w Designerze, to tak.
2. Po co w funkcji run() w wątkach jest ta funkcja exec()?
Ta funkcja robi dokładnie to samo, co funkcja o tej samej nazwie w klasie Q(Core)Application - powoduje, że wątek jest cały czas uruchomiony (w przypadku, gdy funkcja ta jest wywołana na koniec metody run(), inaczej możesz ją zastosować do wstrzymania wątku), dopóki nie wywoałasz w nim slotu quit().
3. Po uruchomieniu jakiegoś wątku w konsoli pojawia mi się coś takiego:
Cytat:
QThread: Destroyed while thread is still running
To dlatego, że wątek był uruchomiony, gdy aplikacja została zamknięta. Rozwiązanie: usuń exec() w metodzie run() - w tym wypadku wywołanie to jest zbędne.
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
przybysh
Piegowaty Guziec
Piegowaty Guziec
Posty: 8
Rejestracja: 28 sty 2006, 15:59
Płeć: Mężczyzna
Wersja Ubuntu: 7.10
Środowisko graficzne: GNOME
Kontakt:

Odp: [QT4] Wątki i progressBar

Post autor: przybysh »

A może wystarczyło użyć slotów i sygnałów i co jakiś czas wysyłać z wątku sygnał aby aktualizować progress bar??
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

przybysh pisze:A może wystarczyło użyć slotów i sygnałów i co jakiś czas wysyłać z wątku sygnał aby aktualizować progress bar??
Też można. To, co wybierasz zależy od wielu czynników. Poza tym przekazywanie wskaźnika jest wydajniejsze, chociaż sygnały i sloty w tym przypadku również byłyby na miejscu.
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
Macok
Sędziwy Jeż
Sędziwy Jeż
Posty: 85
Rejestracja: 12 sty 2008, 13:40
Płeć: Mężczyzna
Wersja Ubuntu: 7.04
Środowisko graficzne: GNOME

Odp: [QT4] Wątki i progressBar

Post autor: Macok »

No dobra mam klase wątku:

Kod: Zaznacz cały

class MyThread : public QThread
{
 public:
  void run();
  QProgressBar *pb;
};
Przy starcie programu tworzę obiekt MyThread thread i przypisuje thread.pb=ui.progressBar;
Wszystko niby działa jak powinno, np. pb->value(); zwraca odpowiednią wartość, niestety gdy wpisze pb->setValue(5); w konsoli pojawia się coś takiego:

Kod: Zaznacz cały

QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QPainter::begin: Cannot paint on a null pixmap
QPixmap: It is not safe to use pixmaps outside the GUI thread
a
X Error: RenderBadGlyphSet (invalid GlyphSet parameter) 179
  Extension:    154 (RENDER)
  Minor opcode: 25 (RenderCompositeGlyphs32)
  Resource id:  0x0
X Error: RenderBadGlyphSet (invalid GlyphSet parameter) 179
  Extension:    154 (RENDER)
  Minor opcode: 25 (RenderCompositeGlyphs32)
  Resource id:  0x0
X Error: RenderBadGlyphSet (invalid GlyphSet parameter) 179
  Extension:    154 (RENDER)
  Minor opcode: 25 (RenderCompositeGlyphs32)
  Resource id:  0x0
X Error: RenderBadGlyphSet (invalid GlyphSet parameter) 179
  Extension:    154 (RENDER)
  Minor opcode: 25 (RenderCompositeGlyphs32)
  Resource id:  0x0
Może zastosuje sie do tego co napisał przybysh?
A może wystarczyło użyć slotów i sygnałów i co jakiś czas wysyłać z wątku sygnał aby aktualizować progress bar??
W jakis posób wysłać taki sygnał?

Z góry dzięki za pomoc.
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

Pokaż cały kod.

Jeśli chcesz zastosować sygnały i sloty, to będzie to wyglądało podobnie do tego:

Kod: Zaznacz cały

class MyThread : public QThread
{
    Q_OBJECT
public:
    void run();
signals:
    void incrementPb(int value);
};

Kod: Zaznacz cały

void MyThread::run()
{
    //...
    emit incrementPb(twojaWartosc);
}
A w klasie, w której używasz wątku wystarczy zrobić połączenie po zainicjalizowaniu formatki i wątku:

Kod: Zaznacz cały

connect(obiektWatku, SIGNAL(incrementPb(int)), obiektPaskPostepu, SLOT(setValue(int)));
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
Macok
Sędziwy Jeż
Sędziwy Jeż
Posty: 85
Rejestracja: 12 sty 2008, 13:40
Płeć: Mężczyzna
Wersja Ubuntu: 7.04
Środowisko graficzne: GNOME

Odp: [QT4] Wątki i progressBar

Post autor: Macok »

Dzięki wszystkim (szczególnie Adrianowi :P).
Udało się wreszcie.
Korzystając z okazji zadam w tym temacie ostatnie pytanie:
Napisałem coś takiego:

Kod: Zaznacz cały

  QFile f(file);
  f.open(QIODevice::WriteOnly | QIODevice::Text);
  QTextStream out(&f);
  out<<"napis";
W ten sposób probowałem dopisać coś na końcu pliku, ale zamiast tego powoduje to jego nadpisanie.
Jak dopisać coś na końcu pliku?
adrian5632
Przyjaciel
Przyjaciel
Posty: 259
Rejestracja: 17 gru 2006, 16:07
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: adrian5632 »

Do flag otwarcia pliku dodaj jeszcze QIODevice::Append.
[IMG]http://www.ubudsl.com/media/UbuDSL.png[/IMG]
Masz problem z UbuDSL? Nie zapomnij wygenerować i załączyć loga do postu!
skoczo
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 176
Rejestracja: 09 kwie 2008, 11:40
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: [QT4] Wątki i progressBar

Post autor: skoczo »

Witam rowniez mam problem z paskiem postepu. Utworzylem okno z paskiem i klase ktora sluzy do symulacji. Chce teraz aby podczas obliczen postep widac bylo na pasku.

Kod: Zaznacz cały

class symulacja : public QThread
{
        Q_OBJECT
        private:
            double  a, mu, f, TM, mem;
            QString *tab;
            QMutex *mut;
	public:
                QProgressBar *pr;
                symulacja(double,double,double,double,double,QString *,QProgressBar *,QMutex *);
                void run();
	
	private:
		double generacja(double x);
		double min(double a,double b, double c);
        signals:
                void incrementPb(int);

};
Kod wywolany po nacisnieciu przycisku.

Kod: Zaznacz cały

symulacja *nowa=new symulacja(s_a.toDouble(),s_mu.toDouble(),s_f.toDouble(),s_TM.toDouble(),s_mem.toDouble(),tab,ui->progressBar,mut);
connect(nowa, SIGNAL(incrementPb(int)), ui->progressBar, SLOT(setValue(int)));
Błędy kompilacji

Kod: Zaznacz cały

/home/skoczo/symulacja2/symulacja.cpp:18: undefined reference to `vtable for symulacja'
/home/skoczo/symulacja2/symulacja.cpp:18: undefined reference to `vtable for symulacja'
/home/skoczo/symulacja2/symulacja.cpp:57: undefined reference to `symulacja::incrementPb(int)':-1: error: collect2: ld returned 1 exit status
Proszę o pomoc. Mutex był dodany wcześniej teraz nie jest używany.

Edit: To jak pomoże mi ktoś?
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: mikolajs »

Tego typu błędy miałem gdy nie usunąłem wcześniejszych plików obiektowych. Spróbój wyczyścić wszystkie pliki kompilacji i od nowa qmake i make
skoczo
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 176
Rejestracja: 09 kwie 2008, 11:40
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: [QT4] Wątki i progressBar

Post autor: skoczo »

Kompiluje qt-creatorem wiec to chyba nie to ale jak usune connecty z kodu to bledow nie ma wiec to chyba gdzies tu jest blad.

EDIT:
Opisze mój problem dokładniej bo może źle to zrobiłem. Mianowicie mam klase służącą do obliczeń. Wykonuje ona TM kroków zaczynając zawsze od 0. Klasa ta jest wątkiem QThread. Obliczanie działa, tylko teraz chcę aby wraz ze zmianą kroków poruszał się pasek postępu. Na początku przekazałem wskaźnik do paska i w funkcji run ustawialem postep ale wyskakiwal mi blad. Wiem ze trzeba to zrobic connectami ale nie mam pojęcia jak. Szukałem odpowiedzi na forach i są podobne tematy ale jak probuje tak kodowac to mam inne bledy. Pomozcie mi jak to zrobic?
Awatar użytkownika
kabanek
Zakręcona Traszka
Zakręcona Traszka
Posty: 592
Rejestracja: 23 cze 2009, 20:34
Płeć: Mężczyzna
Wersja Ubuntu: 13.10
Środowisko graficzne: Xfce
Architektura: x86_64
Kontakt:

Odp: [QT4] Wątki i progressBar

Post autor: kabanek »

jak masz funkcję i jakąś klasę, i z poziomu tej funkcji sięgnąć do bebechów klasy to można je zaprzyjaźnić:)
skoczo
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 176
Rejestracja: 09 kwie 2008, 11:40
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Odp: [QT4] Wątki i progressBar

Post autor: skoczo »

Jeśli klasa nie jest wątkiem to jest ok ale jak zrobie ją wątkiem to wtedy jest problem. dostęp do el mam poprzez wskaźnik do elementu. Zaprzyjaźniłem klasy i niestety nic to nie dało.
mikolajs
Wytworny Kaczor
Wytworny Kaczor
Posty: 352
Rejestracja: 15 paź 2008, 18:30
Płeć: Mężczyzna
Wersja Ubuntu: 9.04
Środowisko graficzne: KDE Plasma

Odp: [QT4] Wątki i progressBar

Post autor: mikolajs »

Kompiluje qt-creatorem wiec to chyba nie to ale jak usune connecty z kodu to bledow nie ma wiec to chyba gdzies tu jest blad.
Tym bardziej może chodzić o to (w końcu qt-creator wywołuje qmake)
Pojawiający się błąd dotyczy linkera i to na dodatek tablicy metod wirtualnych. Albo nie zdefiniowałeś tych metod, albo pliki obiektowe nie zostały odświeżone. Spróbuj usunąć wszystkie pliki poza plikami źródłowymi, zajmie Ci to mało czasu, może nie zadziała ale warto spróbować!
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 10 gości