Another Qt question: calling a function from QThread object

Thought I'd post this here as there seem to be a few switched on people here.

I'm coding a small front end GUI for some chat client code I've written in C. I'm not really worrying about the networking aspect yet, just getting the GUI and signals set up etc.

Here's what the app looks like, it's pretty simple, type input, click submit, it (will eventually) sends the message to the chat server.



I've tried to set up a new qthread object to deal with the task of continually checking for messages sent by the chat server. The problem is when it finds one I want it to update the main "display" with the received message. I've written code to that effect but it doesn't work.

Here's the relevent code segments:

This is the main "display" window..
Code:
class Output : public QWidget
{
  public:
    Output(QWidget *parent = 0);
    
  public slots:
    void displayMsg(QString msg);
    
  private:
    QTextEdit *display;
    
};

And the qthread object...
Code:
class MyThread : public QThread
{
  protected:
    void run();
};

void MyThread::run()
{
  
  
  for (int count = 0; count < 20; count++)
  {
    sleep(1);
    Output::displayMsg("test");
  }

  
  /*char *rawmessage = (char *)malloc(MAX_MSG_LENGTH);
  
  while(1)
  {
    //rawmessage = network_getmessage();
    // translate from char * to QString
    //displayMsg(msg);
  }
  */
}
You can see I've commented out the network stuff, I just want to get the threads communicating in a basic way before I move on.

I get the compile time error:
Code:
main.cpp: In member function 'virtual void MyThread::run()':
main.cpp:94: error: cannot call member function 'void Output::displayMsg(QString)' without object

I can post the full source if it will help, but I think the parts above are all that is needed?

tl;dr version: how can I call another class's member functions from within a qthread object?

Thanks, Benjamin
 
You could try to pass the widget pointer via thread constructor.

Also as far as I understand you can connect signals to qthread states.
But then again like I stated in older posts I havent done anything with Qt.
GTK+ camp supporter here.
 
This is largely a C++ answer. You are calling displayMsg() as if it were a static class method, but it is not. You need a Output object to call displayMsg() with. The thread needs to know the object. As expl said, you can pass in the object pointer to the thread constructor. Alternatively the Output object could be a global object, or perhaps the parent QObject of the thread.

In any case, Qt has several threading and network examples. Run the program "qtdemo" for a nice interface to run the examples and browse the documentation and source.
 
maybe you should look at this:

http://doc.trolltech.com/3.3/qsocketnotifier.html

rather than your thread with it's sleep(1).

you can assign a callback when data become available
on a file descriptor.
in the style of XtAppAddInput

it says socket but I read it works for file descriptors as well.

there is also a Qtimer which runs a thread after a certain time
and handles all the details for you.

but i'd try the socket notifier


note: I haven't tried it.
 
Thanks all for replies, you're more knowledgeable than the Qt Forums... I've got it working now, I've make the thread emit a signal when a message is recv'd (no need to use sleep either, because recv just sits there until in gets something).

One thing is bothering me, someone on the Qt Forums said there is no need to use threads in this case, but that I need to figure out for myself why.

I can't see how I'd get past this without using threads tbh, I need to do two things at once (get input AND check for and display new messages). Anyone have any idea?
 
There is no need to use threading because you are not dealing with a continues lock while handling the sockets so the GUI loop is locked only for milliseconds when you are actually receiving data via callbacks. Now if you were receiving a large file and trying to update your GUI at same time in the loop that would need a separate thread.
 
expl said:
There is no need to use threading because you are not dealing with a continues lock while handling the sockets so the GUI loop is locked only for milliseconds when you are actually receiving data via callbacks. Now if you were receiving a large file and trying to update your GUI at same time in the loop that would need a separate thread.

Ok, I understand, but the problem I have is I have to start a
Code:
for(;;)
loop that continually checks if there is a message from the server. Where can I put this that will not stop other stuff being executed without using a second thread?
 
well I did tell you how not to use threads.

QsocketNotifier will call a function when input arrives on a socket.
that's how I would do it.
 
bigearsbilly said:
well I did tell you how not to use threads.

QsocketNotifier will call a function when input arrives on a socket.
that's how I would do it.

Thanks, I did see that. I just assumed it wouldn't help since all of my network code is in C. But that might be wrong, I'll take a look at it tomorrow.
 
caesius said:
Ok, I understand, but the problem I have is I have to start a
Code:
for(;;)
loop that continually checks if there is a message from the server. Where can I put this that will not stop other stuff being executed without using a second thread?

Well there are several methods of handling sockets while not blocking, allowing for your gui toolkit (Qt) to update the window. Most common way is the POSIX way :]. You have to use fcntl(2) system call and flag your socket description with O_NONBLOCK and O_ASYNC. First flag will make recv to never block (always returning if there is no data available at that time), the second flag will cause kernel to send your process a SIGIO signal when ever the socket description has fresh data. Allowing you to bind the signal to a callback rather than locking your recv in a infinite loop.

I am sure Qt Net API has a more efficient way to deal with this problem since you already have the QtCore libs linked to your application.
 
Back
Top