Задача: использование нескольких окон из GLUT с различными функциями
рисования.
Пример: с использованием C++, freeglut.
Языки:
EN,
RU
Создающиеся окна имеют рамку, стандартную для имеющейся операционной системы.
На изображениях представлен вид окон программы, запускаемой на Ubuntu
16.04LTS.
Дополнение: GLUT мощный и простой в использовании инструмент для создания окон и
работы с пользователем через них. Благодаря именно удобству использования, не
стоит требовать от него операций уровня операционной системы. Таких как,
например, скрытие заголовка (рамки) созданного окна, поддержание окна поверх
остальных окон.
Проинициализируем последовательно два окна, каждый из которых свяжем с собственной функцией отрисовки.
Задача, в том виде как она сформулирована, может считаться решённой. Но что,
если нам потребуется иметь большее число окон, с более сложной логикой отрисовки
и обработкой событий? Давайте попробуем инкапсулировать работу с окном для
будущей масштабируемости приложений, использующих GLUT.
Вернёмся на этап создания одного окна и реализуем класс, обеспечивающий тот же
функционал.
С точки зрения пользователя класса, достаточно выбрать заголовок создаваемого окна, не заботясь о внутренней реализации.
Относительно класса, мы просто оборачиваем существующие функции в соответствующие методы. Для регистрации методов как обработчиков событий, необходима статическая реализация.
Необходимо использовать созданный класс для управления несколькими окнами. Из-за того, что функция отрисовки статична, она одинакова для каждого из объектов класса. Для решения проблемы, объявим функцию display абстрактной, что позволит реализовать функционал в классах-наследниках. А в качестве обработки события отрисовки, вызовем перерисовку всех имеющихся окон.
Обратим внимание, что функция display_all будет зарегестрирована на каждое окно. То есть при необходимости перерисовки одного из окон, будут перерисованы все.
Ранее, у нас были различные функции для различных окон и мы не заботились о том, чтобы идентифицировать окно. Сейчас такая задача возникает. Если развернуть цикл вызовов display внутри display_all, от каждой из реализации класса, получится, что актуальной будет лишь последняя итерация (произойдёт очередная очистка методом glClear(..) и обновление содержимого окна методом glutSwapBuffers()). Для разрешения конфликта, используем функцию glutSetWindow(..), которая устанавливает текущее окно, для которого применяются последующие инструкции.
Для создания нового окна, можно объявить класс-наследник с собственной реализацией метода display.
В качестве дополнения, рассмотрим задачу разделения единственного окна на
области, в каждой из которых собственные функции отрисовки и прочие callback
функции.
GLUT имеет функцию glutCreateSubWindow(..), которая создает окно в пространстве
родительского, существующего окна.
Дополнение: дочернее окно будет иметь постоянный размер, не смотря на изменение размеров родительского окна. При необходимости, можно самостоятельно организовать изменение размеров, используя относительные координаты, пробрасывая события от родительских окон дочерним.