Класс QOpenGLWidget
Класс QOpenGLWidget — это виджет для отрисовки графики OpenGL. Подробнее...
| Заголовок: | #include <QOpenGLWidget> |
| CMake: | find_package(Qt6 COMPONENTS OpenGLWidgets REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::OpenGLWidgets) |
| qmake: | QT += openglwidgets |
| С момента: | Qt 5.4 |
| Наследуется от: | QWidget |
Типы public
| Перечисление | UpdateBehavior { NoPartialUpdate, PartialUpdate } |
Функции public
| QOpenGLWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags()) | |
| virtual | ~QOpenGLWidget() |
| QOpenGLContext * | context() const |
| GLuint | defaultFramebufferObject() const |
| void | doneCurrent() |
| QSurfaceFormat | format() const |
| QImage | grabFramebuffer() |
| bool | isValid() const |
| void | makeCurrent() |
| void | setFormat(const QSurfaceFormat &format) |
| void | setTextureFormat(GLenum texFormat) |
| void | setUpdateBehavior(QOpenGLWidget::UpdateBehavior updateBehavior) |
| GLenum | textureFormat() const |
| QOpenGLWidget::UpdateBehavior | updateBehavior() const |
Сигналы
| void | aboutToCompose() |
| void | aboutToResize() |
| void | frameSwapped() |
| void | resized() |
Защищенные функции
| virtual void | initializeGL() |
| virtual void | paintGL() |
| virtual void | resizeGL(int w, int h) |
Переопределенные защищенные функции
| virtual bool | event(QEvent *e) override |
| virtual int | metric(QPaintDevice::PaintDeviceMetric metric) const override |
| virtual QPaintEngine * | paintEngine() const override |
| virtual void | paintEvent(QPaintEvent *e) override |
| virtual QPaintDevice * | redirected(QPoint *p) const override |
| virtual void | resizeEvent(QResizeEvent *e) override |
Подробное описание
QOpenGLWidget предоставляет функциональность для отображения графики OpenGL, интегрированной в приложение Qt. Его очень просто использовать: сделайте свой класс наследником от него и используйте подкласс как любой другой QWidget, за исключением того, что у вас есть возможность использовать QPainter и стандартные команды OpenGL.
QOpenGLWidget предоставляет три удобные виртуальные функции, которые вы можете переопределить в своём подклассе для выполнения типичных задач OpenGL:
- paintGL() — отрисовывает сцену OpenGL. Вызывается всякий раз, когда виджету нужно обновиться.
- resizeGL() — настраивает область просмотра OpenGL, проекцию и т. д. Вызывается всякий раз, когда виджет был изменён по размеру (а также при его первом отображении, так как все недавно созданные виджеты автоматически получают событие изменения размера).
- initializeGL() — настраивает ресурсы и состояние OpenGL. Вызывается один раз перед первым вызовом resizeGL() или paintGL().
Если вам нужно инициировать перерисовку из мест, отличных от paintGL() (типичный пример — при использовании таймеров для анимации сцены), вы должны вызвать функцию update() виджета для планирования обновления.
Контекст OpenGL вашего виджета становится текущим при вызове paintGL(), resizeGL() или initializeGL(). Если вам нужно вызвать стандартные функции API OpenGL из других мест (например, в конструкторе виджета или в собственных функциях рисования), вы должны сначала вызвать makeCurrent().
Вся отрисовка происходит в объект буфера OpenGL. makeCurrent() гарантирует, что он привязан к контексту. Имейте это в виду при создании и привязке дополнительных объектов буфера в коде отрисовки в paintGL(). Никогда не перепривязывайте буфер с идентификатором 0. Вместо этого вызовите defaultFramebufferObject(), чтобы получить ID, который следует привязать.
QOpenGLWidget позволяет использовать разные версии и профили OpenGL, если платформа их поддерживает. Просто установите требуемый формат с помощью setFormat(). Однако имейте в виду, что наличие нескольких экземпляров QOpenGLWidget в одном окне требует, чтобы все они использовали один и тот же формат или, по крайней мере, форматы, которые не делают контексты несовместимыми для совместного использования. Чтобы обойти эту проблему, предпочитайте использовать QSurfaceFormat::setDefaultFormat() вместо setFormat().
Примечание: Вызов QSurfaceFormat::setDefaultFormat() до создания экземпляра QApplication обязателен на некоторых платформах (например, macOS) при запросе контекста профиля OpenGL Core. Это гарантирует, что совместное использование ресурсов между контекстами остаётся функциональным, так как все внутренние контексты создаются с использованием правильной версии и профиля.
Методы рисования
Как описано выше, подклассы QOpenGLWidget для отрисовки чистого 3D-содержимого следующим образом:
- Переопределите функции initializeGL() и resizeGL(), чтобы настроить состояние OpenGL и предоставить преобразование перспективы.
- Переопределите paintGL(), чтобы нарисовать 3D-сцену, вызывая только функции OpenGL.
Также можно нарисовать 2D-графику на подклассе QOpenGLWidget с помощью QPainter:
- В paintGL(), вместо выдачи команд OpenGL, создайте объект QPainter для использования на виджете.
- Рисуйте примитивы, используя функции члена QPainter.
- Прямые команды OpenGL всё ещё могут быть выпущены. Однако вы должны убедиться, что они заключены в вызов beginNativePainting() и endNativePainting() художника.
При выполнении рисования только с помощью QPainter, также можно выполнить рисование так, как это делается для обычных виджетов: переопределив paintEvent().
- Переопределите функцию paintEvent().
- Создайте объект QPainter, нацеленный на виджет. Передайте виджет в конструктор или используйте функцию QPainter::begin().
- Отобразите примитивы, используя методы объекта QPainter.
- Отображение завершается, когда экземпляр QPainter уничтожается. Также можно явно вызвать QPainter::end().
Вызовы функций OpenGL, заголовки и QOpenGLFunctions
При вызове функций OpenGL настоятельно рекомендуется избегать прямого обращения к ним. Вместо этого используйте QOpenGLFunctions (для создания портативных приложений) или версии с указанием версии (например, QOpenGLFunctions_3_2_Core и аналогичные, для работы с современным OpenGL только на настольных системах). Таким образом, приложение будет работать корректно во всех конфигурациях сборки Qt, включая те, которые выполняют динамическую загрузку реализации OpenGL, что означает, что приложения не связываются напрямую с реализацией GL, и поэтому прямые вызовы недоступны.
В функции paintGL() текущий контекст всегда доступен при вызове QOpenGLContext::currentContext(). Из этого контекста можно получить уже инициализированный и готовый к использованию экземпляр QOpenGLFunctions, вызвав QOpenGLContext::functions(). Альтернативой префиксации каждого вызова GL является наследование от QOpenGLFunctions и вызов QOpenGLFunctions::initializeOpenGLFunctions() в initializeGL().
Что касается заголовков OpenGL, то в большинстве случаев нет необходимости напрямую включать заголовки, такие как GL.h. Заголовки Qt, связанные с OpenGL, включат qopengl.h, который в свою очередь включит соответствующий заголовок для системы. Это может быть заголовок OpenGL ES 3.x или 2.0, самая последняя доступная версия, или системный заголовок gl.h. Кроме того, копия заголовков расширений (называемая glext.h на некоторых системах) предоставляется в составе Qt как для OpenGL, так и для OpenGL ES. Они будут автоматически включены на платформах, где это возможно. Это означает, что константы и определения типов указателей функций из расширений ARB, EXT, OES автоматически доступны.
Примеры кода
Для начала, самый простой подкласс QOpenGLWidget может выглядеть следующим образом:
class MyGLWidget : public QOpenGLWidget
{
public:
MyGLWidget(QWidget *parent) : QOpenGLWidget(parent) { }
protected:
void initializeGL() override
{
// Set up the rendering context, load shaders and other resources, etc.:
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
...
}
void resizeGL(int w, int h) override
{
// Update projection matrix and other size related settings:
m_projection.setToIdentity();
m_projection.perspective(45.0f, w / float(h), 0.01f, 100.0f);
...
}
void paintGL() override
{
// Draw the scene:
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
f->glClear(GL_COLOR_BUFFER_BIT);
...
}
}; В качестве альтернативы, можно избежать префиксации каждого вызова OpenGL, унаследовав от QOpenGLFunctions:
class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
...
void initializeGL() override
{
initializeOpenGLFunctions();
glClearColor(...);
...
}
...
}; Чтобы получить контекст, совместимый с заданной версией или профилем OpenGL, или чтобы запросить буферы глубины и трафарета, вызовите setFormat():
QOpenGLWidget *widget = new QOpenGLWidget(parent); QSurfaceFormat format; format.setDepthBufferSize(24); format.setStencilBufferSize(8); format.setVersion(3, 2); format.setProfile(QSurfaceFormat::CoreProfile); widget->setFormat(format); // must be called before the widget or its parent window gets shown
В контекстах OpenGL 3.0+, когда важно обеспечить переносимость, версии QOpenGLFunctions с указанием версии предоставляют простой доступ ко всем современным функциям OpenGL, доступным в заданной версии:
...
void paintGL() override
{
QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
...
f->glDrawArraysInstanced(...);
...
}
... Как описано выше, проще и надежнее установить запрашиваемый формат глобально, чтобы он применялся ко всем окнам и контекстам в течение всего срока службы приложения. Ниже приведен пример этого:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
MyWidget widget;
widget.show();
return app.exec();
} Многократная выборка
Чтобы включить многократную выборку, установите число запрашиваемых выборок в QSurfaceFormat, который передается в setFormat(). На системах, которые не поддерживают это, запрос может быть проигнорирован.
Поддержка многократной выборки требует поддержки многократной выборки буферов рендеринга и блинков фреймбуфера. В реализациях OpenGL ES 2.0 их, вероятно, не будет. Это означает, что многократная выборка будет недоступна. В современных версиях OpenGL и OpenGL ES 3.0 и выше эта проблема обычно больше не возникает.
Потоки
Поддерживается выполнение рендеринга вне экрана в потоках обработки задач, например, для генерации текстур, которые затем используются в пользовательском интерфейсе/главном потоке в paintGL(), путем предоставления QOpenGLContext виджета, чтобы на каждом потоке можно было создать дополнительные контексты, совмещающие ресурсы с ним.
Рисование непосредственно в буфер кадра QOpenGLWidget вне пользовательского интерфейса/главного потока возможно путем переопределения paintEvent() на пустую операцию. Аффинность потока контекста должна быть изменена с помощью QObject::moveToThread(). После этого makeCurrent() и doneCurrent() можно использовать в потоке обработки задач. Следует позаботиться о возвращении контекста в пользовательский интерфейс/главный поток.
Триггерный обмен буфером только для QOpenGLWidget невозможен, так как для него нет реальной, отображаемой на экране нативной поверхности. Стек виджетов управляет композицией и обменом буферами в потоке пользовательского интерфейса.
Когда поток завершает обновление буфера кадра, вызовите update() в потоке пользовательского интерфейса/главного потоке для планирования композиции.
Особое внимание необходимо уделить, чтобы избежать использования буфера кадра, когда поток пользовательского интерфейса/главного потока выполняет композицию. Сигналы aboutToCompose() и frameSwapped() будут испущены при запуске и завершении композиции. Они испускаются в потоке пользовательского интерфейса/главного потоке. Это означает, что с помощью прямой связи aboutToCompose() можно заблокировать поток пользовательского интерфейса/главного потока до тех пор, пока поток обработки задач не завершит рендеринг. После этого поток обработки задач не должен выполнять дальнейший рендеринг до испускания сигнала frameSwapped(). Если это неприемлемо, поток обработки задач должен реализовать механизм двойного буферирования. Это включает рисование с использованием альтернативного целевого объекта рендеринга, полностью контролируемого потоком, например, дополнительного буфера кадра, и блинков в буфер кадра QOpenGLWidget в подходящее время.
Совместное использование контекста
Когда несколько QOpenGLWidgets добавляются как дочерние элементы к одному виджету верхнего уровня, их контексты будут совмещать ресурсы. Это не относится к экземплярам QOpenGLWidget, которые принадлежат разным окнам.
Это означает, что все QOpenGLWidgets в одном окне могут обращаться к общим ресурсам друг друга, таким как текстуры, и нет необходимости в дополнительном «глобальном» контексте совместно использования.
Чтобы настроить совместное использование между экземплярами QOpenGLWidget, принадлежащими разным окнам, установите атрибут приложения Qt::AA_ShareOpenGLContexts до создания QApplication. Это вызовет совместное использование между всеми экземплярами QOpenGLWidget без дополнительных шагов.
Также возможно создание дополнительных экземпляров QOpenGLContext, которые совмещают ресурсы, такие как текстуры, с контекстом QOpenGLWidget. Просто передайте указатель, возвращаемый из context(), в QOpenGLContext::setShareContext() перед вызовом QOpenGLContext::create(). Полученный контекст также может быть использован в другом потоке, что позволяет создавать текстуры в потоке и асинхронно загружать их.
Обратите внимание, что QOpenGLWidget ожидает стандартной реализации совместного использования ресурсов в отношении базовых графических драйверов. Например, некоторые драйверы, особенно на мобильных и встроенных платформах, имеют проблемы с настройкой совместного использования между существующим контекстом и другими, созданными позже. Некоторые другие драйверы могут вести себя непредсказуемо при попытке использования общих ресурсов между разными потоками.
Инициализация и очистка ресурсов
Контекст OpenGL, связанный с QOpenGLWidget, гарантированно будет текущим всякий раз, когда вызываются initializeGL() и paintGL(). Не пытайтесь создавать ресурсы OpenGL до вызова initializeGL(). Например, попытка компиляции шейдеров, инициализации объектов буферов вершин или загрузки данных текстур завершится ошибкой при выполнении в конструкторе подкласса. Эти операции необходимо отложить до initializeGL(). Некоторые вспомогательные классы Qt для OpenGL, такие как QOpenGLBuffer или QOpenGLVertexArrayObject, имеют аналогичное отложенное поведение: они могут быть созданы без контекста, но вся инициализация откладывается до вызова create() или аналогичного. Это означает, что они могут быть использованы как обычные (не указатель) члены-переменные в подклассе QOpenGLWidget, но функция create() или аналогичная может быть вызвана только из initializeGL(). Однако имейте в виду, что не все классы разработаны таким образом. При возникновении сомнений сделайте переменную-член указателем и создайте/удалите экземпляр динамически в initializeGL() и деструкторе соответственно.
Освобождение ресурсов также требует, чтобы контекст был текущим. Поэтому деструкторы, выполняющие такую очистку, должны вызвать makeCurrent() перед уничтожением любых ресурсов OpenGL или обёрток. Избегайте отложенного удаления с помощью deleteLater() или механизма наследования QObject. Нет гарантии, что правильный контекст будет текущим в момент фактического уничтожения экземпляра.
Типичный подкласс, следовательно, часто будет выглядеть следующим образом, когда дело доходит до инициализации и уничтожения ресурсов:
class MyGLWidget : public QOpenGLWidget
{
...
private:
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vbo;
QOpenGLShaderProgram *m_program;
QOpenGLShader *m_shader;
QOpenGLTexture *m_texture;
};
MyGLWidget::MyGLWidget()
: m_program(0), m_shader(0), m_texture(0)
{
// No OpenGL resource initialization is done here.
}
MyGLWidget::~MyGLWidget()
{
// Make sure the context is current and then explicitly
// destroy all underlying OpenGL resources.
makeCurrent();
delete m_texture;
delete m_shader;
delete m_program;
m_vbo.destroy();
m_vao.destroy();
doneCurrent();
}
void MyGLWidget::initializeGL()
{
m_vao.create();
if (m_vao.isCreated())
m_vao.bind();
m_vbo.create();
m_vbo.bind();
m_vbo.allocate(...);
m_texture = new QOpenGLTexture(QImage(...));
m_shader = new QOpenGLShader(...);
m_program = new QOpenGLShaderProgram(...);
...
} Это, естественно, не единственное возможное решение. Альтернативой является использование сигнала aboutToBeDestroyed() объекта QOpenGLContext. Подключив слот с помощью прямой связи к этому сигналу, можно выполнить очистку всякий раз, когда будет высвобожден базовый системный дескриптор контекста или весь экземпляр QOpenGLContext. Следующий фрагмент кода в принципе эквивалентен предыдущему:
void MyGLWidget::initializeGL()
{
// context() and QOpenGLContext::currentContext() are equivalent when called from initializeGL or paintGL.
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &MyGLWidget::cleanup);
}
void MyGLWidget::cleanup()
{
makeCurrent();
delete m_texture;
m_texture = 0;
...
doneCurrent();
} Примечание: Для виджетов, которые многократно меняют связанное с ними окно верхнего уровня в течение своего жизненного цикла, необходим комбинированный подход. Всякий раз, когда виджет или его родительский элемент пересоздаются так, что окно верхнего уровня становится другим, связанный с виджетом контекст уничтожается, а новый создается. После этого вызывается initializeGL(), где все ресурсы OpenGL должны быть повторно инициализированы. По этой причине единственный вариант для правильной очистки — подключение к сигналу контекста aboutToBeDestroyed(). Обратите внимание, что контекст, о котором идет речь, может быть не текущим, когда сигнал генерируется. Поэтому рекомендуется вызвать makeCurrent() в подключенном слоте. Кроме того, те же шаги по очистке должны выполняться из деструктора производного класса, так как слот, подключенный к сигналу, не будет вызван при уничтожении виджета.
Примечание: Когда Qt::AA_ShareOpenGLContexts установлен, контекст виджета никогда не изменяется, даже при пересоздании, поскольку текстура, связанная с виджетом, гарантированно доступна также из контекста нового окна верхнего уровня.
Правильная очистка особенно важна из-за совместного использования контекста. Несмотря на то, что связанный с каждым QOpenGLWidget контекст уничтожается вместе с QOpenGLWidget, общие ресурсы в этом контексте, такие как текстуры, останутся действительными до тех пор, пока не будет уничтожено окно верхнего уровня, в котором находился QOpenGLWidget. Кроме того, такие параметры, как Qt::AA_ShareOpenGLContexts, и некоторые модули Qt могут вызвать более широкий охват совместного использования контекстов, потенциально сохраняя соответствующие ресурсы на протяжении всего жизненного цикла приложения. Поэтому самым безопасным и надежным способом всегда является явная очистка всех ресурсов и обёртки ресурсов, используемых в QOpenGLWidget.
Ограничения
Размещение других виджетов под QOpenGLWidget и установка прозрачности QOpenGLWidget не приведет к ожидаемым результатам: виджеты под ним не будут видны. Это связано с тем, что на практике QOpenGLWidget отрисовывается перед всеми другими обычными виджетами, не связанными с OpenGL, и поэтому решения, основанные на просвечивании, невозможны. Другие типы макетов, такие как размещение виджетов поверх QOpenGLWidget, будут работать как ожидается.
В случае крайней необходимости это ограничение можно обойти, установив атрибут Qt::WA_AlwaysStackOnTop для QOpenGLWidget. Однако имейте в виду, что это нарушает порядок стекирования, например, другие виджеты не смогут находиться поверх QOpenGLWidget, поэтому его следует использовать только в ситуациях, когда требуется полупрозрачный QOpenGLWidget с другими виджетами, видимыми под ним.
Обратите внимание, что это не относится к случаям, когда других виджетов нет под ним и предполагается полупрозрачное окно. В этом случае достаточно традиционного подхода к установке Qt::WA_TranslucentBackground на окне верхнего уровня. Обратите внимание, что если прозрачные области требуются только в QOpenGLWidget, то Qt::WA_NoSystemBackground необходимо восстановить в false после включения Qt::WA_TranslucentBackground. Кроме того, может потребоваться запросить альфа-канал для контекста QOpenGLWidget через setFormat(), в зависимости от системы.
QOpenGLWidget поддерживает несколько вариантов поведения обновления, аналогично QOpenGLWindow. В режиме сохранения содержимое, отрисованное в предыдущем вызове paintGL(), доступно в следующем, что позволяет выполнять инкрементную отрисовку. В режиме без сохранения содержимое теряется, и реализации paintGL() должны перерисовывать всё содержимое в представлении.
До Qt 5.5 поведение QOpenGLWidget по умолчанию заключалось в сохранении отрисованного содержимого между вызовами paintGL(). Начиная с Qt 5.5, поведение по умолчанию — без сохранения, так как это обеспечивает лучшую производительность, и большинству приложений не нужно предыдущее содержимое. Это также соответствует семантике OpenGL-базированного QWindow и соответствует поведению по умолчанию QOpenGLWindow, при котором цветовой и вспомогательные буферы делают недействительными для каждого кадра. Для восстановления поведения сохранения вызовите setUpdateBehavior() с PartialUpdate.
Альтернативы
Добавление QOpenGLWidget в окно включает OpenGL-композитинг для всего окна. В некоторых особых случаях это может быть нежелательно, и желательно поведение старого QGLWidget со своим отдельным, родным дочерним окном. Приложения для настольных ПК, понимающие ограничения этого подхода (например, при перекрытиях, прозрачности, прокрутке и областях MDI), могут использовать QOpenGLWindow с QWidget::createWindowContainer(). Это современная альтернатива QGLWidget и быстрее, чем QOpenGLWidget, из-за отсутствия дополнительного шага композитинга. Настоятельно рекомендуется ограничить использование этого подхода случаями, когда нет другого выбора. Обратите внимание, что этот вариант не подходит для большинства встроенных и мобильных платформ, и известно, что он имеет проблемы на определенных настольных платформах (например, macOS). Стабильное и кроссплатформенное решение — всегда QOpenGLWidget.
OpenGL — торговая марка Silicon Graphics, Inc. в США и других странах.
См. также QOpenGLFunctions, QOpenGLWindow, Qt::AA_ShareOpenGLContexts и UpdateBehavior.
Документация по типам элементов-члена
[since 5.5] Перечисление QOpenGLWidget::UpdateBehavior
Это перечисление описывает семантику обновления QOpenGLWidget.
| Константа | Значение | Описание |
|---|---|---|
QOpenGLWidget::NoPartialUpdate |
0 |
QOpenGLWidget отбросит содержимое цветового буфера и вспомогательных буферов после отрисовки QOpenGLWidget на экране. Это такое же поведение, которого можно ожидать, вызывая QOpenGLContext::swapBuffers с аргументом по умолчанию OpenGL-активированным QWindow. NoPartialUpdate может иметь некоторые преимущества в производительности на определённых аппаратных платформах, распространённых в мобильных и встраиваемых устройствах, когда в качестве целевой поверхности рендеринга используется объект framebuffer. Объект framebuffer делает недействительным между кадрами с glDiscardFramebufferEXT, если он поддерживается, или с glClear. Более подробную информацию см. в документации EXT_discard_framebuffer: https://www.khronos.org/registry/gles/extensions/EXT/EXT_discard_framebuffer.txt |
QOpenGLWidget::PartialUpdate |
1 |
Цветовой буфер и вспомогательные буферы объектов framebuffer не делают недействительными между кадрами. |
Это перечисление было введено или изменено в Qt 5.5.
См. также updateBehavior() и setUpdateBehavior().
Документация по функциям-членам
QOpenGLWidget::QOpenGLWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
Конструирует виджет, который является дочерним элементом parent, с флагами виджета, установленными на f.
[signal] void QOpenGLWidget::aboutToCompose()
Этот сигнал генерируется, когда окно верхнего уровня виджета начинает композицию текстур его QOpenGLWidget дочерних элементов и других виджетов.
[signal] void QOpenGLWidget::aboutToResize()
Этот сигнал генерируется, когда размер виджета изменяется, и, следовательно, объект framebuffer будет пересоздан.
[signal] void QOpenGLWidget::frameSwapped()
Этот сигнал генерируется после того, как окно верхнего уровня виджета завершит композицию и вернётся из потенциально блокирующего вызова QOpenGLContext::swapBuffers().
[signal] void QOpenGLWidget::resized()
Этот сигнал генерируется сразу после пересоздания объекта framebuffer из-за изменения размера виджета.
[virtual] QOpenGLWidget::~QOpenGLWidget()
Уничтожает экземпляр QOpenGLWidget, освобождая его ресурсы.
Контекст QOpenGLWidget делается текущим в деструкторе, что позволяет безопасно уничтожить любой дочерний объект, которому может потребоваться освободить ресурсы OpenGL, принадлежащие контексту, предоставленному этим виджетом.
Предупреждение: если у вас есть объекты, обёртывающие ресурсы OpenGL (например, QOpenGLBuffer, QOpenGLShaderProgram и т.д.) в качестве членов подкласса OpenGLWidget, вам, возможно, потребуется добавить вызов makeCurrent() в деструкторе этого подкласса тоже. Из-за правил уничтожения объектов C++, эти объекты будут уничтожены *до* вызова этой функции (но после того, как выполнился деструктор подкласса), поэтому приведение контекста OpenGL к текущему в этой функции происходит слишком поздно для их безопасного удаления.
См. также makeCurrent.
QOpenGLContext *QOpenGLWidget::context() const
Возвращает QOpenGLContext, используемый этим виджетом, или 0 если он ещё не инициализирован.
Примечание: Контекст и объект framebuffer, используемые виджетом, изменяются при пересоздании виджета через setParent().
См. также QOpenGLContext::setShareContext() и defaultFramebufferObject().
GLuint QOpenGLWidget::defaultFramebufferObject() const
Возвращает идентификатор объекта framebuffer или 0 если он ещё не инициализирован.
Примечание: Объект framebuffer принадлежит контексту, возвращённому context(), и может быть недоступен из других контекстов.
Примечание: Контекст и объект буфера кадра, используемые виджетом, изменяются при переродите виджета с помощью setParent(). Кроме того, объект буфера кадра изменяется при каждом изменении размера.
См. также context().
void QOpenGLWidget::doneCurrent()
Освобождает контекст.
В большинстве случаев вызывать эту функцию не нужно, так как виджет позаботится о правильном привязке и освобождении контекста при вызове paintGL().
[override virtual protected] bool QOpenGLWidget::event(QEvent *e)
Переопределяет: QWidget::event(QEvent *event).
QSurfaceFormat QOpenGLWidget::format() const
Возвращает формат контекста и поверхности, используемый этим виджетом и его родительским окном.
После создания виджета и его родительского окна, изменения размера и отображения, эта функция вернёт фактический формат контекста. Это может отличаться от запрошенного формата, если платформа не может выполнить запрос. Также возможно получить буферы цвета большего размера, чем запрошенные.
Когда окно виджета и связанные с ним OpenGL ресурсы ещё не инициализированы, возвращаемое значение — это формат, заданный с помощью setFormat().
См. также setFormat() и context().
QImage QOpenGLWidget::grabFramebuffer()
Отрисовывает и возвращает 32-битное RGB изображение буфера кадра.
Примечание: Это потенциально дорогостоящая операция, так как она опирается на glReadPixels() для считывания пикселей. Это может быть медленным и блокировать конвейер GPU.
[virtual protected] void QOpenGLWidget::initializeGL()
Эта виртуальная функция вызывается один раз перед первым вызовом paintGL() или resizeGL(). Переопределите её в подклассе.
Эта функция должна инициализировать необходимые ресурсы и состояние OpenGL.
Нет необходимости вызывать makeCurrent(), так как это уже сделано при вызове этой функции. Однако обратите внимание, что буфер кадра ещё недоступен на этом этапе, поэтому избегайте вызовов отрисовки отсюда. Отложите такие вызовы до paintGL() вместо этого.
См. также paintGL() и resizeGL().
bool QOpenGLWidget::isValid() const
Возвращает true, если виджет и OpenGL ресурсы, такие как контекст, были успешно инициализированы. Обратите внимание, что возвращаемое значение всегда ложно до тех пор, пока виджет не отображен.
void QOpenGLWidget::makeCurrent()
Готовит к отрисовке OpenGL-контента для этого виджета, делая соответствующий контекст текущим и связывая объект буфера кадра в этом контексте.
В большинстве случаев вызывать эту функцию не нужно, так как она вызывается автоматически перед вызовом paintGL().
См. также context(), paintGL() и doneCurrent().
[override virtual protected] int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
Переопределяет: QWidget::metric(QPaintDevice::PaintDeviceMetric m) const.
[override virtual protected] QPaintEngine *QOpenGLWidget::paintEngine() const
Переопределяет: QWidget::paintEngine() const.
[override virtual protected] void QOpenGLWidget::paintEvent(QPaintEvent *e)
Переопределяет: QWidget::paintEvent(QPaintEvent *event).
Обрабатывает события отрисовки.
Вызов QWidget::update() приведёт к отправке события отрисовки e, а значит, к вызову этой функции. (Примечание: это асинхронно и произойдёт в какой-то момент после возвращения из update()). Затем эта функция после некоторой подготовки вызовет виртуальную функцию paintGL() для обновления содержимого буфера кадра QOpenGLWidget. Затем окно виджета верхнего уровня будет компоновать текстуру буфера кадра с остальной частью окна.
[virtual protected] void QOpenGLWidget::paintGL()
Эта виртуальная функция вызывается всякий раз, когда виджет необходимо перерисовать. Переопределите её в подклассе.
Нет необходимости вызывать makeCurrent(), так как это уже сделано при вызове этой функции.
Перед вызовом этой функции контекст и буфер кадра привязаны, а порт просмотра настроен с помощью вызова glViewport(). Никакие другие состояния не устанавливаются и никакое очищение или отрисовка не выполняются фреймворком.
См. также initializeGL() и resizeGL().
[override virtual protected] QPaintDevice *QOpenGLWidget::redirected(QPoint *p) const
[override virtual protected] void QOpenGLWidget::resizeEvent(QResizeEvent *e)
Переопределяет: QWidget::resizeEvent(QResizeEvent *event).
Обрабатывает события изменения размера, передаваемые в параметре события e. Вызывает виртуальную функцию resizeGL().
Примечание: Избегайте переопределения этой функции в производных классах. Если это невозможно, убедитесь, что реализация QOpenGLWidget также вызывается. В противном случае связанный с ним объект буфера кадра и связанные с ним ресурсы не будут правильно изменены по размеру, что приведёт к неправильной отрисовке.
[virtual protected] void QOpenGLWidget::resizeGL(int w, int h)
Эта виртуальная функция вызывается всякий раз, когда виджет был изменён по размеру. Переопределите её в подклассе. Новый размер передаётся в w и h.
Нет необходимости вызывать makeCurrent(), так как это уже сделано при вызове этой функции. Кроме того, буфер кадра также привязан.
См. также initializeGL() и paintGL().
void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
Устанавливает запрашиваемый формат поверхности format.
Если формат не задан явно с помощью этой функции, будет использован формат, возвращаемый QSurfaceFormat::defaultFormat(). Это означает, что при наличии нескольких виджетов OpenGL, отдельные вызовы этой функции могут быть заменены одним вызовом QSurfaceFormat::setDefaultFormat() перед созданием первого виджета.
Примечание: Запрос буфера альфа с помощью этой функции не даст ожидаемого результата, если целью является сделать другие виджеты видимыми снизу. Вместо этого используйте Qt::WA_AlwaysStackOnTop для включения полупрозрачных экземпляров QOpenGLWidget с другими виджетами, видимыми снизу. Однако имейте в виду, что это нарушает порядок стекирования, поэтому другие виджеты больше не смогут расположиться сверху QOpenGLWidget.
См. также format(), Qt::WA_AlwaysStackOnTop и QSurfaceFormat::setDefaultFormat().
[since 5.10] void QOpenGLWidget::setTextureFormat(GLenum texFormat)
Устанавливает пользовательский внутренний формат текстуры texFormat.
При работе с sRGB буферами кадра необходимо указать формат, например, GL_SRGB8_ALPHA8. Это можно сделать, вызвав эту функцию.
Примечание: Эта функция не оказывает никакого влияния, если она вызвана после того, как виджет уже отображён и, следовательно, выполнил инициализацию.
Примечание: Эта функция, как правило, должна использоваться в сочетании с вызовом QSurfaceFormat::setDefaultFormat(), который устанавливает цветовое пространство в QSurfaceFormat::sRGBColorSpace.
Эта функция была введена в Qt 5.10.
См. также textureFormat().
[since 5.5] void QOpenGLWidget::setUpdateBehavior(QOpenGLWidget::UpdateBehavior updateBehavior)
Устанавливает поведение обновления этого виджета в updateBehavior.
Эта функция была введена в Qt 5.5.
См. также updateBehavior().
[since 5.10] GLenum QOpenGLWidget::textureFormat() const
Возвращает активный внутренний формат текстуры, если виджет уже инициализирован, запрошенный формат, если он был установлен, но виджет ещё не отображён, или nullptr если setTextureFormat() не вызывался и виджет ещё не отображён.
Эта функция была введена в Qt 5.10.
См. также setTextureFormat().
[since 5.5] QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
Возвращает поведение обновления виджета.
Эта функция была введена в Qt 5.5.
См. также setUpdateBehavior().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qopenglwidget.html