Библиотеки для кнопки

grabbly
Offline
Зарегистрирован: 14.04.2020

Библиотеки для тактовой кнопки. sbutton - простой антидребезг. hbutton - однозначное определение нажатие, двойной клик, длительное удержание. 

Здравствуйте форумчане.

За время изучения платформы ардуино и программирования  в частности, сайт очень часто помогал мне статьями, вот и настало мое время сделать что-то для сообщества. Я написал две простых библиотеки работы с кнопками.

Первая удобна в случае, когда в программе от кнопки нужно получать только корректные нажатия, обрабатывает одиночные нажатия(sbutton).

Вторая библиотека применяется когда необходимо корректно обработать нажатие, двойной клик или длительное удержание (hbutton).

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

Библиотека обработки антидребезга кнопки sbutton.  https://github.com/Huzenkov/sbutton.git

Библиотека обработки нажатия, двойного клика, длительного удержания кнопки hbutton. https://github.com/Huzenkov/hbutton.git

Тестовый скетч sbutton

#include <sbutton.h>
#define BUTTON_1_PIN 7              // первая кнопка на пине 7
#define BUTTON_2_PIN 8              // вторая кнопка на пине 8

byte ledState;  // просто переменная счетчик

Button button1(BUTTON_1_PIN, 300);  //создаем объект button1 класса Button с параметрами. Button button1(byte pin(физический пин), int debounceDelay(время фильтрации дребезга))
Button button2(BUTTON_2_PIN, 300);  //создаем объект button1 класса Button с параметрами. Button button1(byte pin(физический пин), int debounceDelay(время фильтрации дребезга))
void setup()
  {
    Serial.begin(9600);
  }
void loop() {
button1.scanState();    // сканируем состояние первой кнопки
button2.scanState();    // сканируем состояние второй кнопки (по отдельности для каждой новой кнопки. Пока так, я только учусь :D )
if (button1.push == true) ledState++; //если кнопка 1 нажата, прибавляем счетчик
if (button2.push == true) ledState--; //если кнопка 2 нажата, убавляем счетчик
Serial.println(ledState);
}

При зажатой кнопке значение с TRUE на FALSE меняется с указанной периодичностью, таким образом удобно использовать в счетчике, например, при нажатии значение увеличивается на 1, при удержании увеличивается на 1 каждые ~300мс, таким образом, за три секунды значение увеличится на 10. Комфортная работа возможна при значении параметра debounceDelay от 150 до 300, далее уже по вкусу. 

 

Далее пример из второй библиотеки

#include <hbutton.h>
Button b1(7, 150, 2000); // создаем объект b1 класса Button с параметрами:(физический пин кнопки, период двойного клика(реком. 100-300), период удержания кнопки(реком. 500-2000))

void setup () {Serial.begin(9600);}

void loop() {
int i;                      //переменная счетчика
b1.scanState();             //сканируем состояние кнопки, для каждой отдельной кнопки необходимо это делать отдельно
if (b1.bPush == 1) i++;     //если нажали кнопку - прибавляем счетчик
if (b1.bDouble == 1) i--;   //если двойной клик по кнопке - убавляем счетчик
if (b1.bHold == 1) i = 0;   //если удерживаем кнопку - обнуляем счетчик
Serial.println(i);          //выводим в монитор порта
}

В примере нажатие на кнопку - прибавляет счетчик, двойной клик - убавляет. Нажатие и удержание кнопки сбрасывает счетчик в ноль. 

С уважением, пользуйтесь на здоровье. 

b707
Онлайн
Зарегистрирован: 26.05.2017

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

Более подробно не вникал, сейчас может еще кто  обо... обсудит :)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Удали, не позорься.  Покуда в твоём коде будет 

if(millis() < _lastHold + _delayHold && _trigHold == 0)

 рано тебе еще библиотеки писать

 

b707
Онлайн
Зарегистрирован: 26.05.2017

DetSimen пишет:

Удали, не позорься.

 

удалил :) совсем мне 612-й мозг запудрил :)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

b707 пишет:

DetSimen пишет:

Удали, не позорься.

 

удалил :) совсем мне 612-й мозг запудрил :)

О_О  Я это ТС-у писал

grabbly
Offline
Зарегистрирован: 14.04.2020

Рано или поздно, это вопрос этики и компетентного роста. 

Я не оправдываюсь, тем что это моя первая библиотека или что я не программист по образованию. 

Также я признаю что код не вылизан до идеала, но он работает. По этому я благодарен за обратную связь.  Ведь для того и нужны форумы, для обмена опытом, именно по этому я и создал эту тему, преследуя цели популяризации и качественного роста ДиАйВая среди населения, и моего (диАйВай библиотеки) в том числе. 

Согласен с замечанием 

if(_trigHold == 0) _lastHold = millis();

      if(millis() < _lastHold + _delayHold && _trigHold == 0)
        {
          bHold = 0;
          _trigHold = 1;
        }

Эту конструкцию можно переписать так:

if(_trigHold == 0)
  { 
    _lastHold = millis();
    bHold = 0;
    _trigHold = 1;      
   }

 

b707
Онлайн
Зарегистрирован: 26.05.2017

DetSimen пишет:

О_О  Я это ТС-у писал

по-моему, это называется индукция :) прочитал твое замечание ТС-у. понял. что и сам написал чушь - удалил :)))

grabbly
Offline
Зарегистрирован: 14.04.2020

Согласен. Добавлю в описании. Изначально преследовалась цель простой библиотеки, которая закрыла бы ежедневные мои задачи, по этому там жесткая привязка к "гуглящимся" картинкам подключения... Единственное, что добавил подтяжку внутреннюю. 

Попробую написать "и так и так чтобы работало"

b707
Онлайн
Зарегистрирован: 26.05.2017

grabbly пишет:

Я не оправдываюсь, тем что это моя первая библиотека или что я не программист по образованию.

желание написать "библиотеку для кнопок" и "поделится ей с народом" - это уже как бы звоночек. Нехороший :) - потому что первое никак не согласуется со вторым. 

Ну а по существу твоих ошибок тебе ДидСимен расскажет, замечание насчет миллис ты, похоже, нифига не понял

 

grabbly
Offline
Зарегистрирован: 14.04.2020

А в чем собственно "нехорошесть" желания безвозмездно делиться? раньше я просто писал обработчик в отдельной вкладке каждого скетча, и не писал библиотеку по причине своей лени. Сейчас мне понадобилось кнопку однозначно распознавать че с ней делается, опять же по причине своей лени решил сделать библиотеку, потому что теперь этот код сложнее копировать. т.е. вопрос "когда" я напишу её не стоял изначально, все упиралось в то, когда лень копировать станет сильнее лени писать библиотеку. 

А по сабжу, беглый поиск гугла, "велосипед" клаупуция, библиотека гайвера проблему не решили :)

b707
Онлайн
Зарегистрирован: 26.05.2017

grabbly пишет:

А в чем собственно "нехорошесть" желания безвозмездно делиться?

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

grabbly
Offline
Зарегистрирован: 14.04.2020

b707 пишет:

 замечание насчет миллис ты, похоже, нифига не понял

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

 

 

grabbly
Offline
Зарегистрирован: 14.04.2020

b707 пишет:

Что твоя поделка - гениальна :)

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

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

grabbly пишет:

b707 пишет:

 замечание насчет миллис ты, похоже, нифига не понял

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

У меня больше нет вопросов к обвиняемому. 

b707
Онлайн
Зарегистрирован: 26.05.2017

grabbly пишет:

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

между условиями

if(millis() < _lastHold + _delayHold )

и

if(millis() - _lastHold > _delayHold )

- принципиальная разница. первое даст неверный результат при переполнении миллис, второе будет работать.

Использование первой строчки в ответственных программах - яркий признак новичка, потому Дед и написал , что вам еще рано в  это соваться :)

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

b707 пишет:

между условиями

if(millis() < _lastHold + _delayHold )

и

if(millis() - _lastHold > _delayHold )

- принципиальная разница. первое даст неверный результат при переполнении миллис, второе будет работать.

Использование первой строчки в ответственных программах - яркий признак новичка, потому Дед и написал , что вам еще рано в  это соваться :)

Причём, ТС, в твоём случае это пофиг, канеш, не думаю, что программа твоего уровня проработает 50 суток ни разу не зависнув, но ведь ты потом это и дальше потащишь, не разобравшись.  А программы надо сразу писать надёжно.  Поэтому, как я и сказал, рано ты библиотеки в народ понёс, пока они выглядят как твой ник (или тщательно спланированная диверсия). 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

кстати, покажи как у тебя антидребезг сделан, а то  "debounceDelay"  в описании есть, в коде нету.  Да и в коде я чота нихрена похожего на антидребезг не нашол, мошт и не разобрался, канеш.  

ЗЫ  Я пока только за hbutton говорю.

grabbly
Offline
Зарегистрирован: 14.04.2020

Согласен про переполнения таймера. 

Как лучше в данном случае организовать данное сравнение? 

Сделать просто таймер, не привязанный к миллис? который каждый вызов просто обнуляться будет?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

набей  в поиске "переполнение millis" и читай до просветления

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Господа-это короновирус так действует или C2H5OH+H2O? Вы бредите.

grabbly
Offline
Зарегистрирован: 14.04.2020

Мда уж. Чем наше комьюнити отличается от западного, так это тем, что там - помогают или пытаются помочь, у нас сначала об..срут, а потом может быть что то подскажут. Много тем, где новичек говорит я скачал библиотеки, скрестил - не работает, помогите, в ответ ему иди полгода читай  и учись, и вообще куда ты лезешь раз не знаешь. В другой же теме,человек говорит я подучился, что-то сделал, оно работает, но хочется чтобы все могли пользоваться, соответственно нужно понять проблемные места и найти способы решения, а в ответ - не делай этого, есть абстрактная куча тем или решений проблемы или библиотек. Абстрактная потому что конкретики никто не говорит, гугли до просветления. 

По теме антидребезга - функция возвращает TRUE при нажатии кнопки, далее указанное время delay не реагирует на нажатия, а по истечении времени возвращает FALSE и потом только повторно проверяет состояние кнопки  

b707
Онлайн
Зарегистрирован: 26.05.2017

mykaida пишет:

Господа-это короновирус так действует или C2H5OH+H2O? Вы бредите.

кто и где?

sadman41
Offline
Зарегистрирован: 19.10.2016

Поэтому на западе все жырные - получают сразу готовенькое, а у нас - спортивные.

И что, Вы во многих западных комьюнити участвовали? Там любой безумной теме рады и топикстартера на руках носят? 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Грабли, дорогой! Тебе уже три раза, русским по белому написали, что в сравнениях времени нужно использовать ВЫЧИТАНИЕ, а не сложение.

Вот так:

if (new_millis - old_millis > interval)  doSomething();

а не так:

if (new_millis > old_millis + interval)  doSomething();

=================

Потому что, в случае арифметики в дополнительном коде, которая применяется в любом компьютере, от "перемены мест слагаемых" много чего меняется. ;)))

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

b707 пишет:

кто и где?

Хрен с ним, что вы ТС не слышите - не положено ему. Вы даже дру-друга не воспринимаете. Счас попытаюсь сделать подборочку...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

grabbly пишет:

Согласен про переполнения таймера. 

Как лучше в данном случае организовать данное сравнение? 

Вам же b707 в посте #14 написал как - заменить сложение на вычитание.
Почему так - читайте ЗДЕСЬ.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Уважаемый, grabbly, а как Вы думаете, почему вот такой пример ни хрена не работает на Uno?

#include "sbutton.h"
#define BUTTON_1_PIN 2 

Button * pButton; 

int gdeKnopka(void) {
	String question(F("Where is your fucking button? (0-18):"));
	String confirm(F("Okay, button is on the pin: "));
	int result = -1;
	while (result < 0 || result > 18) {
		Serial.print(question);
		Serial.setTimeout(100500);
		result = Serial.parseInt();
	}
	Serial.print(confirm);
	Serial.println(result);
	return result;
}

void setup() {
	Serial.begin(57600);
	int pin = gdeKnopka();
	pButton = new Button(pin, 300); 
}

void loop() {
	static bool oldState = false;
	pButton->scanState();    // сканируем состояние первой кнопки
	if (pButton->push != oldState) {
		oldState = !oldState;
		Serial.println(oldState);
	}
}

Только не говорите, что "работает" или "должен работать" - я не поленился проверить в реале. Может и должен (я не знаю Ваших с ним кредитных отношений), но не работает, зараза :-)

grabbly
Offline
Зарегистрирован: 14.04.2020

я не на столько опытный программист, по этому для меня в Вашем коде много нового и непонятного. Однако я попробовал у себя и он тоже зараза не работает :-0. 

Я так понял там процедура поиска кнопки у Вас запущена? если опустить её и в строке 

	    pButton = new Button(pin, 300);

вместо pin однозначно указать номер пина, то все работает

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

grabbly пишет:

Я так понял там процедура поиска кнопки у Вас запущена? если опустить её и в строке 

	    pButton = new Button(pin, 300);

вместо pin однозначно указать номер пина, то все работает

Работает только потому, что оптимизатор нахрен выбрасывает из моей программы всё, связанное с запросом номера пина.

На самом деле, ошибка у Вас простая и детская, но я специально не стал её объяснять, а написал пример, показывающий её, чтобы Вы её на практике увидели, разобрались и впредь "на подкорке" так не делали. От чужих объяснений эффект не такой.

В том моём коде нет ничего волшебного. Для демонстрации проблемы подойдёт любой другой код, который немножко поработает с памятью. Например, вот такой - запустите и убедитесь, что тоже не работает.

include "sbutton.h"
#define BUTTON_1_PIN 2 

Button * pButton; 

void setup() {
	Serial.begin(57600);
	{
		String welocmeMessage(F("Прветствуем Вас на тесте библиотеки кнопки!"));
		Serial.println(welocmeMessage);
	}
	pButton = new Button(BUTTON_1_PIN, 300); 
}

void loop() {
	static bool oldState = false;
	pButton->scanState();    // сканируем состояние первой кнопки
	if (pButton->push != oldState) {
		oldState = !oldState;
		Serial.println(oldState);
	}
}

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

grabbly
Offline
Зарегистрирован: 14.04.2020

Уважаемый Евений. Я осознал ошибку с вычитанием, изучил материалы куда "носом ткнули" и переписал библиотеку так, чтобы было только сложение(реозиторий еще не обновил). Если ошибка не в этом, то честно признаюсь сложно понять мне ошибку, прошу подсказить, а лучше снова "ткнуть" в ссылку или направление с подсказкой, изучить детальнее вопрос. 

Немного оффтопа. Изначально я не преследовал цели показать "гениальность" своей библиотеки. У вас же на форуме в "курилке" вы, опытные люди участники этого прекрасного форума, говорите о том, что миссия форумчан помочь тем, кто хочет разобраться или научиться, в отличии от гайвер комьюнити, где "идиоты" и все разжевано для идиотов.  Именно по этому я рискнул выложить тут, свое "творение", зная что за любую мелочь будет критика. Ведь без критики нет развития. Я выложил, и уже получаю ценные советы (без сарказма), по тому что хочу развиваться. Имея опытных наставников гораздо быстрее можно научиться, чем изучать самому все с нуля. 

Большое спасибо за советы. С уважением.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

grabbly пишет:
ошибку с вычитанием, изучил материалы куда "носом ткнули" и переписал библиотеку так, чтобы было только сложение

Это описка (сложение с вычитание перепутано)? Или Вы всё напутали сделали неправильно даже там, где правильно было? Ещё раз прочитайте хотя бы первую часть и сравните с тем, сделали.

grabbly пишет:

прошу подсказить

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

А ошибка такая, что Вы будете долго смеяться и бить себя по лбу. У Вас там в классе есть свойство _lastDebounceTime. А вот теперь посмотрите на код и скажите, где, когда и при каких обстоятельствах эта переменная получает своё начальное значение? Чему она равна в самом начале, пока строка №15 ещё ни разу не выполнилась? .... оопс! А ведь нигде не получает! И чему она равна? А тому, что была в памяти до того, как в ней (памяти) расположилась Ваша кнопка.

В Ваших примерах, когда класс объявляется как глобальная переменная - там 0, потому, что глобальные переменные всегда нули, если им явно чего-то не назначить. А вот в моих примерах, когда я кнопку размещаю после того, как уже что-то поделал в памяти - там оказывается некое случайное значение. И Ваш класс не начнёт работать до тех пор пока значение миллис не дочапает до этой случайной величины и не превысит её. А потом, вдруг, ни с того ни с сего, начнёт работать нормально. Может через час, а может и через месяц - как повезёт :-)

В общем, если у Вас есть свойства, значения которых Вам не пофиг, всегда присваивайте им разумные значения в конструкторах. Просто вставьте в конструктор присваивание нуля этой _lastDebounceTime и мои примеры тут же радостно заработают :-)

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Я одним глазом смотрел исходник: там, вроде, ещё одна лепёха наложена в дизайне - с копипастом блинк-без-дилей 

grabbly
Offline
Зарегистрирован: 14.04.2020

Да уж. Ведь я же еще думал об этом. Вернее, не совсем об этом но около того. о том присвоить значение начальное или нет. 

Работа с памятью для меня это пока новая тема. Подскажите пожалуйста, в Вашем примере строки:

String welocmeMessage(F("Прветствуем Вас на тесте библиотеки кнопки!"));
10
        Serial.println(welocmeMessage);

 это и есть тот фактор, который записывает в память? ну то есть забивает её условно "мусором"? Если да, то я понял примерно как это влияет. 

Еще мне очень интересны новые (не отрытые для меня) возможности языка программирования. Подскажите Апожалуйста, в Вашем примере "String welocmeMessage(F" F - это F-строки из питона?

И по предыдущему примеру, каким образом алгоритм "ищет" кнопку? оочень интересно :)

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:

Я одним глазом смотрел исходник: там, вроде, ещё одна лепёха наложена в дизайне - с копипастом блинк-без-дилей 

Ну, там много к чему можно придраться, не всё сразу, пусть ТС сначала выложит исправленную версия.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

grabbly пишет:

 это и есть тот фактор, который записывает в память? ну то есть забивает её условно "мусором"?

Ну, да, там копируется эта самая строка в память

grabbly пишет:

F - это F-строки из питона?

F - это константы в памяти программ. Вы знаете, что здесь память программ и память данных - это совершенно разные памяти?

grabbly пишет:
каким образом алгоритм "ищет" кнопку? оочень интересно :)

Никак не ищет. Спрашивает у юзера ввести номер пина. Какой тот введёт на таком и "считает, что кнопка находится".

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

grabbly пишет:

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

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

b707
Онлайн
Зарегистрирован: 26.05.2017

andriano пишет:

Перед двойным нажатием класс должен возвращать одиночное.

Совершенно необзательно. Задача различения двойного и одиночного нажатия. так же как короткого и длинного - отлично решается раздельно.

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

b707 пишет:

andriano пишет:

Перед двойным нажатием класс должен возвращать одиночное.

Совершенно необзательно. Задача различения двойного и одиночного нажатия. так же как короткого и длинного - отлично решается раздельно.

 

Согласен с тобой! Это религия Клапауция и, как оказалось Андриано. ;)) Я считаю, что высокоуровневый драйвер должен работать по завершению воздействия пользователя и вернуть одиночное нажатие, если не было двойного. Да - это запаздывание. ;))) и чё?! Даже одиночное нажатие отдавать по отпусканию. ИМХО это эргономичнее... ну мне - точно! Нажал и держишь, отпустишь - ...банёт! ;))))

Если в изделии я использую такую схему, что мне нужно оба варианта  - придется подбирать удобные длительности, но отдавать в обработку нажатие  -  НУЖНО по отпусканию. И даже с интервалом, чтобы убедиться, что нет повторного нажатия. Иначе все это программист будет обрабатывать сам, тогда нахера ему драйвер кнопки?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Я сделал себе Press, LongPress и AutoRepeat.  DoubleClick как то ни разу еще не понадобился

nik182
Offline
Зарегистрирован: 04.05.2015

Дед. И мои кнопки именно так и работают. Ни разу не подводили. Двойной клик кнопкой, а не мышкой это извращение. По любому мышка с системой успевает на первый клик взять фокус, тогда двойной клик имеет смысл. У нас наличие двух кликов, без выдачи первого дает задержку на анализ был двойной или нет. Если уж очень хочется, то пусть сама программа решает два быстрых одиночных это двойной или нет. Точно не дело обработчика кнопок двойной клик выдавать.       

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

wdrakula пишет:

Я считаю, что высокоуровневый драйвер должен работать по завершению воздействия пользователя и вернуть одиночное нажатие, если не было двойного. Да - это запаздывание. ;))) и чё?! Даже одиночное нажатие отдавать по отпусканию. ИМХО это эргономичнее... ну мне - точно! Нажал и держишь, отпустишь - ...банёт! ;))))

Если в изделии я использую такую схему, что мне нужно оба варианта  - придется подбирать удобные длительности, но отдавать в обработку нажатие  -  НУЖНО по отпусканию. И даже с интервалом, чтобы убедиться, что нет повторного нажатия. Иначе все это программист будет обрабатывать сам, тогда нахера ему драйвер кнопки?

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

 

PS. Хотел бы я посмотреть на рояль, который выдает звук по отпусканию клавиши.

nik182
Offline
Зарегистрирован: 04.05.2015

Посмотрел в событиях дельфи на разные элементы - для клавиш есть события DOWN PRESS UP, причем UP DOWN приходят скан коды с состоянием alt shift ctrl клавиш, а  PRESS только скан код. Двойной клик есть только для мыши. Так что чувствую - двойной клик это народное творчество, вызванное отсутствием привычной мыши.  

b707
Онлайн
Зарегистрирован: 26.05.2017

andriano пишет:

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

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

А дальше мы должны согласится с тем, что все это относительно - нажатия "довольно быстрые" и задержка "довольно небольшая". Говорить об таком расплывчатом предмете в столь категоричных выражениях. как "теоретически невозможно" - довольно смешно.

Теоретически невозможно сделать задержку незаметной? - Для кого? Для чемпиона по ловле пуль в полете с  отточенной реакцией или для расслабленной дамы бальзаковского возраста? :)

 

Green
Offline
Зарегистрирован: 01.10.2015

DetSimen пишет:

Я сделал себе Press, LongPress и AutoRepeat.  DoubleClick как то ни разу еще не понадобился

Совсем недавно делал человеку и двойное, и четвертное, и короткое с длинным...) Авто само-собой.
Просто кнопка одна, а хочется многого.)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

b707 пишет:

А дальше мы должны согласится с тем, что все это относительно - нажатия "довольно быстрые" и задержка "довольно небольшая". Говорить об таком расплывчатом предмете в столь категоричных выражениях. как "теоретически невозможно" - довольно смешно.

Не смешнее, чем утверждать, что 2*2=4.

Цитата:

Теоретически невозможно сделать задержку незаметной? - Для кого? Для чемпиона по ловле пуль в полете с  отточенной реакцией или для расслабленной дамы бальзаковского возраста? :)

Для здорового человека или человека, здоровье которого находится в пределах нормы.

Различные биологические и физиологические параметры человека известны с хорошей точностью и (для здорового человека) не имеют слишком большого разброса. Например, длина бедренной кости всегда больше, чем длина фаланги пальца. Вне зависимости от того, чемпион это по ловле пуль или дама бальзаковского возраста. Если Вам это кажется смешным, ну что ж, бывает...

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Вот тут реализовал, и двойное и тройное и 254рное и длинное нажатие.
https://github.com/kakmyc-github/kakmyc_btn

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

andriano пишет:

PS. Хотел бы я посмотреть на рояль, который выдает звук по отпусканию клавиши.

Сережа! Прости, но я долго изучал свой столетний Беккер, потом синтезатор... И ни у одного не обнаружил ни даблклика ни лонгпресса. ;))))

Уважая твое занудство, переформулирую: если в проекте используются лонгпресс и/или даблклик, то драйвер клавиатуры должен отдавать событие в поток по завершению распознавания. Это, очевидно, влечет за собой задержку, заметную пользователю, которая является неизбежной платой за использование вышеназванных способов управления.

Так тебя устроит? ;))

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Кстати, да, любая библиотека от апостолов, будь то VCL или С#, перед DoubleClick всегда отдает сначала Click.  

b707
Онлайн
Зарегистрирован: 26.05.2017

DetSimen пишет:

Кстати, да, любая библиотека от апостолов, будь то VCL или С#, перед DoubleClick всегда отдает сначала Click.  

Дет, можно делать и так и так

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

b707 пишет:

DetSimen пишет:

Кстати, да, любая библиотека от апостолов, будь то VCL или С#, перед DoubleClick всегда отдает сначала Click.  

Дет, можно делать и так и так

мне реально Dblclick еще ни разу не понадобился :)  

Green
Offline
Зарегистрирован: 01.10.2015

"Кому и кобыла невеста"). Раз на раз не приходится - задачки разные бывают.