Using processEvents() in a while loop inside in a Function - c++

I have a slot function
void MobilePlatform::slot_lineFollow(bool checked)
{
while(checked){
...
QCoreApplication::processEvents();
}
if(!checked){
....
}
}
This function is a function that is requested from a QCheckBox and when the checkbox is pressed the variable checked are true and go into the while loop, and when the checkbox is not pressed the variable checked are false and go out from the while loop and goes into the if block, this is normal, but what I don't understand is, why in the next step goes to QcoreApplication::processEvents() and when it goes out, the variable checked are true.
Knows anybody why these happens?
Thanks in advance!

You've got bitten by the fallout from reentering the event loop. Now you know why it's not a good idea. Never block in the main thread, and never reenter the event loop. Invert the flow of control to accurately reflect the asynchronous reality:
class MobilePlatform : public QWidget {
Q_OBJECT
using self = MobilePlatform;
using base_class = QWidget;
using spin_handler = void (self::*)();
QBasicTimer m_spinTimer;
...
Q_SIGNAL void spinSignal();
void spin(spin_handler);
void despin(spin_handler);
void follower();
Q_SLOT void slot_lineFollow(bool checked);
protected:
void timerEvent(QTimerEvent *) override;
public:
...
};
void MobilePlatform::timerEvent(QTimerEvent *ev) {
if (ev->timerId() == m_spinTimer.timerId())
Q_EMIT spinSignal();
else
base_class::timerEvent(ev);
}
void MobilePlatform::spin(spin_handler handler) {
if (!m_spinTimer.isActive())
m_spinTimer.start(0, this);
connect(this, &self::spinSignal, this, handler, Qt::UniqueConnection | Qt::DirectConnection);
Q_ASSERT(m_spinTimer.isActive());
}
void MobilePlatform::despin(spin_handler handler) {
static const auto signal = QMetaMethod::fromSignal(&self::spinSignal);
Q_ASSERT(signal.isValid());
disconnect(this, &self::spinSignal, this, handler);
auto const hasHandlers = isSignalConnected(signal);
if (!hasHandlers)
m_spinTimer.stop();
Q_ASSERT(m_spinTimer.isActive() == hasHandlers);
}
void MobilePlatform::follower() {
/* code that runs when following */
...
}
void MobilePlatform::slot_lineFollow(bool checked) {
if (checked()) {
spin(&self::follower);
} else {
despin(&self::follower);
...
}
}

Related

Qt blocked event loop

I recently started using the QT framework. Yesterday I began programming a simple multithreaded application. At the moment I'm somewhat stuck on the following problem.
Consider two worker classes that both use a thread to do some 'heavy computations'. The first class, FooWorker, looks like the following:
class FooWorker : public QObject
{
Q_OBJECT
public:
FooWorker() : QObject() { }
~FooWorker() { }
signals:
void notify(int);
void aborted();
public slots:
void doWork()
{
int counter = 0;
forever {
// For the sake of this example this reassembles a heavy computational process
if(counter++ < 10) {
emit notify(counter);
QThread::sleep(1);
} else {
counter = 0;
// Wait until we get a signal to restart the process
mutex_.lock();
condition_.wait(&mutex_);
mutex_.unlock();
}
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
private:
QMutex mutex_;
QWaitCondition condition_;
};
The slot 'doWork' will be scheduled to run in another thread. The slot will run forever and is emitting a signal every second until 10 notifications are emitted. After that we wait until it is woken up again.
The second class, BarWorker, looks like this:
class BarWorker : public QObject
{
Q_OBJECT
public:
BarWorker() : QObject() { }
~BarWorker() { }
signals:
void aborted();
public slots:
void doWork()
{
forever {
// Another heavy computational process
QThread::sleep(1);
// We should check for a cancellation flag every iteration...
}
emit aborted();
}
void onNotify(int value)
{
qDebug() << "Notification value:" << value;
}
};
Again the slot 'doWork' will be scheduled to run in another thread. The slot will run forever to do a heavy computational process. Again once the process is done we will wait until it is woken up again (for the sake of this example I left that out in this class).
Finally the main looks like the following:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread* barThread = new QThread();
BarWorker* barWorker = new BarWorker();
barWorker->moveToThread(barThread);
QThread* fooThread = new QThread();
FooWorker* fooWorker = new FooWorker();
fooWorker->moveToThread(fooThread);
// Automatically deletes worker and thread
QObject::connect(fooThread, SIGNAL(started()), fooWorker, SLOT(doWork()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooThread, SLOT(quit()));
QObject::connect(fooWorker, SIGNAL(aborted()), fooWorker, SLOT(deleteLater()));
QObject::connect(fooThread, SIGNAL(finished()), fooThread, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(started()), barWorker, SLOT(doWork()));
QObject::connect(barWorker, SIGNAL(aborted()), barThread, SLOT(quit()));
QObject::connect(barWorker, SIGNAL(aborted()), barWorker, SLOT(deleteLater()));
QObject::connect(barThread, SIGNAL(finished()), barThread, SLOT(deleteLater()));
QObject::connect(fooWorker, SIGNAL(notify(int)), barWorker, SLOT(onNotify(int)), Qt::QueuedConnection);
fooThread->start();
barThread->start();
return a.exec();
}
When I run the application nothing gets printed. That was to be expected because the event loop of the BarWorker instance is blocked. As the 'notify' signal gets emitted the 'onNotify' slot is queued onto the event queue. Because we have a never ending loop (until we manually abort it) in the 'doWork' slot, the 'onNotify' slot will not be called. To solve this I can do a couple of things, namely:
Connect the 'notify' signal to the 'onNotify' slot by using the Qt::DirectConnection flag. This way it looks like a normal function call executing on the signalling thread.
Occasionally call the QCoreApplication::processEvents() method to force the event queue to be processed.
Unknown solution I do not know at this time :)???
I hope someone has some alternative solution to this problem, or even suggest an entire different approach, because IMHO above solutions are somewhat ugly and do not feel right.
I don't think there is any "magic" solution to be found here; a thread can't be running Qt's event loop if it is running your own custom event loop. In practice, there are two common solutions, which are really two sides of the same coin:
Call processEvents() periodically from your event loop, as you suggested in your question, so that the Qt event-handling code occasionally gets to run and handle incoming asynchronous signals.
Don't have a long-running loop in your doWork() method. Instead, do a short amount of work, store the results/state of that work in a member variable or somewhere, and then call something like QTimer::singleShot(0, this, SLOT(doWork())) so that the Qt event loop will call your doWork() method again soon after the first call to doWork() returns. That way the Qt event loop never gets held off for longer than the (brief) period of time taken up by a single doWork() call.
Of those two options, I think the second is preferable, because it allows the Qt event loop to run in its normal fashion, and it also avoids a potential tripping-over-your-own-shoelaces issue -- e.g. imagine if while using solution (1) your call to processEvents() causes a slot to be called that deletes the BarWorker object. When the processEvents() call returns, BarWorker::doWork() will resume executing, but at that point, all of the local member variables and virtual methods it might access as part of its normal execution have been destroyed, and reading or writing them will cause undefined behavior (if you're lucky, an easy-to-debug crash). That possible snafu can't happen when using solution (2), since if the BarWorker object gets deleted between calls to doWork(), any queued-up asynchronous call to doWork() will be safely cancelled.
The idiom for a forever loop that interoperates with the event loop is a zero-duration timer. We can factor it out into a WorkerBase class, where the unit of work is to be done in the workUnit method:
// https://github.com/KubaO/stackoverflown/tree/master/questions/worker-timer-40369716
#include <QtCore>
// See http://stackoverflow.com/q/40382820/1329652
template <typename Fun> void safe(QObject * obj, Fun && fun) {
Q_ASSERT(obj->thread() || qApp && qApp->thread() == QThread::currentThread());
if (Q_LIKELY(obj->thread() == QThread::currentThread()))
return fun();
struct Event : public QEvent {
using F = typename std::decay<Fun>::type;
F fun;
Event(F && fun) : QEvent(QEvent::None), fun(std::move(fun)) {}
Event(const F & fun) : QEvent(QEvent::None), fun(fun) {}
~Event() { fun(); }
};
QCoreApplication::postEvent(
obj->thread() ? obj : qApp, new Event(std::forward<Fun>(fun)));
}
class WorkerBase : public QObject {
Q_OBJECT
QBasicTimer timer_;
protected:
virtual void workUnit() = 0;
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == timer_.timerId() && timer_.isActive())
workUnit();
}
public:
using QObject::QObject;
Q_SIGNAL void finished();
/// Thread-safe
Q_SLOT void virtual start() {
safe(this, [=]{
timer_.start(0, this);
});
}
/// Thread-safe
Q_SLOT void virtual stop() {
safe(this, [=]{
if (!isActive()) return;
timer_.stop();
emit finished();
});
}
bool isActive() const { return timer_.isActive(); }
~WorkerBase() {
if (isActive()) emit finished();
}
};
The workers then become:
class FooWorker : public WorkerBase
{
Q_OBJECT
int counter = 0;
bool isDone() const { return counter >= 10; }
void workUnit() override {
if (!isDone()) {
counter ++;
emit notify(counter);
QThread::sleep(1);
} else
stop();
}
public:
void start() override {
counter = 0;
WorkerBase::start();
}
void stop() override {
if (!isDone()) emit aborted();
WorkerBase::stop();
}
Q_SIGNAL void notify(int);
Q_SIGNAL void aborted();
};
class BarWorker : public WorkerBase
{
Q_OBJECT
void workUnit() override {
QThread::sleep(1);
}
public:
void stop() override {
emit aborted();
WorkerBase::stop();
}
Q_SIGNAL void aborted();
Q_SLOT void onNotify(int value)
{
qDebug() << "Notification value:" << value;
}
};
Note that the aborted() and finished() signals have different meanings.
Finally, the test harness:
class Thread : public QThread { public: ~Thread() { quit(); wait(); } };
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
BarWorker barWorker;
FooWorker fooWorker;
Thread barThread, fooThread;
barWorker.moveToThread(&barThread);
fooWorker.moveToThread(&fooThread);
barWorker.start();
fooWorker.start();
QObject::connect(&fooWorker, &FooWorker::finished, &app, &QCoreApplication::quit);
QObject::connect(&fooWorker, &FooWorker::notify, &barWorker, &BarWorker::onNotify);
fooThread.start();
barThread.start();
return app.exec();
}
#include "main.moc"
If you get a QBasicTimer::stop: Failed. Possibly trying to stop from a different thread warning, it's of no consequence and is a result of a Qt bug.

QT: How to loop a method every second? C++

I've created a Qt project which displays a circle on a widget.
Then I have a method which redraws the circle at different positions every time I call the method.
What I want is to run that method in a for loop, say ten times, and be shown each of the 10 positions that the circle is redrawn in every one second.
Something along the lines of:
void method::paintEvent(QPaintEvent * p)
{
//code
for(int i=0; i<10;i++)//do this every second
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter); //using QPainter
}
//code
}
I've read about QTimer, but do not know how to use it. And the sleep function does not work.
As you've guessed, QTimer is the correct mechanism to use here. How to go about setting it up?
Here's one option:
class MyClass : public QObject
{
public:
MyClass():i(0)
{
QTimer::singleShot(1000,this,SLOT(callback()));//or call callback() directly here
} //constructor
protected:
unsigned int i;
void paintEvent(QPaintEvent * p)
{
//do your painting here
}
public slots:
void callback()
{
method(circle[i]); //co-ordinates change
//circle[i].pain( & painter); //don't use QPainter here - call update instead
update();
++i;//increment counter
if(i<10) QTimer::singleShot(1000,this,SLOT(callback()));
}
}
All you need to do is to trigger an update() from the timer event. The update() method schedules a paintEvent on the widget.
It is invalid to paint on a widget outside of the paintEvent - that's the mistake that all other answers did at the time I posted this answer. Merely calling the paintEvent method is not a workaround. You should call update(). Calling repaint() would also work, but do so only when you have understood the difference from update() and have a very good reason for doing so.
class Circle;
class MyWidget : public QWidget {
Q_OBJECT
QBasicTimer m_timer;
QList<Circle> m_circles;
void method(Circle &);
void paintEvent(QPaintEvent * p) {
QPainter painter(this);
// WARNING: this method can be called at any time
// If you're basing animations on passage of time,
// use a QElapsedTimer to find out how much time has
// passed since the last repaint, and advance the animation
// based on that.
...
for(int i=0; i<10;i++)
{
method(m_circles[i]); //co-ordinates change
m_circles[i].paint(&painter);
}
...
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) {
QWidget::timerEvent(ev);
return;
}
update();
}
public:
MyWidget(QWidget*parent = 0) : QWidget(parent) {
...
m_timer.start(1000, this);
}
};
Try something like this:
class MyDrawer : public QObject
{
Q_OBJECT
int counter;
QTimer* timer;
public:
MyDrawer() : QObject(), counter(10)
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(redraw()));
timer->start(1000);
}
public slots:
void redraw()
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter);
--counter;
if (counter == 0) timer->stop();
}
};
Don't forget to run moc on this file, although if your class is a QObject you probably already do it.
Try this.
for(int i=0; i<10;i++)//do this every second
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter);
sleep(1000);// you can also use delay(1000);
}
Use sleep() The function called sleep(int ms) declared in which makes the program wait for the time in milliseconds specified.

How to call function after window is shown?

Using Qt I create a QMainWindow and want to call a function AFTER the windows is shown. When I call the function in the constructor the function (a dialog actually) get's called before the window is shown.
If you want to do something while the widget is made visible, you can override QWidget::showEvent like this:
class YourWidget : public QWidget { ...
void YourWidget::showEvent( QShowEvent* event ) {
QWidget::showEvent( event );
//your code here
}
After analyzing the solutions above, it turns that all of them, including the heavily upvoted ones, are faulty.
Many recommend something like this:
class MyWidget : public QWidget {
// ...
};
void MyWidget::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
DoSomething();
}
void MyWidget::DoSomething() {
// ...
}
This works as long as there is no QCoreApplication::processEvents(); in DoSomething. If there is one, it processes all events in the queue, including the QShowEvent which called MyWidget::showEvent in the first place. When it gets to the original QShowEvent, it calls MyWidget::showEvent again, causing an infinite loop.
If this happens, there are three solutions:
Solution 1. Avoid calling processEvents in MyWidget::DoSomething, instead call update or repaint when necessary. If DoSomething calls something else, these functions should avoid processEvents also.
Solution 2. Make DoSomething a slot, and replace direct call to DoSomething() by
QTimer::singleShot(0, this, SLOT(DoSomething()));
Since zero interval timer fires only when after all events in the queue are processed, it will process all events, including the original QShowEvent, remove them from the queue, and only then call DoSomething. I like it the most.
Since only zero interval timer fires only when after all events in the queue are processed, you should not try to "improve" it by lengthening the interval, for instance
QTimer::singleShot(50, this, SLOT(DoSomething())); // WRONG!
Since 50 ms is usually enough time for processing events in the queue, that would usually work, causing an error which is hard to reproduce.
Solution 3. Make a flag which prevents calling DoSomething the second time:
class MyWidget : public QWidget {
// ...
};
void MyWidget::showEvent(QShowEvent* event) {
if (is_opening)
return;
is_opening = true;
QWidget::showEvent(event);
DoSomething();
is_opening = false;
}
void MyWidget::DoSomething() {
// ...
}
Here, is_opening is a boolean flag which should be initialized as false in constructor.
try this:
in mainwindow.h:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
protected:
void showEvent(QShowEvent *ev);
private:
void showEventHelper();
Ui::MainWindow *ui;
}
in mainwindow.cpp:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::showEvent(QShowEvent *ev)
{
QMainWindow::showEvent(ev);
showEventHelper();
}
void MainWindow::showEventHelper()
{
// your code placed here
}
Follow Reza Ebrahimi's example, but keep this in mind:
Do not omit the 5th parameter of connect() function which specifies the connection type; make sure it to be QueuedConnection.
I.E.,
connect(this, SIGNAL(window_loaded), this, SLOT(your_function()), Qt::ConnectionType(Qt::QueuedConnection | Qt::UniqueConnection));
I believe that you'd achieve what you need if you do it this way.
There are several types in signal-slot connections: AutoConnection, DirectConnection, QueuedConnection, BlockingQueuedConnection (+ optional UniqueConnection). Read the manual for details. :)
Assuming you want to run your code in the UI thread of the window after the window has been shown you could use the following relatively compact code.
class MainWindow : public QMainWindow
{
// constructors etc omitted.
protected:
void showEvent(QShowEvent *ev)
{
QMainWindow::showEvent(ev);
// Call slot via queued connection so it's called from the UI thread after this method has returned and the window has been shown
QMetaObject::invokeMethod(this, "afterWindowShown", Qt::ConnectionType::QueuedConnection);
}
private slots:
void afterWindowShown()
{
// your code here
// note this code will also be called every time the window is restored from a minimized state
}
};
It does invoke afterWindowShown by name but that sort of thing is fairly common practice in Qt. There are ways of avoiding this but they're a bit more verbose.
Note that this code should work for any QWidget derived class, not just QMainWindow derived classes.
In theory it might be possible for a very quick user to invoke some sort of action on the UI of the displayed window before afterWindowShown can be called but it seems unlikely. Something to bear in mind and code defensively against perhaps.
I found a nice answer in this question which works well, even if you use a Sleep() function.
So tried this:
//- cpp-file ----------------------------------------
#include "myapp.h"
#include <time.h>
#include <iosteream>
MyApp::MyApp(QWidget *parent)
: QMainWindow(parent, Qt::FramelessWindowHint)
{
ui.setupUi(this);
}
MyApp::~MyApp()
{
}
void MyApp::showEvent(QShowEvent *event) {
QMainWindow::showEvent(event);
QTimer::singleShot(50, this, SLOT(window_shown()));
return;
}
void MyApp::window_shown() {
std::cout << "Running" << std::endl;
Sleep(10000);
std::cout << "Delayed" << std::endl;
return;
}
//- h-file ----------------------------------------
#ifndef MYAPP_H
#define MYAPP_H
#include <QtWidgets/QMainWindow>
#include <qtimer.h>
#include <time.h>
#include "ui_myapp.h"
class MyApp : public QMainWindow
{
Q_OBJECT
public:
MyApp(QWidget *parent = 0);
~MyApp();
protected:
void showEvent(QShowEvent *event);
private slots:
void window_shown();
private:
Ui::MyAppClass ui;
};
#endif // MYAPP_H
I solved it without a timer using Paint event. Works for me at least on Windows.
// MainWindow.h
class MainWindow : public QMainWindow
{
...
bool event(QEvent *event) override;
void functionAfterShown();
...
bool functionAfterShownCalled = false;
...
}
// MainWindow.cpp
bool MainWindow::event(QEvent *event)
{
const bool ret_val = QMainWindow::event(event);
if(!functionAfterShownCalled && event->type() == QEvent::Paint)
{
functionAfterShown();
functionAfterShownCalled = true;
}
return ret_val;
}
The best solution for me is count once paint event:
.H
public:
void paintEvent(QPaintEvent *event);
.CPP
#include "qpainter.h"
#include <QMessageBox> // example
int contPaintEvent= 0;
void Form2::paintEvent(QPaintEvent* event)
{
if (contPaintEvent ==0 )
{
QPainter painter(this);
QMessageBox::information(this, "title", "1 event paint"); // example
// actions
contPaintEvent++;
}
}
Reimplement method void show() like this:
void MainWindow::show()
{
QMainWindow::show();
// Call your special function here.
}

Qt: Signal Slot not working

I am trying to implement Signal and Slot system between the main gui and another object moved to another thread...the following is how the class design looks like...unfortunately cannot implement it...
MainWindow.h
signals:
void StopDisplayWidget();
void StartDisplayWidget();
void signalFromGUI();
private slots:
void on_pushButton_start_display_clicked();
void on_pushButton_stop_display_clicked();
void on_pushButton_check_clicked();
private:
Ui::MainWindow *ui;
displaythread *threadforDisplay;
display *displayWidget;
QThread *WorkerDisplay;
MainWindow.cpp
{
threadforDisplay = new displaythread;
threadforDisplay->setptr2display(displayWidget);
WorkerDisplay = new QThread;
QObject::connect(WorkerDisplay,SIGNAL(started()),threadforDisplay,SLOT(Process()));
QObject::connect(this,SIGNAL(StartDisplayWidget()),threadforDisplay,SLOT(StartDisplay()));
QObject::connect(this,SIGNAL(StopDisplayWidget()),threadforDisplay,SLOT(StopDisplay()));
QObject::connect(this,SIGNAL(signalFromGUI()),threadforDisplay,SLOT(Check()));
threadforDisplay->moveToThread(WorkerDisplay);
}
void MainWindow::on_pushButton_start_display_clicked()
{
if(!threadforDisplay->IsDisplayActive())
emit this->StartDisplayWidget();
if(!WorkerDisplay->isRunning())
WorkerDisplay->start();
}
void MainWindow::on_pushButton_stop_display_clicked()
{
if(threadforDisplay->IsDisplayActive())
{
emit this->StopDisplayWidget();
}
}
void MainWindow::on_pushButton_check_clicked()
{
std::cout<<"CHECKING SIGNAL SLOT"<<std::endl;
emit this->signalFromGUI();
}
threadforDisplay is a pointer to displaythread class which looks like
displaythread.h
#include <QObject>
#include <QWaitCondition>
#include <QMutex>
#include "display.h"
class displaythread : public QObject
{
Q_OBJECT
public:
explicit displaythread(QObject *parent = 0);
bool IsDisplayActive() const;
void setptr2display(display *);
signals:
public slots:
void Process();
void StartDisplay();
void StopDisplay();
void Check();
private:
void SleepThread();
volatile bool stopped,running;
QMutex mutex;
QWaitCondition waitcondition;
display *displayinGUI;
displaythread.cpp
void displaythread::setptr2display(display *ptr)
{
displayinGUI = ptr;
}
void displaythread::Process()
{
std::cout<<"RECEIVED START PROCESS SIGNAL"<<std::endl;
running = true;
while(true)
{
if(!stopped)
{
displayinGUI->update();
this->SleepThread();
}
}
}
void displaythread::SleepThread()
{
mutex.lock();
waitcondition.wait(&mutex,20);
mutex.unlock();
}
void displaythread::StartDisplay()
{
std::cout<<"RECEIVED START SIGNAL"<<std::endl;
stopped = false;
running = true;
}
void displaythread::StopDisplay()
{
std::cout<<"RECEIVED STOP SIGNAL"<<std::endl;
stopped = true;
running = false;
}
bool displaythread::IsDisplayActive() const
{
return running;
}
void displaythread::Check()
{
std::cout<<"SIGNAL FROM GUI RECEIVED"<<std::endl;
}
display.h
class display : public QWidget
{
Q_OBJECT
public:
explicit display(QWidget *parent = 0);
~display();
signals:
public slots:
private:
void paintEvent(QPaintEvent *);
IplImage *image_opencvBGR,*image_opencvRGB;
QImage image;
CvCapture *webcam;
display.cpp
display::display(QWidget *parent) :
QWidget(parent)
{
image_opencvRGB = cvCreateImage(cvSize(640,480),8,3);
webcam = cvCaptureFromCAM(-1);
}
display::~display()
{
cvReleaseCapture(&webcam);
}
void display::paintEvent(QPaintEvent *)
{
//std::cout<<"IN PAINT LOOP"<<std::endl;
image_opencvBGR = cvQueryFrame(webcam);
cvCvtColor(image_opencvBGR,image_opencvRGB,CV_BGR2RGB);
image = QImage((const unsigned char*)image_opencvRGB->imageData,image_opencvRGB->width,image_opencvRGB->height,QImage::Format_RGB888);
QRectF target(0.0,0.0,image.width(),image.height());
QRectF source(0.0,0.0,image.width(),image.height());
QPainter painter(this);
painter.drawImage(target,image,source);
}
OUTPUT :
RECEIVED START PROCESS SIGNAL
However except the Process slot no other slot is working when signals are emitted from the main gui i.e. MainWindow..is it due to movetoThread command? Donno where i am going wrong..
The answer is simple : Qwidgets don't work outside the main thread. So you cannot execute GUI code using displaythread.
Furthermore your while loop may cause issues (I know the variable is volatile but I dont have the time to analyze properly if it is correct)
See the documentation for more information.
ps: It seems you are overdoing things. Rework your whole design. GUI operations are in the main thread. Use threads for computations only. If the communication between thread and access to their variables use signal and slots only, you dont need locking mechanisms.

QTimer to execute method every second

I'm learning Qt and I was reading about Threads, Events and QObjects from Qt wiki, and followed the wiki recommendations on how to handle some work in a while condition but its not working for my specific case. Here's a simple example of what I'm currently trying to achieve.
class FooEvents : public FooWrapper {
public virtual serverTime(..) { std::cout << "Server time event\n"; }
public virtual connected(..) { std::cout << "Connected event\n"; }
}
class Foo : public QObject {
private:
FooAPI *client;
public:
Foo(FooEvents *ev, QObject *parent = 0) : client(new FooApi(ev)) { .. }
private slots:
void processMessages() {
if (state is IDLE)
reqFooAPiServerTime();
select(client->fd()+1, ...);
if (socket is ready for read)
client.onReceive();
}
public:
void connect(...) {
if (connection) {
QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(processMessages()));
timer.start(1000); // I don't get the output from FooEvents
}
}
}
This is a very simple but I think it illustrates my case. Why is this not working and what other alternatives to I have to handle this case? Thanks.s
Edit: The processMessages is being called every second but I don't get any output from the events
Where is timer declared and defined?
If it's local to Foo::connect() it'll be destroyed before it ever has a chance to fire. Presumably it just needs to be a member object of the Foo class.
Also keep in mind that QObject provides it's own simple interface to a timer - just override the protected virtual timerEvent() function and call QObject's startTimer() to start getting those timer events. In this case instead of having a slot to receive the timer events, they will just end up at the overridden timerEvent() function:
protected:
void timerEvent(QTimerEvent *event) {
processMessages();
}
public:
void connect( /* ... */ ) {
// ...
startTimer(1000);
}
This won't work, because processMessages() is not a SLOT.
So Declare processMessages() as a private slot and then try.
You don't declare the timer neither the slot. In the header you must declare:
class ... {
QTimer timer;
...
private slots:
void processMessages();
...
};
Then remember to make the SIGNAL-SLOT connection and configure the timer:
connect(&timer, SIGNAL(timeout()), this, SLOT(processMessages()));
timer.setInterval(1000);
timer.start();
Also timer.start(1000); would be valid...
ANOTHER POSSIBILITY
Other possibility would be to use the timer associated with each Q_OBJECT and overload the timerEvent:
class ... {
Q_OBJECT
...
protected:
void timerEvent(QTimerEvent *event);
...
};
Then you must implement the timer event as this:
void MyClass::timerEvent(QTimerEvent *event) {
processMessages();
}
And you can configure the timer with a simple call to startTimer(1000);