На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
Страницы: (6) « Первая ... 3 4 [5] 6  все  ( Перейти к последнему сообщению )  
> QDialog
    Цитата Flex Ferrum @
    Зачем? Это сообщение может отобразить сам диалог. Зачем мессаджбокс еще показывать?

    бр.... я совсем запутался. диалог вообще ничего ни о чем не знает. его задача - просто например крутить часики.
    Да и к тому же если он отобразит его, то поверх себя.

    А зачем - для того. чтобы GUI-поток отобразил строку ошибки. Ведь для этого нужен был ThreadError ?


    Цитата Flex Ferrum @
    В таком случае, у тебя:
    1) Функция не завершится до тех пор, пока не отработает поток.
    2) Во время работы потока будет висеть диалог и ждать его завершения.
    Собственно, это именно то, что тебе нужно, на сколько я смог понять.


    так - нужен перерыв для обмозгования :) я окончательно запутался. Попробую что-нибудь сделать а там будет видно :)
      Цитата zss @
      я совсем запутался. диалог вообще ничего ни о чем не знает. его задача - просто например крутить часики.
      Да и к тому же если он отобразит его, то поверх себя.

      Ну а теперь предположи, что он знает о том, что запущен поток. И его задача - не только крутить часики, но и дожидаться, пока поток завершится. И либо отобразить ошибку, возникшую в процессе работы потока, либо сказать, что все в порядке и схлопнуться. Тогда все получается достаточно стройно.
        Цитата Flex Ferrum @
        Ну а теперь предположи, что он знает о том, что запущен поток. И его задача - не только крутить часики, но и дожидаться, пока поток завершится. И либо отобразить ошибку, возникшую в процессе работы потока, либо сказать, что все в порядке и схлопнуться. Тогда все получается достаточно стройно.

        Ва запутались в показаниях :). сначала Вы говорили, что нужно диалог создавать в отдельном потоке.
        После что нужно в потоке обрабатывать данные. А на последнем допросе - диалог должен знать обо всем :)

        Шутка... Ну я так понял что сигналы нужны только диалогу для того. чтобы прихлопнуться или сообщить об ошибке ?
        Принципе логично. Попробую и скажу что получилось.

        Спасибо за долго общение :)
          Цитата zss @
          Цитата gryz @
          функция gui-потоке выполняется?

          она библиотечная. Выполняется в GUI, но может создавать внутри себя еще потоки

          Если функцию можно выполнить в другом потоке, т.е. она, например, не работает напрямую с gui, то тогда лучше так и сделать.
          О завершении другого потока можно узнать по его сигналу finished () (если это наследник QThread)
          По этому сигналу можно закрыть диалог.
          Если диалогу нужно знать что-то о вычиляющем потоке, то тогда можно сделать дополнительный сигнал в вычисляющем потоке, который будет информировать gui-поток (в частности - наш диалог) о текущем состоянии дел.
          Сообщение отредактировано: gryz -
            Цитата gryz @
            Если функцию можно выполнить в другом потоке, т.е. она, например, не работает напрямую с gui, то тогда лучше так и сделать.
            О завершении другого потока можно узнать по его сигналу finished () (если это наследник QThread)
            По этому сигналу можно закрыть диалог.
            Если диалогу нужно знать что-то о выполняемом процессе, то тогда можно сделать дополнительный сигнал в вычисляющем потоке, который будет информировать gui-поток (в частности - наш диалог) о текущем состоянии дел.

            я долго размышлял, но пока руки не дошли до этого.

            Если не сложно - простейший работающий пример со Sleep можно ?
              Цитата zss @
              я долго размышлял, но пока руки не дошли до этого.

              Если не сложно - простейший работающий пример со Sleep можно ?

              Что за Sleep, зачем он?
                Цитата gryz @
                Что за Sleep, зачем он?

                эмитация долгой функции. пусть например Sleep (50000) - 50 сек.
                  диалог запускаем методом exec(), перед его запуском стартуем вычисляющий поток

                  Добавлено
                  завтра попробую пример написать. сейчас домой - на работе засиделся.
                    Цитата gryz @
                    диалог запускаем методом exec(), перед его запуском стартуем вычисляющий поток

                    а слот диалога вешаем на сигнал завершения потока как сказал Flex Ferrum ?
                      я имел в виду это:

                      ExpandedWrap disabled
                        #include <QApplication>
                        #include <QThread>
                        #include <QMessageBox>
                        #include <QtDebug>
                         
                        class MyThread : public QThread
                        {
                        public:
                            void run()
                            {
                                qDebug() << "thread started";
                                sleep(5);
                                qDebug() << "thread finished";
                            }
                        };
                         
                        int main(int argc, char *argv[])
                        {
                            QApplication a(argc, argv);
                            QMessageBox * d = new QMessageBox;
                            QThread * th = new MyThread;
                            QObject::connect(th, SIGNAL(finished()), d, SLOT(accept()));
                            th->start();
                            d->exec();
                            th->wait();//если нажали ок, то надо дождаться завершения выполнения потока
                        }
                      Сообщение отредактировано: gryz -
                        я про это понял. Тут еще возникла сложность, что нужно создавать для каждого метода свой потоковый класс и свой слот обработки.
                        Много кода лишнего получается ... :)
                          Цитата zss @
                          Тут еще возникла сложность, что нужно создавать для каждого метода свой потоковый класс и свой слот обработки.

                          Зачем?
                          Можно же поместить объект в поток (если объект наследник QObject),
                          сделать его методы слотами и асинхронно вызывать их при помощи
                          QMetaObject::invokeMethod().
                          Только тут надо учесть, что возвращаемыми значениями воспользоваться неполучится.
                          Прийдется использовать сигналы для сообщении о результате, если он нужен.

                          при старте каждого метода испускать сигнал methodStarted(QString methodName),
                          при завершении метода испускать сигнал methodFinished().
                          Можно сделать сигнал methodFinished(QVarinat rez),
                          в rez будет храниться результат выполнения метода.
                            Цитата gryz @
                            Можно же поместить объект в поток (если объект наследник QObject),

                            не наследник, но никто не мешает его хранить внутри объекта-потока.
                            Цитата gryz @
                            сделать его методы слотами и асинхронно вызывать их при помощи
                            QMetaObject::invokeMethod().

                            хорошая идея...


                            Цитата gryz @
                            Только тут надо учесть, что возвращаемыми значениями воспользоваться неполучится.
                            Прийдется использовать сигналы для сообщении о результате, если он нужен.

                            Почему ?


                            Цитата gryz @
                            при старте каждого метода испускать сигнал methodStarted(QString methodName),
                            при завершении метода испускать сигнал methodFinished().
                            Можно сделать сигнал methodFinished(QVarinat rez),
                            в rez будет храниться результат выполнения метода.

                            а можно примерчик - мне кажется интересная идея.

                            З.Ы. Только не понятно что должен делать слот потока ?
                              Цитата zss @
                              Почему ?

                              Потому что это асинхронный вызов. Он происходит не сразу, а при возврате в цикл обработки сообщений.
                              Так что сразу результата никакого нет. А нам нужно продолжить выполнение.
                              В Qt 4.3 появился тип вызова (точнее, это тип соединения) Qt::BlockingQueuedConnection,
                              но он не подойдет для вызова из gui потока.

                              Добавлено
                              Вот примерчик

                              ExpandedWrap disabled
                                //client.h
                                #ifndef CLIENT_H
                                #define CLIENT_H
                                #include <QObject>
                                #include <QVariant>
                                #include <QPushButton>
                                #include <QThread>
                                #include <QMessageBox>
                                #include <QtDebug>
                                 
                                class Client: public QObject
                                {
                                    Q_OBJECT
                                public slots:
                                    bool start()const
                                    {
                                        qDebug() << "start() started";
                                        emit methodStarted("start()");
                                        int sum = 0;//сложнейшие вычисления
                                        for(int i = 0; i < 100000; ++i)
                                            for(int j = 0; j < 10000; ++j)
                                                sum += j * i;
                                        bool rez = true;
                                        qDebug() << "start() finished";
                                        emit methodFinished(QByteArray("true"));//всегда последняя перед return операция.
                                                                                //оказалось, что QVariant нельзя передавать в
                                                                                //в соединениях типа Qt::QueuedConnection (qt4.2.2).
                                                                                //Можно упаковывать результат в QByteArray используя QDataStream.
                                                                                //туда же можно запихнуть имя метода start().
                                                                                //Еще как вариант можно использовать различные синалы
                                                                                //для различных типов возвращаемых значений.
                                        return rez;
                                    }
                                    //...
                                signals:
                                    void methodStarted(QString methodName)const;
                                    void methodFinished(QByteArray rez)const;
                                };
                                 
                                class RunnableThread: public QThread
                                {
                                public:
                                    void run()//в QThread этот метод не определен, поэтому приходится наследоваться
                                    {
                                        exec();
                                    }
                                };
                                 
                                class DummyMainWindow: public QWidget
                                {
                                    Q_OBJECT
                                public:
                                    DummyMainWindow()
                                    {
                                        QPushButton * startBtn = new QPushButton(tr("Start"), this);
                                        theClient = new Client;
                                        theWorkerThread = new RunnableThread;
                                        theWorkerThread->start();
                                        theClient->moveToThread(theWorkerThread);
                                 
                                        connect(startBtn, SIGNAL(pressed()), SLOT(invokeStart()));
                                        connect(theClient, SIGNAL(methodStarted(QString)), SLOT(showDialog(QString)));
                                        connect(theClient, SIGNAL(methodFinished(QByteArray)), SLOT(processResult(QByteArray)));
                                 
                                        theInfoDialog = new QMessageBox(this);
                                        theInfoDialog->setStandardButtons(QMessageBox::NoButton);
                                    }
                                    ~DummyMainWindow()
                                    {
                                        theWorkerThread->quit();
                                        theWorkerThread->wait();
                                        delete theWorkerThread;
                                        delete theClient;
                                    }
                                 
                                private slots:
                                    void invokeStart()
                                    {
                                        //можем запомнить текущий вызываемый метод в члене класса,
                                        //тогда в методе processResult будем знать, какой метод был вызван,
                                        //чтобы правильно интепретировать результат
                                        QMetaObject::invokeMethod(theClient, "start");
                                    }
                                  
                                    void showDialog(QString text)
                                    {
                                        theInfoDialog->setText(text + tr(" is running now"));
                                        theInfoDialog->exec();
                                    }
                                 
                                    void processResult(QByteArray rez)
                                    {
                                        theInfoDialog->accept();
                                        //делаем, что хотим с rez
                                    }
                                        
                                private:
                                    Client * theClient;
                                    RunnableThread * theWorkerThread;
                                    QMessageBox * theInfoDialog;
                                };
                                 
                                #endif


                              ExpandedWrap disabled
                                //main.cpp
                                #include <QtGui/QApplication>
                                #include "client.h"
                                 
                                 
                                 
                                 
                                int main(int argc, char *argv[])
                                {  
                                    QApplication a(argc, argv);
                                    
                                    DummyMainWindow mw;
                                    mw.show();
                                    
                                    return a.exec();
                                }


                              Добавлено
                              В данной реализации в программе всегда запущено 2 потока: gui и вычисляющий.
                              В принципе, можно сделать так, чтобы вычисляющий запускался при необходимости вычислений,
                              а после - завершался.
                              Сообщение отредактировано: gryz -
                                gryz, спасибо за код, но не все подойдет

                                в #49 описано почему. Разные методы, разные сигнатуры и разные возвращаемые значения...
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0519 ]   [ 15 queries used ]   [ Generated: 19.05.24, 13:30 GMT ]