Я проектирую простую структуру графического интерфейса с нуля как проект, используя OpenGL и ничего более внешнего, и мне нужен совет о том, как я могу реализовать взаимодействие с пользователем.
В основном, у меня есть базовый класс GUIItem
от которого наследуются все элементы. Это дает каждому элементу некоторые основные переменные, такие как положение, вектор для дочерних элементов, а также некоторые базовые функции для перемещения мыши и щелчка.
Все элементы настроены, как указано выше, с соответствующими переменными-членами.
То, с чем я борюсь, это как правильно реализовать взаимодействие с пользователем. В моем оконном менеджере я бы создал новый экземпляр элемента, скажем, GUIButton
и назовите это button1
, При возникновении щелчка оконный менеджер будет перебирать свой список элементов и любые дочерние элементы, которые они могут иметь, вычисляя прямоугольную область вокруг объекта на основе его координат, высоты и ширины, а затем запускать любую функцию «по нажатию», связанную с указанный пункт, как изменить значение textlabel1
,
Во-первых, есть ли лучший способ сделать этот расчет? Это будет работать для прямоугольных элементов, но сферические объекты и другие будут иметь гораздо большую ошибочную область, по которой можно щелкнуть. В идеале я бы проверял пиксели, но я не представляю, как это будет достигнуто. Я слышал об этом, но никогда не использовал GLUT (мой проект позволяет использовать его только для обработки взаимодействия мыши и клавиатуры). Предоставляет ли GLUT что-нибудь для помощи в этом случае?
Моя главная проблема связана с обработкой того, что может произойти, когда действительно происходит событие «при нажатии». В данный момент GUIButton
например, имеет встроенную функцию «при нажатии», поэтому, насколько я вижу, мне нужно сделать что-то вроде виртуальной функции, то есть каждая новая кнопка, которую я создал, должна иметь свой собственный класс перезаписать функцию «по нажатию», и каждый экземпляр кнопки будет экземпляром уникального класса, который просто наследуется от GUIButton
, Это кажется мне грязным, так как я понятия не имею, где я буду хранить все эти классы, и, похоже, много лишнего кода. Буду ли я создавать файл button1.cpp и button1.h?
Любой совет по этому поводу будет приветствоваться, так как я новичок в C ++, OpenGL, и я впервые знакомлюсь с программированием GUI, и не так много, чтобы продолжить, когда существующая среда GUI является обычным выбором.
если ты хочешь что-то тупо просто и быстро тогда вы могли бы:
ID/index/pointer
вместо цветапредварительно визуализировать этот буфер
Просто визуализируйте каждый из ваших визуальных компонентов, но вместо этого раскрасьте / текстурируйте, просто заполните ID/index/pointer
визуализированного компонента. Не забудьте очистить это с некоторыми NULL
сначала … После этого у вас должна быть маска ваших компонентов. Вам нужно сделать это только один раз …
На событиях мыши
вы просто конвертируете координаты мыши в пространство экрана тени и выбираете значение. Если это NULL
Затем вы нажали или что-нибудь в пустой области. Если он содержит ID
вместо этого обновите или вызовите обратные вызовы для компонента ID
, если у вас есть список всех компонентов, то ID может быть индексом списка, в противном случае используйте его фактический указатель или кодируйте в стиле (component_type, component_index)
, Как видите, это довольно быстро O(1)
выбор элемента независимо от того, сколько у вас компонентов … Разрешение теневого экрана может отличаться от фактического экрана (для сохранения памяти).
Это обеспечивает идеальную точность выбора мыши с точностью до пикселя независимо от формы ваших компонентов без необходимости во вложенных циклах поиска компонентов.
[Заметки]
Как я это сделал, вот несколько советов:
создать window
учебный класс содержащий конфигурацию ваших компонентов для одного экрана. Программы обычно имеют больше экранов с различным набором компонентов и выполняют динамические экраны снова и снова только потому, что вы переключаете страницы / экраны экрана.
использовать отдельный список компонентов по одному списку для каждого типа компонента.
Создайте IDE редактор для ваших окон см тащить, тянуть & падение примера в C ++ это может пригодиться для этого. добавлять get,set
функции контролируются string/enum or flag
легко получить / изменить свойства, чтобы сделать возможным инспектор объектов. Также вот как выглядит моя IDE:
Окно сохраняется из IDE напрямую как код C ++, который я могу просто скопировать в свое приложение. Это приведенный выше пример без ручки (забыл ее сохранить):
//---------------------------------------------------------------------------
// OpenGL VCL window beg: win
win.grid.allocate(0);
win.grid.num=0;
win.scale.allocate(0);
win.scale.num=0;
win.button.allocate(0);
win.button.num=0;
win.knob.allocate(0);
win.knob.num=0;
win.scrollbar.allocate(3);
win.scrollbar.num=3;
win.scrollbar[0].x0=200.0;
win.scrollbar[0].y0=19.0;
win.scrollbar[0].xs=256.0;
win.scrollbar[0].ys=16.0;
win.scrollbar[0].fxs=8.0;
win.scrollbar[0].fys=19.0;
win.scrollbar[0].name="_vcl_scrollbar0";
win.scrollbar[0].hint="";
win.scrollbar[0].min=0.000;
win.scrollbar[0].max=1.000;
win.scrollbar[0].pos=0.000;
win.scrollbar[0].dpos=0.100;
win.scrollbar[0].horizontal=1;
win.scrollbar[0].style=0;
win.scrollbar[0].resize();
win.scrollbar[1].x0=200.0;
win.scrollbar[1].y0=45.0;
win.scrollbar[1].xs=256.0;
win.scrollbar[1].ys=16.0;
win.scrollbar[1].fxs=8.0;
win.scrollbar[1].fys=19.0;
win.scrollbar[1].name="_vcl_scrollbar1";
win.scrollbar[1].hint="";
win.scrollbar[1].min=0.000;
win.scrollbar[1].max=1.000;
win.scrollbar[1].pos=0.000;
win.scrollbar[1].dpos=0.100;
win.scrollbar[1].horizontal=1;
win.scrollbar[1].style=0;
win.scrollbar[1].resize();
win.scrollbar[2].x0=200.0;
win.scrollbar[2].y0=70.0;
win.scrollbar[2].xs=256.0;
win.scrollbar[2].ys=16.0;
win.scrollbar[2].fxs=8.0;
win.scrollbar[2].fys=19.0;
win.scrollbar[2].name="_vcl_scrollbar2";
win.scrollbar[2].hint="";
win.scrollbar[2].min=0.000;
win.scrollbar[2].max=1.000;
win.scrollbar[2].pos=0.000;
win.scrollbar[2].dpos=0.100;
win.scrollbar[2].horizontal=1;
win.scrollbar[2].style=0;
win.scrollbar[2].resize();
win.interpbox.allocate(0);
win.interpbox.num=0;
win.dblist.allocate(0);
win.dblist.num=0;
// OpenGL VCL window end: win
//---------------------------------------------------------------------------
Посмотрите на изображения здесь отображение данных в реальном времени на осциллографе для некоторых идей (у меня это работает как для GDI, так и для OpenGL)
Лучше использовать пиксельные единицы вместо OpenGL <-1,+1>
единицы экрана для лучшего визуального качества и комфорта редактирования.
Других решений пока нет …