Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
Source: https://mega.co.nz/#!xUMiSRYC!Y8Sxz2fEFb6yEIrnKiGx9n2zeK4YTUwUrCByaAkcOPI
I'm experiencing a problem with QThread::currentThread()->quit();
If you open up my myobject.cpp and go to line 13, the quit() call is supposed to exit. But it seems the quit() call isn't working and it just skips it. Can't see the problem. :(
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QObject::connect(&a, SIGNAL(aboutToQuit()),
&w, SLOT(cleanUp()));
return a.exec();
}
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myobject.h"
#include <QMessageBox>
MyObject* cObject;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(this->size());
cThread = new QThread(this);
cObject = new MyObject();
cObject->moveToThread(cThread);
QObject::connect(ui->pushButton_2, SIGNAL(clicked()),
this, SLOT(close()));
QObject::connect(cThread, SIGNAL(started()),
cObject, SLOT(doWork()));
QObject::connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(runThreadSlot()));
QObject::connect(cThread, SIGNAL(finished()),
cThread, SLOT(deleteLater()));
QObject::connect(cThread, SIGNAL(finished()),
cObject, SLOT(deleteLater()));
QObject::connect(cObject, SIGNAL(setStatusBarSignal(QString)),
this, SLOT(setStatusBarSlot(QString)));
ui->lineEdit->setValidator(new QIntValidator(this));
ui->lineEdit->setFocus(Qt::OtherFocusReason);
ui->statusBar->showMessage("Waiting for input...");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::runThreadSlot()
{
cThread->start();
// I've trimmed some code here.
}
void MainWindow::setStatusBarSlot(QString text)
{
ui->statusBar->showMessage(text);
}
void MainWindow::cleanUp()
{
qDebug() << "Cleaning up!";
cObject->stage = 0;
cThread->wait();
}
myobject.cpp:
#include "myobject.h"
#include <QPixmap>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::doWork()
{
QThread::currentThread()->quit(); // It doesn't stop here. This is my issue.
// I've trimmed the code here.
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void runThreadSlot();
void setStatusBarSlot(QString);
void cleanUp();
private:
Ui::MainWindow *ui;
QThread* cThread;
};
#endif // MAINWINDOW_H
myobject.h:
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QtCore>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
QFile path;
qint32 waitSecs;
int stage;
signals:
void setStatusBarSignal(QString);
public slots:
void doWork();
};
#endif // MYOBJECT_H
QThread::quit() is asynchronous. You shoul add QThread::currentThread()->wait() right after quit.
Related
I am trying to use OpenGLES in a desktop platform. I have a class whose name is GraphicsViewer which is derived from QOpenGLWidget. When I set the QSurfaceFormat::renderableType to QSurfaceFormat::OpenGLES, I get the following errors and nothing is drawn on the widget. Can you help me to create an OpenGLES context in a desktop platform? My OS is Windows 10 and my Qt version is 5.12.3.
Errors:
QOpenGLWidget: Failed to create context
QOpenGLWidget: Failed to create context
qt.qpa.backingstore: composeAndFlush: QOpenGLContext creation failed
QOpenGLWidget: Failed to create context
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed
Here is my codes...
main.cpp
#include "QtOpenGLES.h"
#include <QApplication>
#include <QSurfaceFormat>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat f;
f.setVersion(2, 0);
f.setRenderableType(QSurfaceFormat::OpenGLES);
QSurfaceFormat::setDefaultFormat(f);
QtOpenGLES w;
w.show();
return a.exec();
}
QtOpenGLES.h
#ifndef QTOPENGLES_H
#define QTOPENGLES_H
#include <QMainWindow>
namespace Ui {
class QtOpenGLES;
}
class QtOpenGLES : public QMainWindow
{
Q_OBJECT
public:
explicit QtOpenGLES(QWidget *parent = nullptr);
~QtOpenGLES();
private:
Ui::QtOpenGLES *ui;
};
#endif // QTOPENGLES_H
QtOpenGLES.cpp
#include "QtOpenGLES.h"
#include "ui_QtOpenGLES.h"
QtOpenGLES::QtOpenGLES(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::QtOpenGLES)
{
ui->setupUi(this);
}
QtOpenGLES::~QtOpenGLES()
{
delete ui;
}
GraphicsViewer.h
#ifndef GRAPHICSVIEWER_H
#define GRAPHICSVIEWER_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
class GraphicsViewer : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
GraphicsViewer(QWidget* parent = nullptr);
// QOpenGLWidget interface
protected:
void initializeGL();
void paintGL();
};
GraphicsViewer.cpp
#include "GraphicsViewer.h"
#include <QtOpenGL>
GraphicsViewer::GraphicsViewer(QWidget *parent) :
QOpenGLWidget (parent)
{
}
void GraphicsViewer::initializeGL()
{
initializeOpenGLFunctions();
}
void GraphicsViewer::paintGL()
{
glClearColor(1, 0, 0, 1);
}
In the program, I am trying to create a image player using QT. When I click a button in the UI, the program will create a image slideshow with a 2s pause. I tried to use the QTimer to such things, but failed to do so. Hence, I want to ask how to achieve my purpose by using QTimer.
Let me describe the flow of my program. When the user click a button in the main window, the sub-window showpic will be opened and then start showing each image for a pause of 2s in its qgraphsview. The images filepath are stored in the "QStringlist filenames".
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileSystemModel>
#include "showpic.h"
#include <QBasicTimer>
#include <QTimer>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void display(const QString & , ShowPic* );
private slots:
void tick();
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QFileSystemModel *model;
QString filesPath;
ShowPic *showpic;
QStringList filenames;
QStringList::const_iterator m_imageIt;
QTimer m_timer;
};
#endif // MAINWINDOW_H
showpic.h
#ifndef SHOWPIC_H
#define SHOWPIC_H
#include <QWidget>
namespace Ui {
class ShowPic;
}
class ShowPic : public QWidget
{
Q_OBJECT
public:
explicit ShowPic(QWidget *parent = 0);
~ShowPic();
private:
Ui::ShowPic *ui;
public:
void addPixmap(const QPixmap &pixmap);
};
#endif // SHOWPIC_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QFileDialog>
#include<QFileSystemModel>
#include<QStringList>
#include <QTreeView>
#include <QGraphicsScene>
#include <QTime>
#include <QThread>
#include <QDebug>
#include <iostream>
#include <QTimer>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
filenames.append("C:\\test\\image.jpg");
filenames.append("C:\\test\\apple.jpg");
filenames.append("C:\\test\\orange.jpg");
filenames.append("C:\\test\\lemon.jpg");
filenames.append("C:\\test\\grape.jpg");
m_imageIt = filenames.begin();
m_timer.setInterval(5000);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::display(const QString & filename, ShowPic* showpic) {
showpic->addPixmap(filename);
}
void MainWindow::tick(){
showpic = new ShowPic();
showpic->show();
display(*m_imageIt, showpic);
m_imageIt ++;
}
/*
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId()) tick();
}*/
void MainWindow::on_pushButton_clicked()
{
/*showpic = new ShowPic();
QPixmap pixmap("C:\\test\\image.jpg");
showpic->addPixmap(pixmap);
showpic->show();*/
m_timer.start();
}
showpic.cpp
#include "showpic.h"
#include "ui_showpic.h"
#include <QThread>
ShowPic::ShowPic(QWidget *parent) :
QWidget(parent),
ui(new Ui::ShowPic)
{
ui->setupUi(this);
ui->graphicsView->setScene(new QGraphicsScene);
}
ShowPic::~ShowPic()
{
delete ui;
}
void ShowPic::addPixmap(const QPixmap &pixmap){
ui->graphicsView->scene()->addPixmap(pixmap);
}
The compiling message error:
The error has nothing to do with the timer, it is because you forgot to declare display(), tick(), and timerEvent() as part of the MainWindow:: class, so they cannot access MainWindow members.
The timer should be even easier to use than your code. First I recommend you use a QTimer instead of QBasicTimer. Then you can simply connect to its timeout() signal.
mainwindow.h
#include <QTimer>
QTimer m_timer;
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
m_imageIt = filenames.begin();
m_timer.setInterval(5000);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
}
void MainWindow::on_pushButton_clicked()
{
m_timer.start();
}
You do not need timerEvent() function at all.
I want to implement simple commands like a qDebug() when I click on a sub menu in the mainwindow. I was referring to sample program given along with the Qt 5 IDE (...\Qt\Qt5.2.0\5.2.0\msvc2010\examples\widgets\mainwindows\menus), and using it, I managed to construct the code. I do not receive any compile time or run time errors.
I created the mainwindow.ui using the design mode. It has an object of the QAction class called actionInterval.
But when I click on it, nothing happens, I am not able to implement the command in void interval(). I guess I am not connecting properly. What am I missing here? Please advise.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
void createActions();
private slots:
void interval();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
createActions();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createActions()
{
ui->actionInterval = new QAction(tr("&Interval"), this);
ui->actionInterval->setStatusTip(tr("Set the interval for capturing delta & reference images"));
connect(ui->actionInterval, SIGNAL(triggered()), this, SLOT(interval()));
}
void MainWindow::interval()
{
qDebug()<<"inside interval qdialog";
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
void MainWindow::createActions()
{
ui->actionInterval->setStatusTip(tr("Set the interval for capturing delta & reference images"));
connect(ui->actionInterval, SIGNAL(triggered()), this, SLOT(interval()));
}
You shouldn't need that ui->actionInterval = new QAction(tr("&Interval"), this); line, the ui->setupUi() handles that for you, so it's potentially causing an incorrect reference so when you do click on it it's not firing correctly.
i was experimenting with QThread the other day and i wanted to create an infinite loop by using signals only and not for, foreach or while but then my code would crash after emitting the signal and executing the slot for a number of times here's my code:
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "worker.h"
#include <QThread>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void startthreads();
private:
Ui::MainWindow *ui;
QThread thread;
worker *work;
};
#endif // MAINWINDOW_H
//worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDebug>
#include <QMutex>
#include "insiderobject.h"
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
signals:
void doagain();
void okidid();
void finished();
public slots:
void printing();
};
#endif // WORKER_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
startthreads();
}
MainWindow::~MainWindow()
{
thread.wait();
delete ui;
delete work;
}
void MainWindow::startthreads()
{
work = new worker;
work->moveToThread(&thread);
connect(&thread, SIGNAL(started()), work, SLOT(printing()));
connect(work, SIGNAL(finished()), &thread, SLOT(quit()));
thread.start();
}
//worker.cpp
#include "worker.h"
worker::worker(QObject *parent) :
QObject(parent)
{
connect(this, SIGNAL(okidid()), this, SLOT(printing()));
}
void worker::printing()
{
qDebug() << "printing";
emit okidid();
}
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
i have read the entire documentation for signal/slots and threads and queued connections or whatever i could get my hands on but i could not understand the reason for this crash... also i tried chatting with people and developers at Qt irc chat room but no one could tell me the reason.
What you are doing is an infinite recursion. emit okidid(); is actually a direct call to worker::printing(). That will cause a stack overflow.
You can fix this by using a queued signal connection:
connect(this, SIGNAL(okidid()), this, SLOT(printing()), Qt::QueuedConnection);
Now the emit okidid(); is not a direct function call anymore. The worker::printing() function will be called in the Qt's event loop.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void disableStartButton();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QtCore>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
void doSetup(QThread &cThread);
signals:
void disableStartButton();
public slots:
void doWork();
};
#endif // MYOBJECT_H
main.cpp:
#include "mainwindow.h"
#include "myobject.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
QThread cThread;
MyObject cObject;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
return a.exec();
}
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::disableStartButton() {
ui->pushButton->setEnabled(false);
}
myobject.h:
#include "myobject.h"
#include <QDebug>
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::doSetup(QThread &cThread)
{
connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start())); // (1)
connect(this, SIGNAL(disableStartButton()), ui, SLOT(disableStartButton())); // (2)
}
void MyObject::doWork()
{
emit disableStartButton();
qDebug() << "1";
}
I'm trying to do two things.
(1): As soon pushButton is clicked, I want cThread to start.
(2): As soon as cThread starts, it does: emit disableStartButton();. I want to connect disableStartButton() to disableStartButton() in mainwindow.cpp.
For (1), I get this error:
myobject.cpp:12: error: C2065: 'ui' : undeclared identifier
Of course, there ui is undefined. You try to connect ui->pushButton
connect(ui->pushButton, SIGNAL(clicked()), &cThread, SLOT(start())); // (1)
in file myobject.cpp, when your ui declared only in mainwindow.cpp
You have to connect pushbutton to your thread within mainwindow.cpp file, hope that helps
By the way, you should create your objects NOT in main.cpp but, in your case, in mainwindow.cpp, move lines
QThread cThread;
MyObject cObject;
cObject.doSetup(cThread);
cObject.moveToThread(&cThread);
to file mainwindow.cpp in constructor, for example
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
right after ui->setupUi(this);