QTcpSocket parent-child constructor woes (also cross-thread talk)
I spent about 10 hours yesterday with Qt stuff and I'm kind of exhausted, so I'm really bad at searching for answers on my own right now. If you guys could help me out, that would be appreciated.
The basic idea is that I want to start up TCP socket communication (it reads accelerometer data from a microcontroller), and I want to start up a QGLWidget to do other stuff. The QTcpSocket starts up in it's own thread (apparently on its own) though and can't be set as the QObject child of the QGLWidget, or at least that was my conclusion based on the threading errors that popped up. Then I tried to get a basic QTcpSocket to work and it broke. I am failing here.
What is wrong with the following code? I spits out the following runtime error:
Code:
QObject: Cannot create children
for a parent that is in a different thread.
(Parent is in my_TCP_Q_socket_with_readyRead(*some address*), parent's thread is QThread(*some address*), current thread is QThread(*some address*)
For the record, I am I using QtCreator now. I figured out how to move between Visual Studio and QtCreator, so I just picked one.
Here is main.cpp:
Code:
#include <QTcpSocket>
#include <QObject>
#include <iostream>
using std::cout;
using std::endl;
class my_TCP_Q_socket_with_readyRead
: public QObject{
public:
explicit my_TCP_Q_socket_with_readyRead
(QObject *parent
= 0) : {
m_socket_ptr
= new QTcpSocket(this);
// complains about parent-child threading //m_socket_ptr = new QTcpSocket(0); // no error (??but what is it doing? it is silent??)
}
private:
Q_OBJECT
};
#include "main.moc"
int main(int argc, char *argv[])
{
my_TCP_Q_socket_with_readyRead s;
return 0;
}
What am I doing wrong? I found that this code doesn't complain if I provide a 0 (integer zero) as the argument to the QTcpSocket, but why?
As a related followup question, is it possible to use signals and slots to pass data from the thread that has the QTcpSocket to the thread that contains my QGLWidget? I think I can figure out how to make signals and slots work to call a function in QGLWidget once my custom QTcpSocket object is done reading data, but I don't know how to pass data from one to the other. Or am I missing the way this works? I haven't discovered how or when Qt starts threads on its own (which it clearly does considering that the error shown above specifies two threads).
Re: QTcpSocket parent-child constructor woes (also cross-thread talk)
Quote:
Originally Posted by
amdreallyfast
What am I doing wrong?
No idea, your code is obviously more than what you have posted.
Quote:
Originally Posted by
amdreallyfast
I found that this code doesn't complain if I provide a 0 (integer zero) as the argument to the QTcpSocket, but why?
0 is the value of a null pointer, so no parent.
Quote:
Originally Posted by
amdreallyfast
As a related followup question, is it possible to use signals and slots to pass data from the thread that has the QTcpSocket to the thread that contains my QGLWidget?
Yes, though you most likely don't need threads here at all (Qt's networking code operates event based by default).
Quote:
Originally Posted by
amdreallyfast
I think I can figure out how to make signals and slots work to call a function in QGLWidget once my custom QTcpSocket object is done reading data, but I don't know how to pass data from one to the other.
Signals can carry arguments. Since it is unlikely that the data received via socket is directly usable by a QGLWidget, you will probably want to receive it in a slot that interprets the data.
Can of course be in a slot of a class derived from QGLWidget, though it is probably cleaner to use a dedicated connection/data handling object instead.
Cheers,
_
Re: QTcpSocket parent-child constructor woes (also cross-thread talk)
Quote:
...your code is obviously more than what you have posted.
Nope. That code is all my test code in it's entirety. I just pasted it back into QtCreator and it gave me the same error. Does it work for you?
Re: QTcpSocket parent-child constructor woes (also cross-thread talk)
Ah, then you need to create a Qt application object, e.g. a QCoreApplication instance, before creating the QTcpSocket,
Cheers,
_
Re: QTcpSocket parent-child constructor woes (also cross-thread talk)
Funny thing about that: I tried both the QApplication (that one took awhile to figure out the .pro file) and QCoreApplication, and they both give the same error. The error comes from the QTcpSocket constructor, not from the application. The bizarre part is that it seems that the QTcpSocket was created anyway, and while QCoreApplication ignores it, Qapplication goes ahead anyway and is happy with my QObject::connect(...) stuff and it works, so I don't know what it's complaining about.
Bottom line: My code works, but something, somewhere, is still not ok.
Note: This is a QConsole project. Here is my .pro file:
Code:
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = testing_1
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
HEADERS +=
INCLUDEPATH += tmp/moc/release_shared
unix|win32: LIBS += -L$$PWD/../../../../../Qt/4.8.5/lib/ -lQtCore4
INCLUDEPATH += $$PWD/../../../../../Qt/4.8.5/include
DEPENDPATH += $$PWD/../../../../../Qt/4.8.5/include
Here is my latest experimental code if you're interested:
Code:
#include <QApplication>
#include <QtCore/QCoreApplication>
#include <iostream>
using std::cout;
using std::endl;
#include <QtDebug>
#include <QObject>
#include <QtNetwork/QTcpSocket>
class my_TCP_Q_socket_with_readyRead
: public QObject{
public:
explicit my_TCP_Q_socket_with_readyRead
(QObject *parent
= 0) : {
// ??why are you not ok taking "this" as an argument ?!
m_socket_ptr->connectToHost("10.10.10.126", 5);
if (!(m_socket_ptr->waitForConnected((5000))))
{
qDebug() << "not connected";
m_socket_ptr = NULL;
}
else
{
qDebug() << "connected";
}
m_socket_ptr,
SIGNAL(readyRead()),
this,
SLOT(read_it()));
}
// http://qt-project.org/wiki/Qt_for_beginners_Signals_and_slots_2
// "Even if the signal is declared as a method, there is no
// need to implement it. The meta-object compiler is used to
// do this."
Q_SIGNAL void done_reading(int num);
private:
Q_OBJECT
Q_SLOT void read_it()
{
static int read_count = 0;
qint64 bytes_available = m_socket_ptr->bytesAvailable();
if (bytes_available > 0)
{
read_count += 1;
qDebug() << "Reading '" << bytes_available << "' bytes";
m_arr = m_socket_ptr->readAll();
qDebug() << m_arr;
}
emit done_reading(read_count);
}
};
{
public:
explicit my_class
(QObject *parent
= 0) : {
}
Q_SLOT void say_something(int num)
{
cout << "hey there! number is '" << num << "'" << endl;
}
private:
Q_OBJECT
};
#include "main.moc"
int main(int argc, char *argv[])
{
int app_ret_val = 0;
//QApplication app(argc, argv);
my_TCP_Q_socket_with_readyRead s;
my_class mc;
QObject::connect(&s,
SIGNAL(done_reading
(int)),
&mc,
SLOT(say_something
(int)));
app_ret_val = app.exec();
return app_ret_val;
}
I've been trying to hunt down how the basic QTcpSocket constructor is supposed work with the "this" argument. It is supposed to "just work" from the demos that I have seen, so I don't know where to to do when it doesn't work. Any more ideas?
Re: QTcpSocket parent-child constructor woes (also cross-thread talk)
Have you tried not using the blocking I/O methods, i.e. any of the "waitFor..." ones?
Cheers,
_