I have an application where i should use QWebSocketServer to accept and parse some socket messages coming from a Bokeh Application. I was able to do that up to now, but now i want to move this whole QWebSocketServer into another thread, so that it wont bother the main GUI. The main Question being does the QWebSocketServer in anyway affect GUI?
The GUI being the parent for QWebSocketServer, i was not able to move it to another thread. Will this work if i inherit QThread class?
I know i should not inherit QThread class and overload run method. I am just wondering if this is possible.
FYI : I am doing all of this in Raspberry pi, and raspberry pi has to do lot of data collection.
I initialized the QWebSocketServer without parent and moved it to another thread and it worked. I don't know if im doing right.
Im doing like this :-
self.server = SocketServer()
self.serverThread = QThread()
self.server.moveToThread(self.serverThread)
Here SocketServer is the server class that inherits QObject(), and QWebSocketServer gets defined in it, with out any parent.
Here is a short snippet of SocketServer class:-
onMessageRecieved = pyqtSignal(str)
serverObject = QWebSocketServer("My Server",QWebSocketServer.NonSecureMode)
def __init__(self,parent=None):
super().__init__(parent)
self.server = QWebSocketServer(self.serverObject.serverName(),self.serverObject.secureMode(),parent)
and dont forget to start the thread.
Related
I created a qt class only to make gui and displayed the data on gui.
i didn't want to freeze the gui that's why i created another non_qt class to perform the operation so i made a object in the gui class of non_qt class and pass the parameter in that and started it in a new thread.
now after completing the operation i want to notify the gui class so it can display the results.
i also want to access the status bar of gui class so when non_qt class is performing the operation it can display some message on gui..
(i tried it with qt class but it didn't work that's why i created non_qt class..with non_qt class threading part is working fine but signal part is not working so i'm not able to notify the gui class).
so please help me out how to send signal to a qt class from a not qt class????
The signal is a concept that only applies to classes that derive from QObject.
If you want to trigger a slot, you don't need a signal. If the receiving object lives in the same thread (and only then), you can call the slot method on the reciving object directly.
For example, given an instance of a GUI object with a slot:
MainWindow * mainWindow;
class MainWindow : public QWidget {
Q_OBJECT
...
Q_SLOT void setStatus(const QString &);
...
};
You can simply do:
// The assert is essential to prevent bad bugs. If it triggers,
// you must use `QMetaObject::invokeMethod` instead.
Q_ASSERT(mainWindow->thread() == QThread::currentThread());
mainWindow->setStatus("Finished");
If the receiving object may live in another thread, or if you don't want to worry about threading issues, then you must use QMetaObject::invokeMethod, as follows:
// This is always safe. No need for asserts.
QMetaObject::invokeMethod(mainWindow, "setStatus",
Q_ARG(QString, "Finished"));
This overload of invokeMethod will correctly choose the connection type depending on whether the receiving object runs in the same thread. If the receiver is in the same thread, the call is a direct call. If it runs in another thread, the call will be converted to a QMetaCallEvent and posted to the receving object. This is thread-safe and doesn't require the receving object's setStatus method to be thread-safe.
I have 2 classes: one maintains some loop (at leas for 2-3 minutes; and is inherited from QObject) and another shows up a progress dialog (inherited from QDialog).
I want to start the loop as soon as the dialog is shown. My first solution was:
int DialogClass::exec()
{
QTimer::singleShot(0, LoopClassPointer, SLOT(start()));
return __super::exec();
}
There is a problem with throwing exceptions from slots. so I considered a possibility to make public slot start() just a public function. But now I don't know how to make it works well. Things like this:
int DialogClass::exec()
{
LoopClassPointer->start();
QApplication::processEvents();
return __super::exec();
}
don't help. The dialog doesn't appears.
Is there a common approach to this kind of situations?
some details, according to questions:
I have to work with system with its own styles, so we have a common approach in creating any dialogs: to inherit them from stytle class, which is inherited from QDialog.
my 'LoopClassPointer' is an exported class from separate dll (there is no UI support in it).
I have a 'start' button in main app, which connected with a slot, which creates progress dialog and 'LoopClassPointer'. at the moment I send 'LoopClassPointer' instance in the dialog and don't whant to make significant changes in the architecture.
Take a look at QtDemo->Concurrent Programming->Run function
e.g. in Qt 4.8: http://qt-project.org/doc/qt-4.8/qtconcurrent-runfunction.html
In this situation, I recommend you separate the logic of the loop from the dialog. Gui elements should always be kept separate.
It's great that your worker class is derived from QObject because that means you can start it running on a separate thread: -
QThread* m_pWorkerThread = new QThread;
Worker* m_pWorkerObject = new Worker; // assuming this object runs the loop mentioned
// Qt 5 connect syntax
connect(m_pWorkerThread, &QThread::started, m_pWorkerObject, &WorkerObject::start);
connect(m_pWorkerThread, &QThread::finished, m_pWorkerThread, &QThread::deleteThis);
m_pWorkerObject->moveToThread(m_pWorkerThread);
m_pWorkerThread->start();
If you're not familiar with using QThread, then start by reading this.
The only other thing you require is to periodically send signals from your worker object with progress of its work and connect that to a slot in the dialog, which updates its display of the progress.
I have a Phonon.MediaObject that is connected to a web source through Phonon.AudioOutput. Therefore, when running play(), the main GUI freezes until the player starts playing (5 seconds at worst case).
This could be fixed by moving the player, or at least it's web fetching task. I've read online about moveToThread() function, but it doesn't seem to work.
I tried making a thread out of it, but without luck: http://pastebin.com/1iXdQD8Y (written in PyQt)
Any ideas?
This will require a bit more coding on your side.
I don't know python all that well, but from looking at your code I think that one mistake you are making is to assume that your PhononThread class is living in it's own thread, but it's actually living in thread in which it has been created.
I wouldn't even try to move objects like MediaObject between threads. One way to do it would be to create your own QObject descendant, then in it's constructor create all objects that you will need to play music. You will also need to add slots to your class to access every phonon function you will need to call from main thread. REMEMBER to create this object WITHOUT parent object.
Then you need to move it to newly created QThread and connect all signals/slots between threads.
I don't use python, but here is pseudo-C++ outline of how it should look like:
class MyPlayer: public QObject{
Q_OBJECT
public:
AudioOutput* ao;
MediaObject* mo;
MyPlayer() : QObject(0) { // note no parent QObject instance
ao = new AudioOutput();
... // Create and connect all objects
}
public slots:
void setCurrentSource ( const MediaSource & source ){
mo->setCurrentSource(source);
}
// And other methods that are not slots already.
};
Then in your application you do:
MyPlayer* mp = new MyPlayer();
QThread* th = new QThread();
connect(th, SIGNAL(finished()), mp, SLOT(deleteLater()));
connect( mainThreadObj, SIGNAL(setPlayerSource ( const MediaSource & ) ), mp, SLOT(setPlayerSource ( const MediaSource & ) ) );
... // and other signals; note that methods that are signals already can be conected witout wrappers:
connect( mainThreadObj, SIGNAL(playerPlay() ), mp->mo, SLOT(play()) );
mp->moveToThread(th);
For stopping your thread, just connect signal from your main thread to th's quit() slot, and emit it when needed.
Subclass QThread, reimplement run() with the stuff you want to happen in your thread, and then create an instance of your thread and call start() on it.
Just be careful about when you connect to things in your thread or from your thread, because you don't want to do a direct or auto connection, you want to do a queued connection in most cases.
This link shows two ways to use QThread, one as I just described, and it links to another producer consumer example using moveToThread().
what is the correct way to implement a QThread... (example please...)
Hope that helps.
Have you tried QtConcurrent::run? It runs function in a separate thread.
http://qt-project.org/doc/qt-4.8/qtconcurrentrun.html#run
or check it here https://stackoverflow.com/search?q=QtConcurrent%3A%3Arun
I'm trying to get the information of several of a class' member variables on the receiving end of a slot/signal setup, so I'd like to pass the entire class through. Unfortunately, after the class has been passed, the member variables seem to be empty. Here's some code snippets:
This sets up the signal to pass the class
signals:
void selected(const ControlIcon *controlIcon);
this is the slot/signal connection
connect(controllerList->serialController, SIGNAL(selected(const ControlIcon*)),
infoView, SLOT(serialControllerSelected(const ControlIcon*)));
I emit the signal from within the class to be passed
emit selected(this);
Here's the code to call on the class' member data
QLabel *ASCIIStringHolder = new QLabel;
ASCIIStringHolder->setText(controlIcon->m_ASCIIString);
Nothing shows up in the label, and when I set a breakpoint, I can see that there's nothing inside m_ASCIIString.
I looked to make sure that it was being assigned some text in the first place, and that's not the problem. I also tried the signal/slot setup with and without const.
Any help would be appreciated.
Qt signal/slot mechanism needs metainformation about your custom types, to be able to send them in emitted signals.
To achieve that, register your type with qRegisterMetaType<MyDataType>("MyDataType");
Consult official QMetaType documentation for more information about this.
First, since you are using an auto connection, do both sender and receiver live in the same thread? If not, it could happen that the call is queued and when it arrives, the data in the sender was already modified. You could try to use a direct connection just to make sure this isn't the problem.
Second, just for the fun of it, did you try to access the sender by using qobject_cast<ControlIcon*>(sender()) within the slot? This is how it is usually done if the signal doesn't pass this as an argument. Like this:
QLabel *ASCIIStringHolder = new QLabel;
// this is instead of the argument to the slot:
ControlIcon *controlIcon = qobject_cast<ControlIcon*>(sender());
ASCIIStringHolder->setText(controlIcon->m_ASCIIString);
The signal can't be declared to be passing a class and then actually pass the child of that class. I changed the signal, slot, and connect() to be SerialController (the child of ControllerIcon), and everything worked fine.
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.