Is it possible to create local event loops without calling QApplication::exec()?
Asked Answered
R

1

11

I'd like to create a library built on top of QTcpServer and QTcpSocket for use in programs that don't have event loops in their main functions (because the Qt event loop is blocking and doesn't provide enough timing resolution for the real-time operations required).

I was hoping to get around this by creating local event loops within the class, but they don't seem to work unless I've called app->exec() in the main function first. Is there some way to create local event loops and allow for signal/slot communication within a thread without having an application level event loop?

I've already looked at Is there a way to use Qt without QApplication::exec()? but the answer doesn't help because it seems like the solution adds a local event loop but doesn't remove the application loop.

Ritualism answered 6/1, 2015 at 15:15 Comment(2)
spawn a new thread that has the QApplication::exec() and keep it alive as the "main thread"?Publisher
I'll give it a try. The only downside is that even if works it would probably preclude me from using the library in the future with actual Qt applications as you certainly can't have two calls to QApplication::execRitualism
U
12

You can create the instance of the QCoreApplication in a new thread in the library. You should check to create only one instance of it, That's because each Qt application should contain only one QCoreApplication :

class Q_DECL_EXPORT SharedLibrary :public QObject    
{
Q_OBJECT
public:
    SharedLibrary();

private slots:

    void onStarted();

private:
    static int argc = 1;
    static char * argv[] = {"SharedLibrary", NULL};
    static QCoreApplication * app = NULL;
    static QThread * thread = NULL;
};


SharedLibrary::SharedLibrary()
{
    if (thread == NULL)
    {
        thread = new QThread();
        connect(thread, SIGNAL(started()), this, SLOT(onStarted()), Qt::DirectConnection);
        thread->start();
    }
}
SharedLibrary::onStarted()
{
   if (QCoreApplication::instance() == NULL)
   {
       app = new QCoreApplication(argc, argv);
       app->exec();
   }
}  

This way you can use your Qt shared library even in non Qt applications.

Umbria answered 6/1, 2015 at 15:20 Comment(6)
and maybe synchronize on checking and starting the loopPublisher
This deserves an extra +1 for the check on QCoreApplication::instance()Ritualism
The QCoreApplication should be created on the main thread. See #27964197Hardnosed
@AlexWade The post you mentioned does not tell QCoreApplication should be created on main thread. All that is needed to fix the warning is SharedLibrary not inheriting from QObject and creating QCoreApplication instance in constructor.Umbria
@Umbria right. And no other QObjects should be created prior to instantiating QCoreApplication. Instead of using QThread, std::thread can be used to create the main thread.Hardnosed
If anyone is able to achieve the same thing in PyQt, I'd be happy about a response here: #73914018Substituent

© 2022 - 2024 — McMap. All rights reserved.