crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

canavar
  опции профиля:
сообщение 29.3.2009, 17:40
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


Всем доброго вечера.

Есть такая проблема: Существует окно QDialog. При загрузке этого окна происходят довольно тяжелые вычисления и, как следствие, окно замораживается. Элементов на форме 6 штук ( два QTableWidget, четыре QListWidget). Хотелось бы вынести все вычисления в отдельный поток.

Но я не понимаю, как сделать так, чтобы второй поток смог изменять Widget'ы на форме QDialog. Можно конечно в поток передавать указатели на Widget'ы, но у меня есть подозрение, что существует более красивое решение...

Что вы можете сказать по этому поводу?

Заранее спасибо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
2 страниц V   1 2 >  
Начать новую тему
Ответов (1 - 15)
ViGOur
  опции профиля:
сообщение 29.3.2009, 17:46
Сообщение #2


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(canavar @ 29.3.2009, 18:40) *
Но я не понимаю, как сделать так, чтобы второй поток смог изменять Widget'ы на форме QDialog. Можно конечно в поток передавать указатели на Widget'ы, но у меня есть подозрение, что существует более красивое решение...
Что подразумевается под "красивое решение"? :)
Без указателей ну никак не обойтись, но на все виджеты не обязательно передавать достаточно передать указатель на тот объект, в классе которого они "живут".
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 29.3.2009, 17:48
Сообщение #3


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


А ещё лучше использовать сигналы и слоты.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
canavar
  опции профиля:
сообщение 29.3.2009, 17:53
Сообщение #4


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


Под красивым решением имеется ввиду... кхм... не описать, нужно прочувствовать. ;)

Да, согласен, так скорее всего и сделаю -- передам указатель на главный объект. )

Тогда вопросик в догонку... Тут начал переносить вычисления в отдельный поток.. Переопределил customEvent(), чтобы поток ловил event'ы. Переопределил run(). запихнул туда все вычисления. В конце метода run() написал exec(), чтобы thread не завершался и ждал event'ы. Но после того, как вычисления завершаются, программа вылетает с exception... Не могу понять в чем проблема. Если exec убрать, то все нормально, но поток завершается и не ловит event'ы.

Нет никаких мыслей по этому поводу?

P.S. Скоро код выложу, чтобы понятнее было..
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 29.3.2009, 17:57
Сообщение #5


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(canavar @ 29.3.2009, 21:53) *
Нет никаких мыслей по этому поводу?
цикл там сделай.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
canavar
  опции профиля:
сообщение 29.3.2009, 18:00
Сообщение #6


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


Что-то типа:

while(!stopped)
{
}


Если так, то если не сложно, можете объяснить почему вылетает exception, если использовать exec();
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 29.3.2009, 18:11
Сообщение #7


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Цитата(canavar @ 29.3.2009, 18:40) *
Но я не понимаю, как сделать так, чтобы второй поток смог изменять Widget'ы на форме QDialog. Можно конечно в поток передавать указатели на Widget'ы

Цитата(ViGOur @ 29.3.2009, 18:46) *
Без указателей ну никак не обойтись

Но мы же не можем работать с виджетыми в дочернем потоке. Все работа с ними производится только в осносном Gui потоке. :blink:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 29.3.2009, 19:46
Сообщение #8


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(igor_bogomolov @ 29.3.2009, 19:11) *
Но мы же не можем работать с виджетыми в дочернем потоке. Все работа с ними производится только в осносном Gui потоке.
Все правильно, но для того, чтобы послать сигнал какому-либо виджету нужен как минимум указатель на объект класса, который может их контролировать.

В посте выше я забыл сказать насчет сигналов и слотов, но Litkevich Yuriy меня дополнил.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 29.3.2009, 20:03
Сообщение #9


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


ИМХО.
Я так понимаю, что это от реализации программы зависит.
Чтобы имитировать сигнал никаких указателей не нужно. Вот уже где распологается коннект, это другое дело.
Все равно экземпляры класса, наследовонного от QThread, будут создаваться в "Gui_class", так и коннекты между ними лучше делять тамже.

connect(&thread, SIGNAL(thread_signal()), this, SLOT(gui_slot()));

Сообщение отредактировал igor_bogomolov - 29.3.2009, 20:05
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
canavar
  опции профиля:
сообщение 29.3.2009, 20:07
Сообщение #10


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


Спасибо за ответы.

Так можно узнать почему, если я использую exec() у меня вылезает exception, а если бесконечный цикл, то все нормально?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 29.3.2009, 20:19
Сообщение #11


Мастер
******

Группа: Модератор
Сообщений: 3296
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(igor_bogomolov @ 29.3.2009, 21:03) *
Все равно экземпляры класса, наследовонного от QThread, будут создаваться в "Gui_class", так и коннекты между ними лучше делять тамже.
Это верно, но не всегда. Если у тебя большой проект, то лучше все же разнести по управляющим классам.

Цитата(canavar @ 29.3.2009, 21:07) *
Так можно узнать почему, если я использую exec() у меня вылезает exception, а если бесконечный цикл, то все нормально?
На вскидку пока ничего не приходит в голову. Покажи код.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
canavar
  опции профиля:
сообщение 29.3.2009, 20:36
Сообщение #12


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


ManageThread.h
/*
 * ManageThread.h
 *
 *  Created on: 28.03.2009
 *      Author: canavar
 */

#ifndef MANAGETHREAD_H_
#define MANAGETHREAD_H_
#include <QThread>
#include <QObject>
#include <QtGui>

class ManageThread : public QThread
{
    Q_OBJECT

public:
    ManageThread(QObject *parent = 0);
    virtual ~ManageThread();

    inline void SetWidgetTable(QTableWidget *tbl) { _widgetTable = tbl; };

protected:
    void run();
    void customEvent(QEvent *event);

private:
    QTableWidget *_widgetTable;

    void Load();

    void add(QString a);

};

#endif /* MANAGETHREAD_H_ */

ManageThread.cpp
/*
 * ManageThread.cpp
 *
 *  Created on: 28.03.2009
 *      Author: canavar
 */

#include "ManageThread.h"

ManageThread::ManageThread(QObject *parent) : QThread(parent)
{

}

ManageThread::~ManageThread()
{

}

void ManageThread::run()
{
    // Inserting start values
    Load();

    exec();
}

void ManageThread::Load()
{
    // This function (add) is called about 1500 times...
    add("aaa");
}

// TODO: Move this in other thread
void ManageThread::add(QString a)
{
    if(desc.name().isEmpty() && (!desc.id().isEmpty()))
        _widgetTable->addItem(desc.id());
    else
        _widgetTable->addItem(desc.name());
}

void ManageThread::customEvent(QEvent *event)
{

}


Вызывается из конструктора viewer.cpp (viewer -- наследник QDialog):


    _mgThread = new ManageThread();
    _mgThread->SetWidgetTable(ui.widgetTable);
    _mgThread->start();


_mgThread объявлен в viewer.h:

private:
      ManageThread *_mgThread;


Сообщение отредактировал Admin - 29.3.2009, 23:24
Причина редактирования: Добавил тег expand
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
trdm
  опции профиля:
сообщение 29.3.2009, 21:39
Сообщение #13


Дмитрий Трошин
****

Группа: Участник
Сообщений: 575
Регистрация: 12.1.2008
Пользователь №: 68

Спасибо сказали: 21 раз(а)




Репутация:   6  


Цитата(canavar @ 29.3.2009, 21:36) *
ManageThread.h:


Раскрывающийся текст
/*
 * ManageThread.h
 *
 *  Created on: 28.03.2009
 *      Author: canavar
 */

#ifndef MANAGETHREAD_H_
#define MANAGETHREAD_H_
#include <QThread>
#include <QObject>
#include <QtGui>

class ManageThread : public QThread
{
    Q_OBJECT

#endif /* MANAGETHREAD_H_ */



Пользуйся пожалуйста тегом [ expand ] [ / expand ]

Сообщение отредактировал trdm - 29.3.2009, 21:39
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
canavar
  опции профиля:
сообщение 29.3.2009, 22:13
Сообщение #14


Студент
*

Группа: Новичок
Сообщений: 14
Регистрация: 26.3.2009
Пользователь №: 643

Спасибо сказали: 0 раз(а)




Репутация:   0  


Хорошо.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 30.3.2009, 1:55
Сообщение #15


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


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

Что такое addItem()? У QTableWidget нет такого метода. Или там должен быть QListWidget?

В дочернем потоке нужно производить вычисления, а результат высылать через сигнал. Ловить этот сигнал в Gui потоке, и в нем устанавливать значения для таблиц и списков.

Привыкаем к следущему объявлению
void add(const QString &a)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость__canavar_*
сообщение 30.3.2009, 13:43
Сообщение #16





Гости








    


Огромное спасибо! Теперь стало понятно.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 29.5.2025, 17:42