LINUX.ORG.RU

[GUI]Как быстро определить какая кнопка на экране нажата

 


0

3

В силу некоторых причин пишу свой GUI.

В мою функцию передаётся что сделали (нажали или отжали), код кнопки и где нажали (x и y).

В окне есть мои кнопочки. Сейчас сделано так: перебираются по очереди эти кнопочки — сравнивается x и y с координатами каждой и как только окажется что x и y внутри кнопки — вызывается функция-обработчик для этой кнопки.

Меня терзают смутные сомнения по поводу эффективности такого метода поиска кнопки которую нажали. Может быть есть более эффективный метод?

★★★

Последнее исправление: LinuxUser (всего исправлений: 1)

сравнивается x и y с координатами каждой

Запихни координаты каждой в b-tree хотя бы.

x3al ★★★★★
()

самопальный тулкит, чтоле?

anonymous
()

А зачем? Не в смысле зачем писать свой гуй (хотя конечно это вызывает...), зачем БЫСТРО определять какая кнопка нажата? Для гуев это обычно совершенно некритично, компутер все равно быстрее человека.

Я такую задачу решал для коллекции массивов. Можно выкрутиться через std::map - будет наверное в разы быстрее, но геморроя...

Ну или хранить двумерный массив размером в окно, для каждой точки держать информацию о том к какой кнопке она относится. Но опять таки, зачем?

AIv ★★★★★
()
Ответ на: комментарий от zJes

В чем хоть гуй то?

Гуй на OpenGL. События от устройств ввода берутся из Xlib. Пишу по причине отсутствия гуёвых библиотек для OpenGL на чистом C.

Запихни координаты каждой в b-tree хотя бы.

x3al, спасибо.

Ещё идеи?

LinuxUser ★★★
() автор топика
Ответ на: комментарий от x3al

Запихни координаты каждой в b-tree хотя бы.

Там же диапазон нужен, причем двумерный. От бинарного дерева тут толку чуть, надо городить октет, но его еще набить надо...

AIv ★★★★★
()
Ответ на: комментарий от LinuxUser

Ещё идеи?

Оставить как есть, простой перебор. То, что Вы пытаетесь сделать, называется «преждевременная оптимизация». Что, уже начали поступать жалобы на тормознутость гуя, и на тестах выяснилось что основной затык в переборе?

AIv ★★★★★
()
Ответ на: комментарий от AIv

«преждевременная оптимизация»

Да, согласен, это она.

Ну а если, скажем, прога должна реагировать не только на нажатия, но и на движения мышки. Для каждого движения придётся искать кнопку. Тот метод что используется сейчас для этого явно не эффективен.

А вот двумерный массив размером с окно — хорошая идея. для окна 1280x1024 он будет занимать всего 5 мегабайт (для 64-битных систем — 10).

LinuxUser ★★★
() автор топика
Ответ на: комментарий от LinuxUser

А Вы попробуйте обрабатывать движения мыши обычным перебором... проблемы надо решать по мере их поступления. Я не спец по гуям, но сильно сомневаюсь что бы Вы когда нить уперлись в перебор. Если это тока монстр будет типа ворда со 100500 кнопками, и то тормозить оно будет ИМНО уже по другим причинам;-)

Елементарная же оценка - берем типовое число кнопок, оцениваем время перебора, сравниваем со временем между запросами...

AIv ★★★★★
()
Ответ на: комментарий от LinuxUser

Гуй на OpenGL. События от устройств ввода берутся из Xlib. Пишу по причине отсутствия гуёвых библиотек для OpenGL на чистом C.

А чем не устраивают биндинги OpenGL к питону и прочим гадам? Вроде ж их есть... ИМНО гуйню на чистом С писать последнее дело. Да еще и свою... куда то далеко Вы ушли от unix-way ;-)

AIv ★★★★★
()
Ответ на: комментарий от LinuxUser

Гуй на OpenGL

Пользуйтесь буфером выбора (select buffer) - пусть openGL за вас считает.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от AIv

Если надо реагировать не только на нажатия, я на 'mouse over', при наличии 100500 кнопок можно и встрять, особенно если мышом быстро возить :)

invy ★★★★★
()
Ответ на: комментарий от LinuxUser

> всего 5 мегабайт
nooooooooooooooooooooooooooooooow!

trex6 ★★★★★
()
Ответ на: комментарий от anonymous

причём тут unix-way?

При том, что уже есть туева хуча бол-мен православных средств для разработки гуя, в т.ч. и таких которые дружатся с опенГЛ. Писать свой низкоуровневый туева-хуча-первый вариант, тока потому что он будет на чистом С... это как бы ни разу ни юникс-вэй, так обычно мелкософт делает. И то нечасто...

Мнение дилетанта;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

да, я в курсе насчёт первого, но причём тут unix-way? Если парнишу не устраивают существующие инструменты и ему проще написать новый, чем дорабатывать имеющиеся, он пишет новый. Если для него важны скорость работы и переносимость, он пишет на C. Твоё мнение же ошибочно и тебе следует от него избавиться как можно скорее.

anonymous
()
Ответ на: комментарий от anonymous

Если парнишу не устраивают существующие инструменты и ему проще написать новый, чем дорабатывать имеющиеся, он пишет новый.

Гы... из критики существующих инструментов пока было озвучено «они не на чистом С». Боязнь юзать несколько ЯП в проекте обычно характерна для мелкомягких хомячкофф. Не существует универсальных инструментов, одинаково хороших для всех задач, и С тут не исключение.

Если для него важны скорость работы и переносимость, он пишет на C.

Скорость работы ГУЯ? Чего вы там курите?

Твоё мнение же ошибочно и тебе следует от него избавиться как можно скорее.

А твое мнение насчет моего мнения меня вообще не интересует;-)

AIv ★★★★★
()
Ответ на: комментарий от anonymous

Если для него важны скорость работы и переносимость, он пишет на C.

Про переносимость ГУЯ написанного на С, можешь рассказывать своей бабушке. А вот питонячий гуй действительно взлетает как есть что под *никс, что под виндой. За одноклассников питона не скажу, но думаю примерно так же...

AIv ★★★★★
()

А много ли у тебя кнопок? Если меньше десяти-шестнадцати, то я бы не парился по этому поводу. Дешевле пройтись тупым перебором, чем устраивать сложные хитроумные «оптимизации».

Если же больше, скажем условно, тридцати кнопок, то можно приспособить k-d четверья, что я один раз и сделал для похожей задачи в одном редакторе диаграмм. Только у меня были не кнопки, а элементы диаграммы. Постоянно возникала задача найти пересечение множества элементов с заданной прямоугольной областью.

dave ★★★★★
()

Делай снимок экрана и распознавай :) (Тут когда-то мелькал подобный рецепт обнаружения захода абонента в асечку) А если серьезно, событийная модель в твоем гуе какая-то используется? Сигналы-слоты, может быть? Если нет, то... мб перепроектировать гуй или... преодолеть тягу к велосипедостроению? :)

slackwarrior ★★★★★
()

Если бы ты хотел трахаться с деревьями, ты бы ведь не стал использовать плоскую модель гуя? Возня мышкой не генерит больше ~50 событий в секунду. Если кнопок меньше 1000, делай перебором, запоминай последнюю, и в следующий раз начинай с нее. При map/unmap и т.п. обнуляешь ее.

arturpub ★★
()
Ответ на: комментарий от dave

А много ли у тебя кнопок? Если меньше десяти-шестнадцати, то я бы не парился по этому поводу. Дешевле пройтись тупым перебором, чем устраивать сложные хитроумные «оптимизации».

В каком месте тут «хитроумные оптимизации»? Это фича OpenGL. Она в приведённом мной примере подробно разобрана.

Кроме того «тупой перебор» не заработает, если ТС захочет вдруг сделать интерфейс трёхмерным (кнопки в пространстве там - такая задача в игрушках может понадобиться), то он пожалеет, что делал «тупо».

invy ★★★★★
()
Ответ на: комментарий от invy

Пожалеет, что потратил уйму времени на такой сложный алгоритм, как «тупой перебор» ))

arturpub ★★
()
Ответ на: комментарий от invy

В каком месте тут «хитроумные оптимизации»? Это фича OpenGL. Она в приведённом мной примере подробно разобрана.

Если фича, то это здорово. Ничего против не имею :)

dave ★★★★★
()

отсортить копки по координате начала/конца и искать бинпоиском?

Tanger ★★★★★
()
Ответ на: комментарий от invy

GL_SELECT по идее подошёл бы, но во-первых вроде как её в OpenGL ES нету (http://en.wikipedia.org/wiki/OpenGL_ES#OpenGL_ES_1.0). А во-вторых метод с двумерным массивом размером с экран будет работать чуточку быстрее.

Так что пока остановлюсь на нём.

Трёхмерный интерфейс точно не понадобится, то что пишу — двумерное.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от LinuxUser

метод с двумерным массивом размером с экран будет работать чуточку быстрее.

Мдя... уже жалею, что предложил.

В головах программистов существует огромное число мифов об оптимизации. Так вот, вариант с 2Д массивом в ряде случаев может оказаться и медленнее перебора. И самое главное - не надо пытаться оптимизировать что то, пока не будет четко понятно, что оно нуждается в оптимизации. А если уж оптимизировать, то надо обязательно тестить - как было до и как стало после. Причем в зависимости от условий, результаты могут быть совершенно различными...

AIv ★★★★★
()
Ответ на: комментарий от LinuxUser

Тогда уж хотя бы разбей все на квадраты ~16х16 и в квадратах храни списки попавших в них виджетов. Тупой расход памяти точно тупее тупого перебора.

arturpub ★★
()
Ответ на: комментарий от AIv

Мдя... уже жалею, что предложил.

Если тебе станет легче — до твоего предложения в голове промелькнула мысль про массив размером с окно, но я откинул её сразу, почему-то подумав, что массив будет очень большим.

вариант с 2Д массивом в ряде случаев может оказаться и медленнее перебора

Например? В момент обращения к элементу нужно всего лишь вычислить смещение обратится по указанному смещению от начала массива. Это не более 5 ассемблерных инструкций. По смещению будет указатель на кнопку или NULL. Проверяем на NULL и переходим. Мы у цели.

не надо пытаться оптимизировать что то, пока не будет четко понятно, что оно нуждается в оптимизации

Хорошо, сначала создам 100 кнопок, протестирую. Если будет подтормаживать — первым делом реализую с 2Д массивом и протестирую с ним.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от arturpub

расход памяти точно тупее тупого перебора.

Я предпочитаю расход памяти тормозам. Тем более что 10 мегабайт это ерунда.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от LinuxUser

А мы посмотрим на твою плавную отрисовку, когда 8 из них провалятся в своп.

arturpub ★★
()
Ответ на: комментарий от LinuxUser

Например?

Про кэширование что нить слышали? А про латентность доступа к памяти?

Хорошо, сначала создам 100 кнопок, протестирую.

О_О... е-мае... 1000 кнопок. А кто на них будет давить?;-)

Если будет подтормаживать

То надо брать хороший профилировщик, и смотреть где именно подтормаживает.

AIv ★★★★★
()
Ответ на: комментарий от LinuxUser

Я предпочитаю расход памяти тормозам.

Если на С-ях будут тормоза из-за за перебора, даже с тысячей кнопок, с меня шоколадка!;-)

AIv ★★★★★
()
Ответ на: комментарий от arturpub

Этим надо переболеть.

Да волнуюсь, как бы не помер;-)

AIv ★★★★★
()

Если кнопок не много, сойдет и перебор.

Для определения «что под курсором» можно в момент нажатия мыши рендерить кнопки кодом цвета, полученным из адреса указателя на кнопку. А потом читать значение цвета пикселя в точке. Только нужно в этот момент отключать блендинг, если он используется.

XyAH
()
Ответ на: комментарий от AIv

Я, когда проверял, насколько быстро работает selection buffer, сделал пробную картиночку с несколькими миллионами пересекающихся объектов. Тормозов не было вообще.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от LinuxUser

Для сборки нужен xxd, xcf2png и convert. Собирать так: make или make ver=debug или make ver=release arch=ia32 и т.п. В файлике settings.ini можно прописать настройки, например сейчас там для linux прописан компилятор colorgcc.

LinuxUser ★★★
() автор топика
Ответ на: комментарий от dave

задача найти пересечение множества элементов с заданной прямоугольной областью

что является классической задачей из вычислительной геометрии. По идее именно так и должны быть решены подобные вопросы в гуях.

Да, опен соурс - это классно. А вот попробуй, быстренько так найти в исходниках, каким способом это решено, скажем, в gtk, qt, wxwidgets. Не детали реализации, а каркас.

gag ★★★★★
()

Что-то тут жесть какую-то понаписали.

Посмотри на принципы интерфейса в андроиде, они максимально простые и максимально эффективные. Дерево из элементов одного базового класса (View) с несколькими методами для раскладки, рисования и обработки событий.

note173 ★★★★★
()
Ответ на: комментарий от gag

Насколько я заню, Qt и прочие используют родную систему событий ОС. Т.е. WinAPI, XWindows и прочее. Хотя у Qt еще есть собственный QWS, вот в его код было бы полезно заглянуть.

trex6 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.