QPixmap and GUI application - how end my app?
-
Hello,
I have a problem with ending my GUI Application. Often I get warnings:QPixmap::fromImageInPlace: QPixmap cannot be created without a QGuiApplication QPixmap: Must construct a QGuiApplication before a QPixmap
My code:
while(1) { QPixmap pixmap = qApp->screens().at(0)->grabWindow(QDesktopWidget().winId()); label->setPixmap(pixmap.scaled(label->width(), label->height(), Qt::KeepAspectRatio)); }
When I close my App, my App is deleted, but grabWindow function is still working, but there is no qApp when pixmap is ready.
How can I wait until grabWindow() will be ready and next I'll end my app.
EDIT:
One solution is to add "Sleep(1000)" in the MainWindow destructor before delete ui. It works, but I think there is better solution -
Hi
Do you have that code in a thread
as while(1) is pure evil for a GUI app. -
Hi
You have to fix your thread code then so it can exit the loop on some condition.
then in the main app doconnect(qApp, &QApplication::aboutToQuit, Yourthread, [=]{
Yourthread->quit();
Yourthread->wait();
});Did you override thread::run ?
-
@mrjj My current code is:
class threadx: public QThread { Q_OBJECT public: threadx(clickableLabel * l, int i); void run() override; void setKill(); private: clickableLabel* label; int whichOne; bool kill = false; };
threadx::threadx(clickableLabel * l, int i): label(l), whichOne(i){} void threadx::run() { while(1) { QPixmap pixmap = qApp->screens().at(0)->grabWindow(QDesktopWidget().winId()); label->setPixmap(pixmap.scaled(label->width(), label->height(), Qt::KeepAspectRatio)); if(kill) { terminate(); wait(); } } } void threadx::setKill() { kill = true; }
And In my mainWindow I only create QVector with xthreads:
threads.append(new threadx(wektor.last(),i));
After 200 msec I start them:
for(int i=0;i<threadsAmount;i++) { threads[i]->start(); }
And in mainWindow destructor I have:
for(auto x: threads) { x->setKill(); } Sleep(1000); delete ui;
-
Hi
How can this even run ?
Mine says ASSERT failure in QWidget: "Widgets must be created in the GUI thread.",
since you have a QLabel ? in the thread.Also you use wait inside the run and doc says
https://doc.qt.io/qt-5/qthread.html#wait
The thread associated with this QThread object has finished execution (i.e. when it returns from run()).so not sure thats is nice inside run
Also you use terminate which is brute force and should not be used ( often)
Try this
MainWindow::~MainWindow() { for (auto x : threads) { x->requestInterruption(); x->wait(); delete x; } delete ui; } void threadx::run() { while ( ! QThread::currentThread()->isInterruptionRequested()) { QPixmap pixmap = qApp->screens().at(0)->grabWindow(QDesktopWidget().winId()); label->setPixmap(pixmap.scaled(label->width(), label->height(), Qt::KeepAspectRatio)); } }
But im really, really surprised if you can use a Qwidget inside a thread. Its an instant crash for me.
-
@mrjj @SGaist I create QLabels in my main thread. The next threads get only pointers to labels and change pixmaps.
PseudoCode is:
my main thread
for(int i=0; i<screensAmount();i++) { vectorLabels[i] = new QLabel(); // here there are clickableLabels which are QLabels and I can click on them vectorthreadsx[i] = new threadx(vectorLabels[i], i); grid->addWidget(vectorLabels[i]); } QTimer::singleShot(200, this, slotStart()); slotStart(): { for(int i=0; i<screensAmount();i++) { vectorXthreads[i] ->start(); } }
And my threadx Class:
threadx::threadx(clickableLabel * l, int i): label(l), whichOne(i){} void threadx::run() { while(1) { QPixmap pixmap = qApp->screens().at(0)->grabWindow(QDesktopWidget().winId()); label->setPixmap(pixmap.scaled(label->width(), label->height(), Qt::KeepAspectRatio)); if(kill) { terminate(); wait(); } } }
And the second question:
I would like to get screen in Linux. In windows I have to do only:
QPixmap pixmap = qApp->screens().at(0)->grabWindow(QDesktopWidget().winId());
But in Linux this isn't work. So what can I do?
-
You are accessing a GUI element from a different thread which as already said shall not be done. QPixmap is a class ride to the graphics environment so it follows the same rule. If you to process some image in a different thread, use QImage and send that back to the original thread.