diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/opengl/hellogl2/glwidget.cpp | 1 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/glwidget.cpp | 51 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/glwidget.h | 9 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/main.cpp | 3 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/mainwindow.cpp | 56 | ||||
-rw-r--r-- | examples/opengl/qopenglwidget/mainwindow.h | 3 |
6 files changed, 101 insertions, 22 deletions
diff --git a/examples/opengl/hellogl2/glwidget.cpp b/examples/opengl/hellogl2/glwidget.cpp index 9988902071..23736cd752 100644 --- a/examples/opengl/hellogl2/glwidget.cpp +++ b/examples/opengl/hellogl2/glwidget.cpp @@ -131,6 +131,7 @@ void GLWidget::cleanup() delete m_program; m_program = nullptr; doneCurrent(); + QObject::disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup); } static const char *vertexShaderSourceCore = diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp index a480fe5726..da098319e4 100644 --- a/examples/opengl/qopenglwidget/glwidget.cpp +++ b/examples/opengl/qopenglwidget/glwidget.cpp @@ -66,9 +66,8 @@ const int bubbleNum = 8; #define GL_SRGB8_ALPHA8 0x8C43 #endif -GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) - : m_mainWindow(mw), - m_hasButton(button), +GLWidget::GLWidget(MainWindow *maybeMainWindow, const QColor &background) + : m_mainWindow(maybeMainWindow), m_background(background) { setMinimumSize(300, 250); @@ -78,20 +77,41 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background) GLWidget::~GLWidget() { + reset(); +} + +void GLWidget::reset() +{ qDeleteAll(m_bubbles); + // Leave everything in a state suitable for a subsequent call to + // initialize(). This matters when coming from the context's + // aboutToBeDestroyed signal, would not matter when invoked from the + // destructor. + m_bubbles.clear(); // And now release all OpenGL resources. makeCurrent(); delete m_texture; + m_texture = nullptr; delete m_program1; + m_program1 = nullptr; delete m_program2; + m_program2 = nullptr; delete m_vshader1; + m_vshader1 = nullptr; delete m_fshader1; + m_fshader1 = nullptr; delete m_vshader2; + m_vshader2 = nullptr; delete m_fshader2; + m_fshader2 = nullptr; m_vbo1.destroy(); m_vbo2.destroy(); doneCurrent(); + + // We are done with the current QOpenGLContext, forget it. If there is a + // subsequent initialize(), that will then connect to the new context. + QObject::disconnect(m_contextWatchConnection); } void GLWidget::setScaling(int scale) @@ -334,6 +354,13 @@ void GLWidget::initializeGL() m_vbo1.release(); createBubbles(bubbleNum - m_bubbles.count()); + + // A well-behaved QOpenGLWidget releases OpenGL resources not only upon + // destruction, but also when the associated OpenGL context disappears. If + // the widget continues to exist, the context's destruction will be + // followed by a call to initialize(). This is not strictly mandatory in + // widgets that never change their parents. + m_contextWatchConnection = QObject::connect(context(), &QOpenGLContext::aboutToBeDestroyed, context(), [this] { reset(); }); } void GLWidget::paintGL() @@ -403,7 +430,7 @@ void GLWidget::paintGL() // When requested, follow the ideal way to animate: Rely on // blocking swap and just schedule updates continuously. - if (!m_mainWindow->timerEnabled()) + if (!m_mainWindow || !m_mainWindow->timerEnabled()) update(); } @@ -545,16 +572,16 @@ void GLWidget::setTransparent(bool transparent) void GLWidget::resizeGL(int, int) { - if (m_hasButton) { + if (m_mainWindow) { if (!m_btn) { - m_btn = new QPushButton("A widget on top.\nPress for more widgets.", this); - connect(m_btn, &QPushButton::clicked, this, &GLWidget::handleButtonPress); + m_btn = new QPushButton("\nAdd widget\n", this); + connect(m_btn, &QPushButton::clicked, this, [this] { m_mainWindow->addNew(); }); } m_btn->move(20, 80); + if (!m_btn2) { + m_btn2 = new QPushButton("\nI prefer tabbed widgets\n", this); + connect(m_btn2, &QPushButton::clicked, this, [this] { m_mainWindow->showNewWindow(); }); + } + m_btn2->move(20, 160); } } - -void GLWidget::handleButtonPress() -{ - m_mainWindow->addNew(); -} diff --git a/examples/opengl/qopenglwidget/glwidget.h b/examples/opengl/qopenglwidget/glwidget.h index 50f8aa9be5..bc664f474c 100644 --- a/examples/opengl/qopenglwidget/glwidget.h +++ b/examples/opengl/qopenglwidget/glwidget.h @@ -71,7 +71,7 @@ class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: - GLWidget(MainWindow *mw, bool button, const QColor &background); + GLWidget(MainWindow *maybeMainWindow, const QColor &background); ~GLWidget(); public slots: @@ -81,9 +81,6 @@ public slots: void setShowBubbles(bool); void setTransparent(bool transparent); -private slots: - void handleButtonPress(); - protected: void resizeGL(int w, int h) override; void paintGL() override; @@ -96,6 +93,7 @@ private: void createBubbles(int number); void quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4); void extrude(qreal x1, qreal y1, qreal x2, qreal y2); + void reset(); MainWindow *m_mainWindow; qreal m_fAngle = 0; @@ -126,8 +124,9 @@ private: int m_textureUniform2 = 0; bool m_transparent = false; QPushButton *m_btn = nullptr; - bool m_hasButton; + QPushButton *m_btn2 = nullptr; QColor m_background; + QMetaObject::Connection m_contextWatchConnection; }; #endif diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp index 968b2a7258..08d1f2f14f 100644 --- a/examples/opengl/qopenglwidget/main.cpp +++ b/examples/opengl/qopenglwidget/main.cpp @@ -84,6 +84,7 @@ int main( int argc, char ** argv ) QSurfaceFormat::setDefaultFormat(format); MainWindow mw; - mw.showMaximized(); + mw.resize(1280, 720); + mw.show(); return a.exec(); } diff --git a/examples/opengl/qopenglwidget/mainwindow.cpp b/examples/opengl/qopenglwidget/mainwindow.cpp index eb34f87cb7..b3cbb4a69b 100644 --- a/examples/opengl/qopenglwidget/mainwindow.cpp +++ b/examples/opengl/qopenglwidget/mainwindow.cpp @@ -59,13 +59,16 @@ #include <QRandomGenerator> #include <QSpinBox> #include <QScrollArea> +#include <QTabWidget> +#include <QTabBar> +#include <QToolButton> #include "glwidget.h" MainWindow::MainWindow() : m_nextX(1), m_nextY(1) { - GLWidget *glwidget = new GLWidget(this, true, qRgb(20, 20, 50)); + GLWidget *glwidget = new GLWidget(this, qRgb(20, 20, 50)); m_glWidgets << glwidget; QLabel *label = new QLabel(this); m_timer = new QTimer(this); @@ -127,6 +130,7 @@ MainWindow::MainWindow() QAction *showBubbles = showMenu->addAction("Show bubbles", glwidget, &GLWidget::setShowBubbles); showBubbles->setCheckable(true); showBubbles->setChecked(true); + showMenu->addAction("Open tab window", this, &MainWindow::showNewWindow); QMenu *helpMenu = menuBar()->addMenu("&Help"); helpMenu->addAction("About Qt", qApp, &QApplication::aboutQt); @@ -156,9 +160,9 @@ void MainWindow::addNew() { if (m_nextY == 4) return; - GLWidget *w = new GLWidget(this, false, qRgb(QRandomGenerator::global()->bounded(256), - QRandomGenerator::global()->bounded(256), - QRandomGenerator::global()->bounded(256))); + GLWidget *w = new GLWidget(nullptr, qRgb(QRandomGenerator::global()->bounded(256), + QRandomGenerator::global()->bounded(256), + QRandomGenerator::global()->bounded(256))); m_glWidgets << w; connect(m_timer, &QTimer::timeout, w, QOverload<>::of(&QWidget::update)); m_layout->addWidget(w, m_nextY, m_nextX, 1, 1); @@ -185,3 +189,47 @@ void MainWindow::resizeEvent(QResizeEvent *) { m_glWidgets[0]->setMinimumSize(size() + QSize(128, 128)); } + +void MainWindow::showNewWindow() +{ + QTabWidget *tabs = new QTabWidget; + tabs->resize(800, 600); + + QToolButton *tb = new QToolButton; + tb->setText(QLatin1String("+")); + tabs->addTab(new QLabel(QLatin1String("Add OpenGL widgets with +")), QString()); + tabs->setTabEnabled(0, false); + tabs->tabBar()->setTabButton(0, QTabBar::RightSide, tb); + tabs->tabBar()->setTabsClosable(true); + QObject::connect(tabs->tabBar(), &QTabBar::tabCloseRequested, tabs, [tabs](int index) { + tabs->widget(index)->deleteLater(); + }); + + const QString msgToTopLevel = QLatin1String("Break out to top-level window"); + const QString msgFromTopLevel = QLatin1String("Move back under tab widget"); + + QObject::connect(tb, &QAbstractButton::clicked, tabs, [=] { + GLWidget *glwidget = new GLWidget(nullptr, Qt::blue); + glwidget->resize(tabs->size()); + glwidget->setWindowTitle(QString::asprintf("QOpenGLWidget %p", glwidget)); + + QPushButton *btn = new QPushButton(msgToTopLevel, glwidget); + connect(btn, &QPushButton::clicked, glwidget, [=] { + if (glwidget->parent()) { + glwidget->setAttribute(Qt::WA_DeleteOnClose, true); + glwidget->setParent(nullptr); + glwidget->show(); + btn->setText(msgFromTopLevel); + } else { + glwidget->setAttribute(Qt::WA_DeleteOnClose, false); + tabs->addTab(glwidget, glwidget->windowTitle()); + btn->setText(msgToTopLevel); + } + }); + + tabs->setCurrentIndex(tabs->addTab(glwidget, glwidget->windowTitle())); + }); + + tabs->setAttribute(Qt::WA_DeleteOnClose); + tabs->show(); +} diff --git a/examples/opengl/qopenglwidget/mainwindow.h b/examples/opengl/qopenglwidget/mainwindow.h index 43cc55100e..69dcb34bb9 100644 --- a/examples/opengl/qopenglwidget/mainwindow.h +++ b/examples/opengl/qopenglwidget/mainwindow.h @@ -68,6 +68,9 @@ public: void resizeEvent(QResizeEvent *); +public slots: + void showNewWindow(); + private slots: void updateIntervalChanged(int value); void timerUsageChanged(bool enabled); |