Qt создание дочерних потоков с использованием ошибки QFuture - PullRequest
0 голосов
/ 08 февраля 2012

Я пытаюсь сделать Collaborative Editor (я должен использовать сетевые библиотеки Linux для всех сетевых вещей), у меня есть основной виджет (пользовательский класс, который наследует QWidget) со всеми компонентами. В конструкторе я создаю все виджеты на этом главном виджете и в конце пытаюсь создать новый поток, используя QFuture (вместо QThread я использую QFuture, потому что он позволяет мне легко вызывать функции с параметрами любого типа, такими как QTextEdit, QTextCursor ...) но это дает мне эту ошибку при компиляции:
"QObject: Невозможно создать дочерние элементы для родителя, который находится в другом потоке. (Родитель - QTextDocument (0x1b064b0), родительский поток - QThread (0x1985750), текущий поток - QThread (0x1ae7610) ".
Как решить ошибку?
Вот мой код:
mainwindow.h:

...//includes
using namespace QtConcurrent;
...
namespace Ui {
    class Widget;
    class TextEdit;
}

class TextEdit;
class Widget;

class Widget : public QWidget {
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
    ...
    QFuture<void> thread;
}

class TextEdit : public QTextEdit {
    Q_OBJECT
    ...
}

static void receiveKeyPress(TextEdit *textedit, QTextCursor *secondUserCursor) {
    unsigned long long int Number = NULL;
    QMessageBox::information(textedit->parentWidget(), "UI Component", "This makes the thread to throw the error");
    while(1) if(connected == 1) {
        read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
          if( Number != NULL)
            if( Number == Qt::Key_Home )
              secondUserCursor->movePosition(QTextCursor::StartOfLine);
              ...
              else {
                QTextCharFormat backgroundFormat = textedit->textCursor().charFormat();
                backgroundFormat.setBackground(QColor("lightGreen"));
                //If I don't use QMessageBox up there, it breaks here on the next command
                secondUserCursor->setCharFormat(backgroundFormat);
                secondUserCursor->setPosition(textedit->textCursor().position());
                secondUserCursor->insertText(QString::number(Number));
               } //else
            }//while
        }//the function

И mainwindow.cpp:

#include "mainwindow.h"

Widget::Widget(QWidget *parent) {
...
thread = run(receiveKeyPress, this->edit1, this->edit1->secondUserCursor); //run is from QtConcurrent namespace 
}


main.cpp:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget window;
...
    window.show();
    return a.exec();
}



Я читал здесь о стековерсии, как другие используют QObject (который я никогда не использовал, и я не понимаю его) и QThread (единственная комбинация), но я уже пытался использовать QThread и не смог передать QTextEdit и QTextCursor к нему.

Заранее спасибо
Edit:


mainwindow.h

class TextEdit : public QTextEdit {
    Q_OBJECT
...
public slots:
    void receiveKeyPress(qulonglong);
...
};


mainwindow.cpp

void TextEdit::receiveKeyPress(qulonglong Number) {
if( Number == Qt::Key_Home )
...
}


recv-thread.h - создано по этой ссылке http://developer.qt.nokia.com/doc/qt-4.8/thread-basics.html#example-3-clock

#include <QThread>
#include "mainwindow.h" //To get TextEdit in here

class RecvThread : public QThread {
    Q_OBJECT

signals:
    void transferDataToSlot(qulonglong Data);

protected:
    void run();
};


RECV-thread.cpp

#include "recv-thread.h"

void RecvThread::run() {
    unsigned long long int Number = NULL;
    while(1) if(connected == 1) {
        read(recvFileDescriptor, &Number, sizeof(unsigned long long int));
        if( Number != NULL) {
            emit transferDataToSlot(Number);
        }
    }
}


main.cpp

...
#include "recv-thread.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget window;
    RecvThread recvThread;
...
    QObject::connect(&recvThread, SIGNAL(transferDataToSlot(qulonglong)), window.edit1, SLOT(receiveKeyPress(qulonglong)), Qt::QueuedConnection); //line 38
    recvThread.start();
    //Displaying the window
    window.show();
    a.exec();
    recvThread.quit();
    recvThread.wait();
    return 0;
}

Я правильно делаю?

...