Название: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 21, 2009, 15:31 Всем привет. Заранее извеняюсь что выложил много кода, хочется что бы при выполнении длительных расчетов не замирал интерфейс пользователя. В книге по QT "Бланшет,Саммерфилд - QT4 Программирование GUI на С++.2ed.2008.djvu" нашел примерчик, вроде все вычисления проводятся в отдельном потоке, но мне нужно записывать в статус бар значений счетчика после каждой итерации (функция Run::apply(const QString &str)), как это можно сделать в моем случае ? (код выложен полностью в том виде в котором у меня есть сейчас, с исправлениями спасибо niXman)
Код: //main.cpp Код: //mythread.h Код: //mythread.cpp Код: //transactionthread.h Код: //transactionthread.h Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: niXman от Декабрь 21, 2009, 15:49 методы напутал ;)
тот метод, в котором выполняются вычисления, не является субклассом QThread Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 21, 2009, 15:52 методы напутал ;) тот метод, в котором выполняются вычисления, не является субклассом QThread во блин, а где будет правильно выполнять ? я не очень шарю пока в программирование воообще, учусь :( Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: niXman от Декабрь 21, 2009, 15:56 ты же по книжке учишься? а там написано - в виртуальном защищенном методе void run(), в классе потомке, производном от QThread
Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 21, 2009, 16:03 ты же по книжке учишься? а там написано - в виртуальном защищенном методе void run(), в классе потомке, производном от QThread спасибо понял..., до меня как то с трудом все доходит.... :'( Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: SASA от Декабрь 21, 2009, 16:13 QtConcurrent. Спецом для таких вещей.
Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 21, 2009, 17:54 ты же по книжке учишься? а там написано - в виртуальном защищенном методе void run(), в классе потомке, производном от QThread черт все равно виснет, я перенес вычисления в защищенный метод void run(), добавил в mythread.cpp Код: connect(&thread, SIGNAL(transactionStarted(const QString &)), Код: Run::Run() значения счетчика на интерфейс выводятся, но сдвинуть его никуда немогу..... Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Vass от Декабрь 21, 2009, 20:40 Вот вы пишите:
Код: //вывожу на интерфейс значения счетчика// а я вообще в коде у Вас такого сигнала не нахожу, к чему он подключен? Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 22, 2009, 10:51 Вот вы пишите: Код: //вывожу на интерфейс значения счетчика// а я вообще в коде у Вас такого сигнала не нахожу, к чему он подключен? подправил, но проблема осталась, мне необходимо выводить промежуточные значения при долгих расчетах на интерфейс без его залипания.. Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Vass от Декабрь 22, 2009, 11:41 Читаем Assistant, а там написано:
Код: void QThread::run () [virtual protected] А это значит, что чтобы все работало, Вам просто необходимо где-то вызвать exec(); Но вот где я чего-то не пойму никак. Дело в том что из exec(); он не выйдет пока не будет вызван слот quit(); ------ О! кажется сообразил. в общем Вам надо ваш цикл вынести в отдельный слот, который будет вызываться по сигналу started(); соответственно когда будете выходить из цикла вызывайте слот quit(); Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Igors от Декабрь 22, 2009, 17:44 Код: QString Run::apply(const QString &str){ a = 10, i = 1 a = 10, i = 2 a = 5, i = 3 a = 1, i = 4 a = 0, i = 5 a = 0, i = 6 Бесконечный цикл поскольку (a !=i) всегда. Поэтому что имеем то и имеем - да, интерфейс не виснет, я могу двигать и сайзить главное окно. Но вычисления (и нитка) никогда не кончатся Примечание: не беда если много исходников но пожалуйста в следующий раз прикрепляйте их zip файлом компилябельного примера (выдирать через copy/paste никому не хочется :)) Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 23, 2009, 11:22 Код: QString Run::apply(const QString &str){ я понимаю что цикл бесконечный это не важно, у меня не получается послать сигнал на форму из (QString Run::apply(const QString &str)), как это можно сделать..... сейчас программа посылает сигнал только из потока (void TransactionThread::run() ), но мне необходимо посылать на форму значения ну к примеру I Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Igors от Декабрь 23, 2009, 15:42 я понимаю что цикл бесконечный это не важно, у меня не получается послать сигнал на форму из (QString Run::apply(const QString &str)), как это можно сделать..... В нитке у Вас 2 цикла и оба бесконечные. Поэтому строка во внешнем циклесейчас программа посылает сигнал только из потока (void TransactionThread::run() ), но мне необходимо посылать на форму значения ну к примеру I Код: emit allTransactionDone(); Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 23, 2009, 16:04 я понимаю что цикл бесконечный это не важно, у меня не получается послать сигнал на форму из (QString Run::apply(const QString &str)), как это можно сделать..... В нитке у Вас 2 цикла и оба бесконечные. Поэтому строка во внешнем циклесейчас программа посылает сигнал только из потока (void TransactionThread::run() ), но мне необходимо посылать на форму значения ну к примеру I Код: emit allTransactionDone(); прикрипил все исходники, с ними будет более понятно. После запуска нитки выполняется QString Run::apply(const QString &str)), я знаю что он бесконечен в цикле, мне это не важно, я так сделал специально, мне нужно понять каким образом я могу передать из QString Run::apply(const QString &str)) сигнал в статус бар формы во время каждой итерации бесконечного цикла и каким образом этот сигнал принять в форме ЗЫ: из void TransactionThread::run() сигнал в статус бар формы приходит нормально, я не знаю как его послать именно из QString Run::apply(const QString &str)) Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Igors от Декабрь 23, 2009, 17:35 прикрипил все исходники, с ними будет более понятно. После запуска нитки выполняется QString Run::apply(const QString &str)), я знаю что он бесконечен в цикле, мне это не важно, я так сделал специально, мне нужно понять каким образом я могу передать из QString Run::apply(const QString &str)) сигнал в статус бар формы во время каждой итерации бесконечного цикла и каким образом этот сигнал принять в форме Это легко сделать "технически" (см. attachment). Но это идет вразрез с логикой примера, с именами переменных и.т.п. Подразумевается что "transaction" (класс Run) - это неделимая единица вычислений, которая не должна ничего знать об UI, не должна посылать сигналов и.т.п. Всем этим занимается класс TransactionThread. ЗЫ: из void TransactionThread::run() сигнал в статус бар формы приходит нормально, я не знаю как его послать именно из QString Run::apply(const QString &str)) Поэтому посмотрите как но не используйте, уберите бесконечность в Run но оставьте ее в TransactionThread Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Marat(Qt) от Декабрь 24, 2009, 03:55 Если бы использовался QProcess вместо QThread, то можно было бы использовать сигнал readyReadStandardOutput. Альтернатива не самая веселая, но, судя по всему, вполне подходящая.
Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 24, 2009, 11:35 это легко сделать "технически" (см. attachment). Но это идет вразрез с логикой примера, с именами переменных и.т.п. Подразумевается что "transaction" (класс Run) - это неделимая единица вычислений, которая не должна ничего знать об UI, не должна посылать сигналов и.т.п. Всем этим занимается класс TransactionThread. Поэтому посмотрите как но не используйте, уберите бесконечность в Run но оставьте ее в TransactionThread спасибо большое все работает теперь так как мне было нужно !!!! а как тогда делать правильно, какой должен быть подход ? у меня есть графический редактор, после построения в нем схемы мне нужно провести некотырые довольно медленные расчеты вызвав некую функцию, нужно что бы интерфейс не зависал и была показана какая то видимость работы, прогрэссбар не подходит по причине что я незнаю заранее чему равно 100% работы... как решение была выбрана работа с потоками и вывод информации в статус бар, можно бы ло бы просто создавать поток и делать всю работу в нем но дело в том что расчетов (функций) как минимум 3-4 варианта и для каждого из них описывать свой поток как мне кажется не совсем читабельно, используя выше приведенный подход можно вызывать только требуемые режимы расчета (функции) при этом поток всегда один, а вызывать несколько расчетов сразу мне ненужно Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Igors от Декабрь 24, 2009, 14:09 а как тогда делать правильно, какой должен быть подход ? Правильный подход в исходном примере. Смысл простой: не смешивать расчеты с UI, выделить все расчеты в отдельные классы (а лучше в отдельный файл(ы)). Сделать промежуточное звено (в примере это TransactionThread) которое обеспечивает взаимодействие "расчеты - UI". На первый взгляд это может показаться заумным и.т.п. но когда в один прекрасный день Вы услышите "нужна версия программы с командной строкой" - придется пожалеть о содеянном :) как решение была выбрана работа с потоками и вывод информации в статус бар, можно бы ло бы просто создавать поток и делать всю работу в нем но дело в том что расчетов (функций) как минимум 3-4 варианта и для каждого из них описывать свой поток как мне кажется не совсем читабельно, используя выше приведенный подход можно вызывать только требуемые режимы расчета (функции) при этом поток всегда один, а вызывать несколько расчетов сразу мне ненужно У Вас в примере показано как :) Класс Run порождается от Transaction. Пусть Run - это "расчет 1". Делаете еще классы порожденные от Transaction, напр. Run2, Run3 (расчет 2, расчет 3) для каждого делаете виртуальный метод где выполняются сами расчеты (у Вас это apply) - и одна и та же TransactionThread работает со любыми расчетами, хотите по очереди, хотите вперемежку - зависит от того какие Transaction Вы кладете в очередь.Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: AntonUfo от Декабрь 24, 2009, 16:29 Правильный подход в исходном примере. Смысл простой: не смешивать расчеты с UI, выделить все расчеты в отдельные классы (а лучше в отдельный файл(ы)). Сделать промежуточное звено (в примере это TransactionThread) которое обеспечивает взаимодействие "расчеты - UI". На первый взгляд это может показаться заумным и.т.п. но когда в один прекрасный день Вы услышите "нужна версия программы с командной строкой" - придется пожалеть о содеянном :)
[/quote] еще один глупый вопрос :(, долгий расчет записан в отдельный файл formula.cpp, соответственно при необходимости расчета вызывается функция int formula(int param), как предоставить возможность функции formula посылать сигнал (emit changedStatus(QString) ), я же его объявил в классе Run... ? Название: Re: Зависает интерфейс программы нужна помощь.... Отправлено: Igors от Декабрь 24, 2009, 16:50 еще один глупый вопрос :(, долгий расчет записан в отдельный файл formula.cpp, соответственно при необходимости расчета вызывается функция int formula(int param), как предоставить возможность функции formula посылать сигнал (emit changedStatus(QString) ), я же его объявил в классе Run... ? Run у Вас кто? Расчетная часть, вот пусть она и занимается расчетами, а не посылкой сигналов. Поэтому место класса Run в файлах formula.h и formula.cpp. И формула должна вычисляться в одном из методов Run.Если расчет короткий то достаточно что TransactionThread сама обновит UI. Если же длинный (2 сек и больше) и разбить его на части неудобно - тогда через прокладочку (см. интерфейс CProgressShow в ishodniki2.zip). В любом случае formula.h и formula.cpp ничего не должны знать о QtGUI, сигналах и.т.п. |