summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/opengl/hellogl2/glwidget.cpp1
-rw-r--r--examples/opengl/qopenglwidget/glwidget.cpp51
-rw-r--r--examples/opengl/qopenglwidget/glwidget.h9
-rw-r--r--examples/opengl/qopenglwidget/main.cpp3
-rw-r--r--examples/opengl/qopenglwidget/mainwindow.cpp56
-rw-r--r--examples/opengl/qopenglwidget/mainwindow.h3
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);