Is it possible to add GUI for QOpenGLWindow? The button should be in the center of the OpenGL canvas.
-
Hello,
Is it possible to add GUI for QOpenGLWindow?
Clarification added: The button should be in the center of the OpenGL canvas.
-
The solution is here: https://forum.qt.io/post/756018 But I prefer to make my own GUI in OpenGL for games: https://forum.qt.io/post/755887
I see that it is impossible, becauseFailed to place widget over widget container containing QOpenGLWindow See example: https://forum.qt.io/post/753086QWidget::createWindowContainer
doesn't work properly. Perhaps this is a bug. I created a bug report: -
-
@8Observer8 you can overlay some on it. That is what I did.
-
@8Observer8 you can create a QWidget with a layout and put your OpenGL Window in it.
Then use QWidget as parent to create for example a button. Place the button(not into the layout) where you want. It can be on top of your OpenGL Window. -
@JoeCFD But actually my main goal is to create a game GUI. For example, create a button on top of the graphics. Is it possible?
For example, a button:
main.cpp
/* .pro file: QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 SOURCES += main.cpp TARGET = app ------------------------------- Build and run commands for CMD: > qmake -makefile > mingw32-make > "release/app" */ #ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif #include <iostream> #include <QtCore/QSize> #include <QtGui/QOpenGLFunctions> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> #include <QtWidgets/QPushButton> #include <QtWidgets/QVBoxLayout> class OpenGLWidget : public QOpenGLWidget, QOpenGLFunctions { Q_OBJECT public: OpenGLWidget() { setFixedSize(QSize(350, 350)); setWindowTitle("OpenGL21 Qt6 C++"); QVBoxLayout *vbox = new QVBoxLayout(); QPushButton *startButton = new QPushButton("Start Game"); startButton->setFixedSize(QSize(120, 50)); QHBoxLayout *startButtonLayout = new QHBoxLayout(); startButtonLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter); startButtonLayout->addWidget(startButton); vbox->addLayout(startButtonLayout); setLayout(vbox); // Set font for the start button QFont font = startButton->font(); font.setPointSize(14); startButton->setFont(font); // Set style for the start button startButton->setObjectName("startButton"); setStyleSheet( "QPushButton#startButton {" " background-color: yellow;" " border-radius: 10px;" "}" "QPushButton#startButton:pressed {" " background-color: red;" " border-radius: 10px;" "}"); connect(startButton, &QPushButton::clicked, this, &OpenGLWidget::startButtonClick); } private slots: void startButtonClick() { std::cout << "start button click" << std::endl; } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.1f, 0.3f, 0.2f, 1.f); } void resizeGL(int w, int h) override { glViewport(0, 0, w, h); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; #include "main.moc" int main(int argc, char *argv[]) { #ifdef _WIN32 if (AttachConsole(ATTACH_PARENT_PROCESS)) { freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); } #endif std::cout << std::endl; QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }
-
@8Observer8 I never tried integrating OpenGL into Qt GUI but my first feeling is that this is what QOpenGLWindow is intended for.
-
@8Observer8 Yes, you can. But I would not add button to the OpenGLWidget. Instead, create a QWidget, for example;
class DisplayWidget : public QWidget { explicit DisplayWidget( QWidget * parent=nullptr ) : QWidget( parent ) { make a layout and add m_openGLWidget; m_startGameButton = new QPushButton( QString( "Start Game" ), this ); /* do not add it to the layout */ m_startGameButton->move( center); } private: OpenGLWidget * m_openGLWidget{}; QPushButton * m_startGameButton{}; }
After button click, either hide it(for reuse) or destroy it(not needed anymore)
separate all controls from OpenGLWidget and make OpenGLWidget handling drawing only. Otherwise, the code looks a bit messy. -
@ankou29666 said in Is it possible to add GUI for QOpenGLWindow?:
I never tried integrating OpenGL into Qt GUI but my first feeling is that this is what QOpenGLWindow is intended for.
But the developers removed the dependency on the
widgets
module for better performance: https://doc.qt.io/qt-6/qopenglwindow.htmlQOpenGLWindow is an enhanced QWindow that allows easily creating windows that perform OpenGL rendering using an API that is compatible with QOpenGLWidget Unlike QOpenGLWidget, QOpenGLWindow has no dependency on the widgets module and offers better performance.
For example, QOpenGLWindow doesn't have the
setLayout
method. -
@8Observer8 QOpenGLWindow depends on QWindow, which as far as I understand is rather intended for QtQuick, but not for QtWidget.
QOpenGLWindow depends on QWindow and QWindow is not QWidget.
If you want a QtWidget app, you need QOpenGLWidget instead (which is based on QWidget and thus has setLayout). -
@ankou29666 said in Is it possible to add GUI for QOpenGLWindow?:
If you want a QtWidget app, you need QOpenGLWidget instead (which is based on QWidget and thus has setLayout).
QOpenGLWidget has a bad performance for animations, i.e. the animation is not smooth, because there is no synchronization for updating frames on the monitor. To solve this problem, QOpengLWindow was created with the frameSwapped signal: https://doc.qt.io/qt-6/qopenglwindow.html#frameSwapped
This signal is emitted after the potentially blocking buffer swap has been done. Applications that wish to continuously repaint synchronized to the vertical refresh, should issue an update() upon this signal. This allows for a much smoother experience compared to the traditional usage of timers.
-
@8Observer8 yes this is issue to consider indeed. I hadn't read properly your second doc quote ...
QOpenGLWindow depends on QWindow and so does QQuickWindow ...
What QWindow's doc says
QWindow::QWindow(QWindow *parent)
Creates a window as a child of the given parent window.
The window will be embedded inside the parent window, its coordinates relative to the parent.
The only option I see then would be something like nesting QOpenGLWindow inside a QQuickWindow and do your ui in QtQuick and QML instead.
-
@JoeCFD I am trying to compile your example. What the
center
variable here:main_window.h
#ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H #include <QtCore/QString> #include <QtWidgets/QPushButton> #include <QtWidgets/QWidget> #include "opengl_window.h" class MainWindow : public QWidget { public: explicit MainWindow(QWidget * parent=nullptr) : QWidget(parent) { m_pStartGameButton = new QPushButton(QString("Start Game"), this); /* do not add it to the layout */ m_pStartGameButton->move(center); } private: OpenGLWindow *m_pOpenGLWindow {}; QPushButton *m_pStartGameButton {}; }; #endif // MAIN_WINDOW_H
-
@ankou29666 said in Is it possible to add GUI for QOpenGLWindow?:
The only option I see then would be something like nesting QOpenGLWindow inside a QQuickWindow and do your ui in QtQuick and QML instead.
I will first try placing a QPushButton on top of a QOpenGLWindow as suggested by JoeCFD and then try your way.
-
@8Observer8 it is pseudocode. I do not know the center coordinates of your widget. You need to know where it is.
-
@JoeCFD said in Is it possible to add GUI for QOpenGLWindow?:
make a layout and add m_openGLWidget;
How to add it to layout?
QHBoxLayout *hbox = new QHBoxLayout(); hbox->addWidget(m_pOpenGLWindow);
error: no matching function for call to 'QHBoxLayout::addWidget(OpenGLWindow*&)' vbox->addWidget(m_pOpenGLWindow);
main_window.h
#ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H #include <QtCore/QSize> #include <QtCore/QString> #include <QtWidgets/QHBoxLayout> #include <QtWidgets/QPushButton> #include <QtWidgets/QWidget> #include "opengl_window.h" class MainWindow : public QWidget { public: explicit MainWindow(QWidget *parent=nullptr) : QWidget(parent) { setFixedSize(QSize(300, 300)); m_pStartGameButton = new QPushButton(QString("Start Game"), this); // m_pStartGameButton->move(center); QHBoxLayout *hbox = new QHBoxLayout(); m_pOpenGLWindow = new OpenGLWindow(); hbox->addWidget(m_pOpenGLWindow); } ~MainWindow() { delete m_pOpenGLWindow; } private: OpenGLWindow *m_pOpenGLWindow {}; QPushButton *m_pStartGameButton {}; }; #endif // MAIN_WINDOW_H
opengl_window.h
#ifndef OPENGL_WINDOW_H #define OPENGL_WINDOW_H #include <QtCore/QSize> #include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGL/QOpenGLWindow> #include <iostream> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { public: OpenGLWindow() { resize(QSize(300, 300)); setTitle("OpenGL 2.1, Qt6, C++"); // Set format QSurfaceFormat format; format.setSamples(4); format.setSwapInterval(1); setFormat(format); connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2, 0.2, 0.2, 1); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); // std::cout << "paintGL" << std::endl; } }; #endif // OPENGL_WINDOW_H
main.cpp
/* .pro file: QT += core gui opengl widgets win32: LIBS += -lopengl32 SOURCES += main.cpp TARGET = app ------------------------------- Build and run commands for CMD: > qmake -makefile > mingw32-make > "release/app" */ #ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif #include <QtWidgets/QApplication> #include <iostream> #include "main_window.h" int main(int argc, char *argv[]) { #ifdef _WIN32 if (AttachConsole(ATTACH_PARENT_PROCESS)) { freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); } #endif std::cout << std::endl; QApplication app(argc, argv); MainWindow w; w.show(); return app.exec(); }
-
@8Observer8 said in Is it possible to add GUI for QOpenGLWindow?:
m_pOpenGLWindow
m_pOpenGLWindow is not created. Is its header included? QOpenGLWidget is a widget. Sure you can add it to the layout.
-
I posted all the example code above.
-
@JoeCFD said in Is it possible to add GUI for QOpenGLWindow?:
QOpenGLWidget is a widget. Sure you can add it to the layout.
I just replaced QOpenGLWidget to QOpenGLWindow in your example. I don't need QOpenGLWidget.
-
@8Observer8 You can not add it to the layout. I use QOpenGLWidget. You can overlay your button to any widget which holds QOpenGLWindow.
https://stackoverflow.com/questions/32593428/add-qwidget-on-top-of-qopenglwindow