In main, I'm creating a QApplication in a thread I create, and then, according to commands from the user (from cin), I want to use callbacks on the QApplication instance I created in the thread.
The creation of the QApllication happens on a workerthread that is called 'StartQtThread', and my main function, in which I get the commands is the main thread.
my problem is that my commands from the main thread, don't work on the qapplication.
for example: if the user enters 'z', I cant to zoom in , on the map in my QApplication. bus since I'm on the main thread nothing happens.
I tried to use my zoom-in function, from the 'StartQtThread' thread, it works.
tried to use 'moveToThread(qApp->thread())' function from the main thread , but the current thread isn't being changed.
anyone knows how can I change that?
thread->moveToThread(obj) moves object obj to the thread thread. Code moveToThread(qApp->thread()) moves main thread's object to another thread (which is kinda strange). GUI can work ONLY in main thread.
Related
I have a class, audio_engine_interface, and in main.cpp, I add it to the QML thing.
viewer.rootContext()->setContextProperty("engine", engine);
In audio_engine_interface, I have a audio_engine class, which is computationally intensive—it needs to run on its own thread.
void audio_engine_interface::play()
{
QThread thread;
thread.start();
engine->moveToThread(&thread);
engine->play(); // Will use 100% of CPU
}
However, when I do this, the whole QML thread locks up, meaning I can't pause (pretty important). Am I missing something?
EDIT:
This thread won't mess up anything or access objects from other places. However, it does have a pause function that will need to be called at some point. For what it's worth, the engine is doing pitch shifting.
This is a problem: -
Qthread thread;
Creating a QThread object like this is creating it on the stack. When the function ends, the object will go out of scope and delete the QThread object.
You need to dynamically allocate the object on the heap: -
QThread* thread = new QThread;
Then remember to delete the thread, or set it to delete itself: -
//Qt 5 connect syntax
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
You should also be aware of thread affinity (the thread which an object is running on). I suggest reading this article on how to use QThread properly.
You have so many problems.
when you move to thread your object must not have a parent
your thread object is local variable so it will day immediately when udio_engine_interface::play() end execution
you are invoking you engine->play(); method directly and this means that it will be executed in current thread.
moveToThread means that slots invked by signals connected using default 5th parameter (Qt::AutoConnection) will be queued in event loop of given thread.
The easiest way to fix it is use QtConcurrent:
void audio_engine_interface::play()
{
QtConcurrent::run(engine, &EngineClass::play);
}
Depending what your engine does you should make it thread safe (use mutex locks an so on), without details it is hard to tell, what exactly you should do.
I am trying to create a client application in QT which requires both threads for processing and a variable amount of window instances. But I am having a hard time trying to figure out how to create a new window inside one of the processing thread. I understand that all ui elements must be created in the same thread as the QApplication class, but I need to be able to instantiate, or at least have a reference to a QDialog in another thread.
Communicating between the thread and QDialog can be done using signals, I am not worried about this, but actually creating the window is another matter. I could use signals to tell the main thread to create an instance to the window, and then retrieve the pointer to it somehow, but to me that seems a bit to complicated and ugly. Is there a better way to accomplish such a task? To create a QDialog outside the main thread were the QApplication class exists?
Edit : I have tried the Q_INVOKABLE method but it does not work across threads. I have created a view factory class which can create a QDialog of a type I specify and returns a pointer to it. This class has been instantiated in the main GUI thread and a reference to this class is sent to any worker threads. The problem is that, when a thread invokes the create method from the factory using Qt::BlockingQueuedConnection, the invoke method fails. If I change it to Qt::DirectConnection, the invoke method calls the right create method but in the current thread as the worker thread.
My main function looks like this :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ViewFactory vFactory;
vFactory.registerCreator(Util::W_CONNECT, new ConnectWindow::ConnectCreator());
ClientApp app;
if(!app.Initialize(&vFactory))
return 0;
app.start();
a.exec();
.............................
}
And my run function from the ClientApp thread looks something like this :
void ClientApp::run()
{
QDialog * tmp = NULL;
QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}
Like I said, the invokeMothod will not fail if I change the connection type to Qt::DirectConnection, so the params are not the problem, but rather calling the method across a separate worker thread.
You can only do Gui stuff in the gui thread. The obvious solution is for the worker thread to send a message to the gui thread = a signal in Qt terms.
If a worker thread needs to ask a question it should send a message to the gui thread and then block until it gets a signal back.
AFAIK, signals (or just a dynamically callable method, using Q_INVOKABLE) or an event is the way to go.
Note that, using QMetaObject::invokeMethod() (with Qt::BlockedConnection), you can call a function safely across threads and get a return value back without too much coding.
It seems like QObject::moveToThread can solve this problem. This function moves event processing loop to another thread.
Example from Qt documentation:
myObject->moveToThread(QApplication::instance()->thread());
Here is the code I am having trouble with:
QApplication a(argc, argv);
QString path = qApp->applicationDirPath();
qApp->setQuitOnLastWindowClosed(false);
a.addLibraryPath(path+"/plugins");
TryQt w;
w.show();
return a.exec();
This is how I am starting my Application. In the Application (TryQt) I am creating several other QWidgets and Qwindows. The problem arises when I close the application The QMainWindow disappears, looks like the program exits, but it remains in the memory. (I can see from Task Manager / Processes ) .
I am also catching the closeEvent in my TryQt program and closing every thing possible I opened in there. But still no use. Does any one has any idea why this is happening?
well, it's because you're calling
qApp->setQuitOnLastWindowClosed(false);
the docs say:
This property holds whether the
application implicitly quits when the
last window is closed.
The default is true.
If this property is true, the
applications quits when the last
visible primary window (i.e. window
with no parent) with the
Qt::WA_QuitOnClose attribute set is
closed. By default this attribute is
set for all widgets except for
sub-windows. Refer to Qt::WindowType
for a detailed list of Qt::Window
objects.
and you are for some reason setting it to false.
I had a similar problem (except calling qApp->setQuitOnLastWindowClosed(true); as the previous answer suggests). I suspect one of the libraries we use doesn't clean up its thread properly and an investigation is pending, but the simplest workaround was to replace return a.exec(); with:
exit(a.exec());
I have created Qt tree control( and its nodes ) in different thread than the main thread. In the main thread I want to show context menu for the clicked node, so I am connectiong the actions in the menu with appropriate slots in the main thread. The connect function returns true , but slot is never executed. If I explicitly say in connect function that this is Qt :: DirectConnection then everything works fine. Why is this ?
I I create my tree in main thread, everything also works fine , without having to say that this is Qt::DirectConnection .
See the documentation here.
The default connection type, Qt::AutoConnection, is the same as Qt::DirectConnection if the signal is sent from the same thread as the receiver slot, otherwise the behaviour is the same as Qt::QueuedConnection.
In the case where you create the widget in the main thread, you basically get the same behaviour as when you explicitly specify Qt::DirectConnection.
The behaviour of Qt::QueuedConnection is to call the slot when that threads event loop regains control.
To solve your problem, make sure you have an event loop in every thread which may be receiving signals, unless you manually specify Qt::DirectConnection (which, I assume, will mean the slot is called from the same thread as the signals emitter - basically the equivelent of a normal function call).
I'm facing a practical problem with Qt. I'm using a class that communicates with QLocalSocket to another process (pipes/unix sockets) and I need to do that communication before other events occur, that is before app.exec() starts (or more precisely,as soon as app starts). The class that I'm using needs an eventloop so it does not work if I call the class methods before an event loop is started. There is any way to start something when the event loop is ready? I thought of making a hidden event-only window and do my duties in the hidden window constructor, and stablish this window as toplevel.
Basically, I need this local-socket communication task to start as soon as the event loop becomes available.
Any ideas?
Thank you.
You could start a separate eventloop, using QEventLoop, before calling QApplication::exec(). You should emit a "done" signal from your class and connect that to the QEventLoop quit() slot, or use an existing signal provided in the Qt class you're using.
Here's a simple example fetching a webpage using QNetworkAccessManager:
app = QtCore.QCoreApplication([])
manager = QtNetwork.QNetworkAccessManager()
req = QtNetwork.QNetworkRequest(QtCore.QUrl("http://www.google.com"))
resp = manager.get(req)
eventloop = QtCore.QEventLoop()
eventloop.connect(resp, QtCore.SIGNAL('finished()'), QtCore.SLOT('quit()'))
eventloop.exec_() # this will block until resp emits finished()
print resp.readAll()
app.exec_()
While this might suit your needs, I couldn't quite understand why you can't simply do whatever business you have prior to calling show() on your window, once that's done, call show().
If you just need to start the communications before everything else, you can simply use a single-shot timer with 0ms delay:
QTimer::singleShot(0, commsInstancePtr, SLOT(startCommunication()));
If you need your operations to actually finish before doing everything else, Daniel's solution might be more suitable.