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);
}
Related
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 am trying to take a feedback data which is published from arduino and subscribed to my GUI created in QT.
Now i have main.cpp and mainwindow.cpp.
main.cpp
#include <QtGui>
#include <ros/ros.h>
#include <QApplication>
#include "../include/abc/main_window.hpp"
#include "std_msgs/String.h"
#include <std_msgs/UInt16.h>
#include <QMainWindow>
#include <std_msgs/Float32.h>
void chatterCallback(const std_msgs::UInt16 &fb_msg){
ROS_INFO("Feedback: [%f]", fb_msg.data);
ui.label_6->setText(QString("%1").arg(fb_msg.data));
}
int main(int argc, char **argv) {
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("feedback",1000, chatterCallback);
ros::spinOnce();
QApplication app(argc, argv);
abc::MainWindow w(argc,argv);
w.show();
w.setWindowTitle("GUI for Controlling Servo Motor");
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
int result = app.exec();
return result;}
mainwindow.cpp
namespace abc {
using namespace Qt;
QSerialPort *serial;
MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
: QMainWindow(parent)
, qnode(argc,argv)
{
ui.setupUi(this);
}
MainWindow::~MainWindow() {}
void MainWindow::on_horizontalSlider_valueChanged(int value)
{
ui.label_5->setText(QString("%1").arg(value));
msg.data = ui.label_5->text().toUInt();
ROS_INFO("%d", msg.data);
chatter_pub.publish(msg);
ros::spinOnce();
}
main_window.hpp
#ifndef abc_MAIN_WINDOW_H
#define abc_MAIN_WINDOW_H
#include <QtGui/QMainWindow>
#include "ui_main_window.h"
#include "qnode.hpp"
#include <QtSerialPort/QSerialPort>
#include <ros/ros.h>
#include "std_msgs/UInt16.h"
namespace abc {
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(int argc, char** argv, QWidget *parent = 0);
~MainWindow();
public Q_SLOTS:
private:
Ui::MainWindowDesign ui;
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise <std_msgs::UInt16> ("chatter", 1000);
QSerialPort *arduino;
QNode qnode;
};
} // namespace abc
#endif // abc_MAIN_WINDOW_H
Now when i run this code, it shows me that UI is not declared in main.cpp.
I wanted to display the data from feedback to label_6 (TextBox). The data is only available in main.cpp, any suggestions are highly appreciable.
Thanks in advance.
You will have to pass the fb_msg.data as an argument to the MainWindow constructor. Then you can set the UI element in the MainWindow thread.
Alternatively once you create the MainWindow instance in your main, you can emit a signal which you catch and process in the MainWindow thread.
You cannot modify the UI elements from a different thread.
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);
I've been struggling with the problem of initializing of multiple forms in Qt under Windows (the version is 5.0.1 but I don't reckon this to matter much). Long story short, my application contains of 2 forms the one of which is supposed to be called on clicking the button on the another one.
The code runs as follows:
1) main.cpp:
#include "main.h"
#include <QApplication>
FmNewWord fmNewWord;
MainWindow w;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
w.show();
return a.exec();
}
2) main.h:
#ifndef MAIN_H
#define MAIN_H
#include "mainwindow.h"
#include "fmnewword.h"
extern FmNewWord fmNewWord;
extern MainWindow w;
#endif // MAIN_H
3) mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "ui_mainwindow.h"
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
signals:
void sgnl_new_word();
public:
explicit MainWindow(QWidget *parent = 0);
protected:
void changeEvent(QEvent *e);
private slots:
void on_commandLinkButton_clicked();
void on_miExit_triggered();
void on_miNewWord_triggered();
};
#endif // MAINWINDOW_H
4) mainwindow.cpp:
#include "main.h"
#include <Windows.h>
extern FmNewWord fmNewWord;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
}
void MainWindow::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
void MainWindow::on_commandLinkButton_clicked()
{
MessageBox(0, 0, 0, 0);
}
void MainWindow::on_miExit_triggered()
{
this->close();
}
void MainWindow::on_miNewWord_triggered()
{
fmNewWord.show();
}
5) fmnewword.cpp:
#include "fmnewword.h"
FmNewWord::FmNewWord(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this); /// here the app crashes with parent == NULL
}
void FmNewWord::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
retranslateUi(this);
break;
default:
break;
}
}
6) fmnewword.h:
#ifndef FMNEWWORD_H
#define FMNEWWORD_H
#include "ui_fmnewword.h"
class FmNewWord : public QMainWindow, private Ui::FmNewWord
{
Q_OBJECT
public:
explicit FmNewWord(QWidget *parent = 0);
protected:
void changeEvent(QEvent *e);
};
#endif // FMNEWWORD_H
The code keeps crashing during inititialization in fmnewword.cpp on the line shown. Could anybody point out the reason? Thanks.
First of all, QApplication must be created before any widgets.
Your code should look llike this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
And that's how the second form must be created:
class FmNewWord;
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
...
private slots:
void on_miNewWord_triggered();
private:
FmNewWord *fmNewWord;
};
void MainWindow::on_miNewWord_triggered()
{
fmNewWord = new FmNewWord;
fmNewWord->show();
}