Russian Qt Forum

Qt => Общие вопросы => Тема начата: IgorbIgorev от Декабрь 24, 2007, 14:50



Название: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 14:50
приложение работает, но через раз!, сообщая о выполненной невыполнимой операции:)(пытается отправить отчет в микрософт)
код:
Код:
class MyThread : public QThread
{
    QTextEdit* textEdit;
    volatile int val;
  public:
    void set_textEdit(QTextEdit* p){textEdit=p;}
    void set_val(const int v){val=v;}
    void run();
};
class dlgTest: public QDialog, public Ui_dlgTest
{
    Q_OBJECT
    MyThread thread;
  public: 
    dlgTest(QWidget *parent=0); 
  public slots:
    void  on_pbSetThread_clicked();
};
dlgTest::dlgTest(QWidget *parent):QDialog(parent)
{
  setupUi(this);
  thread.set_textEdit(textEdit);
}
void dlgTest::on_pbSetThread_clicked()
{
  thread.set_val( spinBox->value() );
  thread.start();
}
void MyThread::run()
{
  int x;
  for (int i = 0; i <val; ++i)
  {
    x=i*2;
    textEdit->insertHtml ("test №"+QString::number(x)+" completed");
  }
}


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 14:54
Ошибка в том, что вы обращаетесь к гуёвым компонентам с негуёвого потока. Так делать нельзя! Используйте сигнал\слот или эвенты для передачи данных между потоками.


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 16:56
Ошибка в том, что вы обращаетесь к гуёвым компонентам с негуёвого потока. Так делать нельзя! Используйте сигнал\слот или эвенты для передачи данных между потоками.
у textEdit кокраз insertHtml и является слотом!
если эт неверно, то тогда как туда передавать данные во время выполнения потока?


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: Emc от Декабрь 24, 2007, 17:27
всё что связано с paintEvent'ом (а вставка текста вызывает перерисовку textEdit'a) не может исполняться в другом потоке


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 17:37
всё что связано с paintEvent'ом (а вставка текста вызывает перерисовку textEdit'a) не может исполняться в другом потоке
да нет же, неможет этого быть, есть много всяких программ где это КАКТО работает,
например в программе по распаковке ati драйверов catalist там и сообщения выводятся(при нажатии showprogress) в list или в ещё какойто бокс и окно адекватно реагирует на перемещение указателя и scrollbox'а.


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 17:46
у textEdit кокраз insertHtml и является слотом!
если эт неверно, то тогда как туда передавать данные во время выполнения потока?

Повторяю ещё раз! Так делать нельзя! Вы обращаетесь напрямую к гуевому элементу с негуювого потока. Создайте сигнал дял потока, сконнектите этот сигнал со слотом вашего виджета, незабыв про параметр Qt::QueuedConnection. Испустите сигнал с данными из вашего второго потока. Или используйте эвенты для передачи данных между потоками.


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 17:53
да нет же, неможет этого быть, есть много всяких программ где это КАКТО работает,

Может! Это так и есть! Давайте код всяких программ, заценим


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 17:56
Читаем внимательнее Thread Support in Qt:

Цитировать
In GUI applications, the main thread is also called the GUI thread because it's the ONLY thread that is allowed to perform GUI-related operations.


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: Emc от Декабрь 24, 2007, 18:03
почувствуй разницу
Код:
void MyThread::run()
{
  int x;
  for (int i = 0; i <val; ++i)
  {
    x=i*2;
    //textEdit->insertHtml ("test №"+QString::number(x)+" completed");  -- ERROR
    emit sig_toTextEdit_insertHtml("test №"+QString::number(x)+" completed"); -- GOOD
  }
}


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 18:22
если я правильно понял то:
Код:
class MyThread : public QThread
{
    QTextEdit* textEdit;
    volatile int val;
  public:
    void set_textEdit(QTextEdit* p){textEdit=p;}
    void set_val(const int v){val=v;}
    void run();
  signals:
    void sendData(const QString &s);
};
class dlgTest: public QDialog, public Ui_dlgTest
{
    Q_OBJECT
    MyThread thread;
  public: 
    dlgTest(QWidget *parent=0); 
  public slots:
    void  on_pbSetThread_clicked();
};
dlgTest::dlgTest(QWidget *parent):QDialog(parent)
{
  setupUi(this);
  thread.set_textEdit(textEdit);
  QObject::connect(&thread,  SIGNAL( sendData(const QString &)   ),
                   textEdit,   SLOT( insertHtml(const QString &) ),
                   Qt::QueuedConnection
                   );
}
void dlgTest::on_pbSetThread_clicked()
{
  thread.set_val( spinBox->value() );
  thread.start();
}
void MyThread::run()
{
  int x;
  for (int i = 0; i <val; ++i)
  {
    x=i*2;
    sendData("test №"+QString::number(x)+" completed");
  }
}
но эта штука неверно работает, отображает первых 2 записи останавливается(не отвечает в это время на запросы) и через нек-е время отображает все сразу!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: ритт от Декабрь 24, 2007, 18:34
emit где?


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: Emc от Декабрь 24, 2007, 18:35
просто задача которую ты решаешь довольно бессмысленная
вынести в thread умножение на число - ради чего?
построчное появление html документа -- можно, но чтоб было красиво -- придется вводить задержку (смысл это городить?
если важна скорость -- сначала сформируй документ потом вставь целиком в  textEdit


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 18:37
emit где?
Код:
void MyThread::run()
{
  int x;
  for (int i = 0; i <val; ++i)
  {
    x=i*2;
    emit sendData("test №"+QString::number(x)+" completed"); //ничего не меняет
  }
}
все также, отображает несколько первых записей->зависает->выводит все остальное!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 18:41
вынести в thread умножение на число - ради чего?
просто типа пример для меня
построчное появление html документа -- можно, но чтоб было красиво -- придется вводить задержку (смысл это городить?
нет задержки не надо, реальные данные итак будут медленно грузиться.
если важна скорость -- сначала сформируй документ потом вставь целиком в  textEdit
это понятно но нужно чтоб пользователь видел что он получает чтоб в случае чего мог отменить загрузку ненужного ему документа!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: ритт от Декабрь 24, 2007, 19:44
сделал такой же тест - отображает несколько первых записей->зависает->выводит все остальное
в то время, как и без того нешустрый кутекстэдит добавляет текст, ты тред его просит докинуть ещё текста - и так по кругу
попробуй после каждой итерации делать мслип(500)


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: ритт от Декабрь 24, 2007, 19:46
вообще, тыкие вещи надо с мутексом делать


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 20:10
до этого как-то работало нормально но через раз, а щас тормозит жутко,
можно пример с мутексом, а то в exampla'х  тока с консолью балуются!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 20:19
может есть какая нибудь статья, книжка где все это подробно рассматривается,
чтот до меня туго все эт доходит ([:/з)
спасиб вам за ответы и терпение!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: Emc от Декабрь 24, 2007, 20:38
после вставки текста добавляй
Код:
QCoreApplication::processEvents();
тогда будет прорисовываться постепенно, но работать будет медленно
текст лучше вставлять кусками


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 20:40
QCoreApplication::processEvents();
нет это не дело!
поскажите/покажите как с мьютексами делать


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 20:45
поскажите/покажите как с мьютексами делать

А зачем мютексы приминительно к этой задаче? У вас ещё присудствует установка текста из гуёвого потока или ещё с какого-то?


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 20:50
вообще, тыкие вещи надо с мутексом делать
У вас ещё присудствует установка текста из гуёвого потока или ещё с какого-то?
да!


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: Emc от Декабрь 24, 2007, 20:52
зачем тебе мутекс - не забивай себе голову - улучшить все равно не получиться
потоки здесь не нужны это очевидно, только если твои сложные обсчеты туда вынести, хотя я не верю что для одной строчки что-либо может обсчитываться так долго, чтобы требовать отдельный поток
тормоза у тебя из-за множественных insertText и как следствие постоянной перерисовки textEdit
так что выхода два:
 1 - формировать textDocument целиком -- самый лучший способ - но раз хочешь выводить текст постепенно то забыли о нем
 2 - использовать задержку , чтобы textEdit успевал отрисоваться -- и самый лучший вариант здесь processEvents (просто и наверняка будет работать
 


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: pastor от Декабрь 24, 2007, 20:58
да!

Тогда да, объекты синхронизации нужны. Сделаешь вот такой метод добавишь член класса mutex типа QMutex:

Код:
void <className>::setText(const QString &text)
{
    QMutexLocker locker(&mutex);
    textEdit->setHtmlText(text);
}

BWT: Qt::QueuedConnection из коннекта. Этот параметр применяеться в потоках, но не в вашем случаем. Возможно из-за этого и тормоза


Название: Re: [QT4] как нормально связать GUI с Thread
Отправлено: IgorbIgorev от Декабрь 24, 2007, 21:01
спасиб большое, за советы,
как допишу код подсчета строки, вновь к вам обращусь, на данный момент этого достатчно!
всем огроммный РЕСПЕКТ!