Страницы

Поиск по вопросам

Показаны сообщения с ярлыком события. Показать все сообщения
Показаны сообщения с ярлыком события. Показать все сообщения

понедельник, 13 апреля 2020 г.

Глобально отслеживать нажатия клавиш

#c_sharp #события

                    
Как глобально (не в рамках моего приложения) отследить нажимаемые комбинации клавиш
и, если, к примеру, комбинация CTRL+Q то активировать мое приложение? Перенести фокус
то бишь. Ну или на какой-либо элемент в нем. TextBox, например.
Спасибо!    


Ответы

Ответ 1



Посмотрите сюда: MSDN/Hooks overview. Учтите, что с такими трюками ваше приложение не получит Vista Logo (и более поздние сертификации): благопристойной программе не к чему шпионить за другими программами.

Ответ 2



Можно использовать такую подтехнологию WinAPI, как хуки( HOOKS ). Вообще, внедрение низкого уровня в C# - дело не клевое, так как .NET предоставляет массу высокоуровневых( и наиболее удобных, кстати говоря ) замещений WinAPI функциям. Но, если б я столкнулся с вашей задачей, вероятно, я бы решил ее именно так: HOOKPROC hkprcSysMsg; static HINSTANCE hinstDLL; static HHOOK hhookSysMsg; hinstDLL = LoadLibrary(TEXT("c:\\myapp\\MyHookDLL.dll")); hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "MyHookProc"); hhookSysMsg = SetWindowsHookEx( WH_KEYBOARD, hkprcSysMsg, hinstDLL, 0); Доки. При этом нажатия клавиш( и их комбинаций ) будет перехвачено глобально, на уровне системы, созданным вами хуком.

Ответ 3



EasyHook starts where Microsoft Detours ends. This project supports extending (hooking) unmanaged code (APIs) with pure managed ones, from within a fully managed environment like C# using Windows 2000 SP4 and later, including Windows XP x64, Windows Vista x64 and Windows Server 2008 x64. Also 32- and 64-bit kernel mode hooking is supported as well as an unmanaged user-mode API which allows you to hook targets without requiring a NET Framework on the customers PC. An experimental stealth injection hides hooking from most of the current AV software. http://easyhook.codeplex.com/

Ответ 4



Смотрите в сторону winapi, в шарпе нет возможности взаимодействовать напрямую с неподготовленными приложениями.

Android: long click - как заставить работать так же как и onclick

#события #android #view

                    
Проблема такая: понаписывал я своих вьюшек (иконки разные с текстом) и для них определил
onclick listener'ы, но тут проблема - если держать палец около секунды - то ничего
происходить не будет (очевидно сработал он самый long click). Можно конечно создать
onLongClickListener и вызывать в нём onClick, но тогда придётся каждой вьюшке назначить
его. Пробовал поставить в xml longClickable = false, но это ничего не дало. В общем
есть какое то нормальное решение, или придётся всё же обрабатывать onLongClick?    


Ответы

Ответ 1



Как по мне - так если пользователь сделал LongClick, значит он и хотел сделать лонг клик... Ну а если уж сильно надо - устанавливайте не OnClick, а OnTouch. И производите действия, скажем, по отпусканию вьюшки if (event.getAction() == MotionEvent.ACTION_UP) { //что нужно сделать по клику и лонг клику }

четверг, 2 апреля 2020 г.

JS keycode event

#javascript #html #события

                    
пытаюсь сделать html страницу с 


  event.keyCode


написал такой скрипт :

document.addEventListener('keydown', eventT, false);

    function eventT(event) {

        switch (event.keyCode) {
            case 38:
                console.log('вперед');
                break;
            case 40:
                console.log('назад');
                break;
            case 37:
                console.log('лево');
                break;
            case 39:
                console.log('право');
                break;
        }
    }


здесь все работает но как можно сделать движение нискосоком добавил такой скрипт
но не сработало 

if (event.keyCode == 37 && event.keyCode == 38) {
      console.log('найскосок NUM7')
} else
if (event.keyCode == 38 && event.keyCode == 39) {
      console.log('найскосок NUM9')
}


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





    Control Panel


Control Panel




Ответы

Ответ 1



Чтобы обрабатывать одновременное нажатие клавиш, надо нажатия записывать отдельно, а обрабатывать - отдельно. Попробуйте: const keys = []; document.onkeydown = e => { if(keys.indexOf(e.which)<0) keys.push(e.which); }; document.onkeyup = e => { keys.splice(keys.indexOf(e.which),1); }; setInterval(() => { keys.forEach(item => { switch(item){ case 87:case 38://W console.log('вперед'); break; case 68:case 39://D console.log('вправо'); break; case 65:case 37://A console.log('влево'); break; case 83:case 40://S console.log('назад'); break; default: //console.log(item); } }); // Наискосоки: if (keys.includes(37) && keys.includes(38)) { console.log('найскосок NUM7') } if (keys.includes(38) && keys.includes(39)) { console.log('найскосок NUM9') } if (keys.includes(39) && keys.includes(40)) { console.log('найскосок NUM3') } if (keys.includes(37) && keys.includes(40)) { console.log('найскосок NUM1') } }, 111);

Ответ 2



Что-то вы заморочились... Вот что-то похожее на более правильную реализацию: document.addEventListener('keydown', eventT, false); document.addEventListener('keyup', eventT, false); var arrowLeft=false; var arrowRigth = false; var arrowForward = false; var arrowBack = false; function eventT(event) { switch (event.keyCode) { case 38: arrowForward = !arrowForward; break; case 40: arrowBack = !arrowBack; break; case 37: arrowLeft = !arrowLeft; break; case 39: arrowRigth = !arrowRigth; break; } if(arrowRigth === true) { if(arrowForward === true) console.log('диагональ направо'); else console.log('право'); } else if(arrowLeft === true) { if(arrowForward === true) console.log('диагональ налево'); else console.log('лево'); } else if (arrowBack === true) { console.log('назад'); } else if(arrowForward === true) { console.log('вперед'); } }

среда, 4 марта 2020 г.

Изменение видимости элемента управления при обновлении свойства во ViewModel

#c_sharp #wpf #mvvm #события


К примеру, есть класс User. Есть ViewModel, в которой есть свойство LastUser. Свойство
периодически обновляется, генерируя NotifyPropertyChanged. На форме, поверх остальных
элементов, лежит невидимая панель. При обновлении свойства, необходимо показать панель
на несколько секунд, а затем спрятать. Как можно реализовать такое поведение? Есть
ли какой-нибудь EventTriger или DataTrigger?
    


Ответы

Ответ 1



Наиболее простым видится вынести в VM отдельное свойство для видимости панели и сделать метод, который запускать в сеттере LastUser: private async void ShowDetails() { IsVisiblePanel = true; await Task.Delay(TimeSpan.FromSeconds(1)); IsVisiblePanel = false; } Если не хотите делать это в VM - можно сделать во View, подписавшись вручную на PropertyChanged и делая тоже самое. Другой вариант, немного более замороченый - задействовать анимацию. Давайте будем действовать через прозрачность, у меня вот такая панель: Обратите внимание, у панели установлен DataContext, это важно, мы этим воспользуемся в дальнейшем. Давайте добавим в панель стиль и определим триггер, который будет скрывать панель когда она полностью прозрачна: Хорошо, а теперь управлять прозрачностью будет анимация, для этого запустим ее в EventTrigger Чтобы событие Binding.TargetUpdated возникало нужно его включить: DataContext="{Binding SelectedUser, NotifyOnTargetUpdated=True}" Теперь надо отключить панель в обычном режиме: Opacity="0" Ну и можно сделать анимацию посимпатичнее: Полный код панели, на всякий случай: PS: как раз вчера появилась статья на Хабре, в которой описаны возможные замены подписке на Binding.TargetUpdated. Получается всё можно сделать гораздо проще используя PropertyChangedTrigger из пакета Microsoft.Expression.Interactions

Локальные переменные в C#

#c_sharp #net #события #net_core


Есть следующий код на C# (.NET Core):

using System;

public class LambdaTest {
 public static void Main() {
  MyClass obj = new MyClass(32);

  UnsafeFunc(obj);
  obj.EventCall();
  Console.WriteLine();
  obj.EventCall();
 }

 public static void UnsafeFunc(MyClass obj) {
  int local = 10;

  obj.MyEvent += delegate {
   Console.WriteLine("Unsafe event");
   local++;
   Console.WriteLine("Variable from function: {0}", local);
  };
 }
}

public class MyClassArgs: EventArgs {
 public int Prop {
  get;
  set;
 }
 public MyClassArgs(int arg) {
  Prop = arg;
 }
}

public class MyClass {
 public int ObjProp {
  get;
  set;
 }
 public event EventHandler < MyClassArgs > MyEvent;

 public MyClass(int arg) {
  ObjProp = arg;
 }

 public void EventCall() {
  Console.WriteLine("Event call");
  MyEvent(this, new MyClassArgs(64));
 }
}


Метод UnsafeFunc(MyClass obj) назначает событию obj.MyEvent анонимный метод, который
изменяет и выводит локальную переменную local, объявленную в UnsafeFunc(MyClass obj).
При первом вызове события выводится значение local: 11. При втором вызове: 12. Но дело
в том, что local - локальная переменная метода, т.е. после выполнения метода выделенная
ей память вроде как должна очищаться. Тогда как объяснить, что обработчик события имеет
доступ к памяти, которая не должна существовать?
    


Ответы

Ответ 1



В языках программирования, в том числе и в C# есть такое понятие, как замыкание (closure). Смысл его в том, что если в каком-либо методе (назовём его Outer) объявлен анонимный метод (скажем Inner), использующий локальные переменные метода Outer, то ссылки на эти переменные будут живы до тех пор, пока Inner не завершит свою работу, даже если Outer уже завершился. В вашем случае метод UnsafeFunc уже отработал, но переменная local используется в обработчике события obj.MyEvent, и поэтому ссылка на неё сохраняется сборщиком мусора и после выхода из метода UnsafeFunc. Фактически в этом случае компилятор создаёт анонимный класс, в поля которого записываются захваченные переменные, а в анонимные методы, захватывающие эти переменные, он передаёт поля этого класса.

четверг, 27 февраля 2020 г.

Для чего нужны события и слушатели событий в Laravel на примере интернет-магазина?

#php #laravel #события


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


Ответы

Ответ 1



Если очень кратко и в двух словах, то: События и слушатели - это реализация паттерна Observer (статья на Википедии). Смысл в том, что у вас есть класс, в нем есть функции, вот вы хотите чтобы при вызове функций этого класса, вызывалась функция из другого класса - Вот собсна для чего и нужно. Функция из первого класса - будет событием (а точнее её вызов) Функция из второго класса - будет эвентом. Вы можете подумать - что мне мешает вызвать из одной функции другую, без этих слушателей. Но это будет не совсем правильно. Давайте на пальцах: Самый банальный пример: пусть у нас есть класс Users, у этого класса есть метод Auth (авторизация). Т.е. этот метод отвечает за логику-авторизации, и вызывается он только тогда когда происходит успешный вход (ввод логина и пароля). Теперь мы хотим, чтобы при входе, нам приходило письмо, что кто-то на нашем сайте вошел в систему. У нас, условно, есть класс Admin и у него метод SendMessage, который реализует данную логику. Самое первое что может прийти на ум, мы внутри метода Auth можем написать вызов класса Admin и его метода SendMessage. Но это будет не правильно, потому что в логике Auth внутри появляется сторонняя логика SendMessage (P.S. вот тут очень тонко, сложно для понимания, где логика считается раздельной, а где единой, но думаю вы понимаете). Правильней применить наш паттерн, и реализовать такую систему, где при вызове Auth вызовется наш SendMessage, не влияя на логику внутри Auth. Почему я сказал про тонкость? Дело в том, что где-то SendMessage будет являться частью логики Auth и тогда вызов внутри функции - это нормально, а где-то нет. Для визуального представления различий ситуации, давайте возьмем третий класс Logs с методом CreateLog - цель которого записывать(логировать) какие-то данные о нашем пользователе. Понятное дело что логировать надо не только Auth, а еще и вход, и выход, и регистрацию, и восстановление - а это все функции, если мы в каждой функции будем дописывать вызов нашего класса Logs и метода CreateLog - то как видите получится не совсем красиво, потом после отладки забудем где-то что-то удалить, или забудем где мы что писали, ходи по файликам и ищи. Собсна в такой ситуации с логированием, лучшего помощника, чем слушатель - не найти. Мы просто указываем какие функции нам нужны (события), и какую функцию вызывать. P.S. Это мое личное представление, может быть искажено с реальным представлением о паттерне Observer. При написании ответа ни один класс и метод не пострадал!

Ответ 2



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

Ответ 3



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

вторник, 25 февраля 2020 г.

Как ловить mouse events для группы SVG форм, как единого целого?

#raphael #javascript #события


Разбираюсь с Raphael и SVG. Есть графический объект, состоящий из нескольких: напр.,
окружность и внутри неё квадрат поменьше. 
Как ловить мышиные события  для этой пары, будто она одно целое?
Пробовал:

вешать onmouseover на бОльший (окружность): когда курсор заходит на квадрат, происходит
onmouseout окружности;
Встречал «решение» рисовать поверх группы почти прозрачную форму, покрывающую всю
активную область, и вешать слушателя на неё. Как-то «неаккуратненько»..
делать из них set, и цеплять Raphael'овский mouseover( handler) на этот сет: срабатывает
для каждого из объектов сета.
    


Ответы

Ответ 1



Предлагаю такой вариант - отлавливать mouseenter и mouseleave для группы элементов (). Raphael в "базовой поставке" это не поддерживает (set не является группой), но есть расширения которые позволяют добавить в него возможность работы с группами, вот например это https://github.com/rhyolight/Raphael-Plugins. А дальше просто - берём группу и вешаем на неё mouseenter - mouseleave. Вот что-то типа этого.

Ответ 2



В SVG можно делать группы: На них можно вешать евенты.

понедельник, 24 февраля 2020 г.

Сохранять базу данных каждую неделю

#mysql #phpmyadmin #события


Возможно ли используя events в phpMyAdmin создать event который позволит мне каждую
неделю сохранять базу данных в папку? 
    


Ответы

Ответ 1



Чтобы сохранять БД каждую неделю (каждый понедельник в 00:00), можно с помощью cron'a выполнять команду mysqldump В правило cron 00 00 * * 1 mysqldump -u{пользователь} -p{пароль} --all-databases > /{path_to_backups}/mysqldump_`$(date +\%Y\%m\%d\%H\%M\%S)`.sql

воскресенье, 16 февраля 2020 г.

Сохранять базу данных каждую неделю

#mysql #phpmyadmin #события


Возможно ли используя events в phpMyAdmin создать event который позволит мне каждую
неделю сохранять базу данных в папку? 
    


Ответы

Ответ 1



Чтобы сохранять БД каждую неделю (каждый понедельник в 00:00), можно с помощью cron'a выполнять команду mysqldump В правило cron 00 00 * * 1 mysqldump -u{пользователь} -p{пароль} --all-databases > /{path_to_backups}/mysqldump_`$(date +\%Y\%m\%d\%H\%M\%S)`.sql

пятница, 14 февраля 2020 г.

Передача данных в компоненты vue с помощью шины событий

#javascript #vuejs #события


Начал изучать vue столкнулся с проблемой,есть сестринские компоненты, их 4 штуки,
при выборе в селекте "Добавить новую организацию" (компонент CompanyRegistration) вся
информация введеная пользователем отправляется с помощью EventBus в методе add_company_to_hash.
Затем, название организации и форма добавляются в селект (компонент PersonalAccount,
в массив companies: []),при выборе организации ,вся информация должна передаваться
в компонент AllCompanies. Но вот тут и возникла проблема, что информация появляется
в компоненте (передаю я так же с помощью EventBus) , только когда выбираю второй! раз
в селекте строчку с компанией, почему так не могу понять. Прикрепляю код
https://codepen.io/anon/pen/aPjjKx
    


Ответы

Ответ 1



В твоей ситeации не нужно использовать EventВus. Достаточно нативной реактивность VueJs. Если у тебя есть объект с массивом организаций то тебе надо просто передать его во все места где он используется, и при обновлении он будет обновлённым во всех компонентах. Все шаблоны зависящие от этого массива будут автоматически перерисованы. В твоей ситуации лучше всего использовать Vuex для хранения общего состояния приложения. То есть организации надо поместить внутрь контейнера Vuex. Если без vuex просто помести его в рутовый компонент, к нему есть доступ у любого дочернего компонента через el.$root. При добавлении новой организации через organizations.push(...) всё шаблоны зависящие от этого массива будут перерисованы. Реактивность VueJS - документация. Использование реативности с массивами - документация.

Ответ 2



C мнением @Дмитрий Полянинб я согласен, однако это не ответ на вопрос. Твой код работает не так, как задумано по нескольким причинам: 1) Пересчет индекса компании (whichIndex) повешен на клик, а нужно на change. Если бы ты повесил обработчик как положено, то у тебя даже так не работало, как работает сейчас. Повезло) 2) Событие company_index эмитится еще до того, как будет создан компонент AllCompanies. Таким образом, в связи с вышесказанным, получается, что компонент AllCompanies не слышит события company_index, т.к. оно уже прошло. Потом, когда идет клик, индекс пересчитывается, генериться событие company_index - и все работает как ты и задумывал. Чтобы реализовать функционал, так как ты задумал - данные для AllCompanies необходимо передавать в props, через router

Стоит ли удалять событие с элемента, перед его удалением? [дубликат]

#javascript #html #события #javascript_events


        
             
                
                    
                        
                            На этот вопрос уже дан ответ здесь:
                            
                        
                    
                
                        
                            Корректное удаление узлов из DOM, у которых зарегистрированы
обработчики
                                
                                    (1 ответ)
                                
                        
                                Закрыт 11 месяцев назад.
            
                    
В одном видео слышал, что удаляя элемент в котором есть событие мы не удаляем сам
обработчик. Другими словами обработчик события продолжает работать, не смотря, что
элемента нет. Хотел бы получить подтверждение или опровержение этим словам. Спасибо!
    


Ответы

Ответ 1



удаляя элемент в котором есть событие мы не удаляем сам обработчик Да, при удалении элемента из dom-дерева все обработчики на нём остаются: document.querySelector('button').addEventListener('click', function (e) { e.target.remove(); setTimeout(function () { document.body.appendChild(e.target) }, 500); }); Ну как я понимаю событие может находиться в памяти, но не выполняться Выполняться тоже может: document.querySelector('button').addEventListener('click', function(e) { if (e.target.parentElement) { e.target.remove(); setTimeout(function() { e.target.click() }, 500); } else { document.body.appendChild(e.target); } }); Стоит ли удалять событие с элемента, перед его удалением? В большинстве случаев нет. Если на элемент нет других ссылок, то он всё равно будет собран сборщиком мусора вместе с обработчиком: ~function add() { var btn = document.createElement('button'); btn.textContent = "Click me"; btn.addEventListener('click', function (e) { btn.remove(); setTimeout(add, 500); }); document.body.appendChild(btn); }(); Как видно в профайлере, выживших объектов от кликов кроме последнего нет: Впрочем, в IE8 действительно была проблема с утечками в некоторых подобных случаях. Однако, если обработчик или элемент каким-то образом удерживается внешним кодом, то они будут сохранены до тех пор, пока это удерживание не исчезнет. Если есть какие-либо подписки на более долгоживущие объекты или события, то отписываться надо. Поэтому при использовании фреймвёрка, имеющего жизненный цикл компонента, рекомендуется при уничтожении компонента отписаться от всего, на что подписался руками.

четверг, 13 февраля 2020 г.

Отписывание от события

#c_sharp #net #события


Как то я решил был проверить что будет если из другого объекта подписать метод на
событие и потом присвоить переменной которая хранит ссылку на этот объект (из которого
брали метод) ссылку на null. К моему удивлению метод отработал и вывел все свойства
объекта, т.е. казалось бы, что после присвоения переменой ссылку на null, этот объект
должен был скушать сборщик мусора, но это не происходит следовательно объект ещё в
памяти, следовательно это очень плохо. Может есть уже готовой класс который автоматизирует
процесс отписывания?
    


Ответы

Ответ 1



Представим себе сценарий (пример того как не надо делать) : static class MyEventClass { public static event EventHandler someEvent; public static Delegate[] GetInvokationList() { return someEvent.GetInvocationList(); } } class MyClass { void someEvent_Handler(object sender, EventArgs e) { Console.WriteLine("hello"); } public MyClass() { MyEventClass.someEvent += someEvent_Handler; } } class Program { static void SomeMethod() { new MyClass(); } static void Main() { SomeMethod(); Delegate[] invokationList = MyEventClass.GetInvokationList(); for (int i = 0; i < invokationList.Length; i++) Console.WriteLine("Subscribed to event in {0} to handler {1}", invokationList[i].Target, invokationList[i].Method.Name); Console.ReadKey(); } } На экран получаем результат : Subscribed to event in Test.MyClass to handler someEvent_Handler Пояснение примера: В методе, где мы создаем объект этот объект должен был бы быть собранным сборщиком мусора по заверешнию метода, но мы подписали его метод к статическому ивенту, таким образом создали ссылку на него. Именно поэтому он не будет собран сборщиком мусора пока не закончится работа программы и сборщик мусора не соберет класс-объект в котором хранится ссылка на этот класс... Наш класс с событием был статическим, но то же происходило бы и с нестатическим классом. Если бы мы отписались от события вовремя - то такой проблемы бы не возникло. По возможности нужно избегать статические события вообще так как они ведут к "memory leak", но если уж придется - лучше класс наследовать от интерфейса IDisposable и в методе Dispose() отписываться от всех событий... Потом создавать экземпляр класса только используя директиву using, например : class MyClass : IDisposable { public void Dispose() { MyEventClass.someEvent1 -= someEvent_Handler1; MyEventClass.someEvent2 -= someEvent_Handler2; MyEventClass.someEvent3 -= someEvent_Handler3; } } И в программе : using(MyClass instance = new MyClass()) { // code here }

Ответ 2



Нужно не null присваивать, а использовать оператор -= my.MyEvent -= MyEventHandle();

воскресенье, 9 февраля 2020 г.

Подписка на событие и передача данных javascript

#javascript #события #javascript_events


Есть следующая задача. 

Даны класс Rabbit и класс Hunter. Rabbit может менять свои координаты x и y. Нужно
сделать так, чтобы при изменении координат охотники, созданные через конструктор вне
зависимости от их количества могли получать эти координаты, то есть были подписаны
на изменения в Rabbit. Код выглядит так:

'use strict';

class Rabbit {
  constructor(name) {
    this.name = name;
    this.x = 0;
    this.y = 0;
  }

  move() {
    this.x = (Math.random() * 100).toFixed(0);
    this.y = (Math.random() * 100).toFixed(0);
    console.log(this.x, this.y, this.name + ' ' + 'moved');
  }
}

class Hunter {
  constructor(name) {
    this.name = name;
  }
}

let rabbit = new Rabbit("Jonny");

rabbit.move();

let hunter1 = new Hunter("Ted");
let hunter2 = new Hunter("Billy");
let hunter3 = new Hunter("Greg");


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


Ответы

Ответ 1



class Rabbit { constructor(name) { this.name = name; this.x = 0; this.y = 0; this.handlersMove = []; } move() { this.x = (Math.random() * 100).toFixed(0); this.y = (Math.random() * 100).toFixed(0); console.log(this.x, this.y, this.name + ' ' + 'moved'); this.handlersMove.forEach(handler => handler(this)); } } class Hunter { constructor(name) { this.name = name; } onGameMoves(game) { console.log(`${this.name} sees that ${game.constructor.name} ${game.name} moved to (${game.x}, ${game.y}).`); } } let rabbit = new Rabbit("Jonny"); let hunter1 = new Hunter("Ted"); rabbit.handlersMove.push(hunter1.onGameMoves.bind(hunter1)); let hunter2 = new Hunter("Billy"); let hunter3 = new Hunter("Greg"); rabbit.handlersMove.push(hunter3.onGameMoves.bind(hunter3)); rabbit.move();

Ответ 2



Вы в своём вопросе на него же и ответили, воспользуйтесь шаблоном публикатор-подписчик. Все это выглядит примерно так: Где то в начале создаётся глобальный объект, назовём его broker который имеет 2 метода fire(отправить событие) и on(подписаться на событие) let broker = new Broker(); Затем все Hunter при создании подписываются на событие rabbit-moved broker.on("rabbit-moved", hunt) Тут я предположил что у охотника есть метод hunt(eventContext) в котором находится код логики охоты Когда произойдёт изменение координат какого либо Rabbit, то есть внутри вашего метода Rabbit.move() вы отправляете событие rabbit-moved broker.fire("rabbit-moved", eventContext) Вторым аргументом тут идёт объект, который будет содержать всю необходимую информацию об обработке этого события, в нашем случае это x и y наших кроликов. Брокер отправляет это сообщение всем подписчикам, topic - на картинке выше, это имя нашего события Сам брокер может отличаться тяжестью случая, самая простая версия выглядит примерно так class Broker { constructor() { // массивы подписчиков привязанные к каждому топику this.subscribers = {}; } // метод подписки on(topic, func) { if (!this.subscribers[topic]) this.subscribers[topic] = []; this.subscribers[topic].push(func); } // метод оповещения подписчиков fire(topic, data) { if (this.subscribers[topic]) this.subscribers[topic].forEach(l => l(data)); } } // создаётся глобальный объект, который связывает публикаторов и подписчиков let broker = new Broker(); class Rabbit { constructor(name) { this.name = name; this.x = 0; this.y = 0; this.handlersMove = []; } move() { this.x = (Math.random() * 100).toFixed(0); this.y = (Math.random() * 100).toFixed(0); // все кролики в момент перемещение публикуют событие broker.fire('rabbit-moved', this); } } class Hunter { constructor(name) { this.name = name; // все охотники подписаны на топик "rabbit-moved" // и когда приходит данное событие вызывается метод hunt broker.on('rabbit-moved', data => this.hunt(data)) } hunt(data) { console.log(`Hunter ${this.name}: I saw ${data.name} at ${data.x}:${data.y}`); } } // создаем 10 кроликов и 2 охотника let rabbits = Array(10).fill(0).map((e, i) => new Rabbit(`Rabbit ${i+1}`)); new Hunter("Tom") new Hunter("Max") function moveRandomRabbit() { // перемещение случайного кролика в случайную точку rabbits[Math.floor(Math.random() * rabbits.length)].move(); }

вторник, 28 января 2020 г.

Почему не работает встроенный JavaScript? [закрыт]

#javascript #html #события


        
             
                
                    
                        
                            Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он соответствовал тематике «Stack Overflow на русском».
                        
                        Закрыт 2 года назад.
                                                                                
           
                
        
Почему не работает этот код: 













    


Ответы

Ответ 1



img

Ответ 2



опечатка в свойстве нужно src а не scr

пятница, 24 января 2020 г.

stopPropagation для отмены изменения state в React

#javascript #reactjs #события


Есть функция, которая меняет состояние state, срабатывающая при клике на внутреннем
элементе:

toggleModal(typeModal){
  this.setState({
    [typeModal]: !this.state[typeModal]
  });
}


При клике вне элемента состояние state должно изменяться:

closeModal(typeModal){
  this.setState({
    [typeModal]: false
  });
}


closeModal вещаем на onClick у контейнера, например, Body. 

Вопрос: как запретить всплытие изменения состояния на элементе?
(return false; и event.stopPropagation() не работают)
    


Ответы

Ответ 1



1. Информация в вопросе слегка неполна и противоречива. Начнем, с того что согласно документации event.stopPropagation лучше применять с версии 0.14, до нее можно возвращать false у обработчика. И если Вы обрабатываете все с помощью реактовской системы событий, все должно работать. 2. Proof of concept: jsfiddle. Только с реактовскими событиями, обработчик клика висит на контейнере. 3. Значит остается достать хрустальный шар и угадать что не работает у вас. Вероятнее всего Вы мешаете реактовские события с браузерными. closeModal вещаем на onClick у контейнера, например, Body. Т.е. body это у вас не ректовский компонент а самое что ни на есть document.body с событием onclick. React использует свою систему синтетических событий. Физически, по крайней мере для всплывающих событий это один обработчик на document, дальше используется делегирование. Поэтому такой подход напрямую не сработает: к моменту когда событие до реактовского обработчика дойдет, оно уже всплыло. 4. Окей, как тогда мне ловить клик снаружи компонента? Можно сделать например так: jsfiddle. Смысл в том что пока компонент существует, на document висит наш обработчик клика. Срабатывание его при клике на сам компонент мы обрабатываем ручками в самом обработчике. Если у вас устаревшая версия реакта, (<0.14), то апи может быть чуть чуть другим, но смысл от же. Магия происходит здесь: // Привязываем-отвязываем обработчик на документ, соответственно жизненному циклу компонента componentWillMount: function () { document.addEventListener('click', this.unStrike, false); }, componentWillUnmount: function () { document.removeEventListener('click', this.unStrike, false); }, и здесь: unStrike: function(event){ // предотвращаем срабатывание на самом элементе if (ReactDOM.findDOMNode(this).contains(event.target)) { return; } // smth else },

EventTrigger с двумя условиями

#wpf #события #триггер


Доброго времени суток! Помогите пожалуйста дописать триггер. Данный триггер меняет
Opacity  компонента (StackPanel) с 0 до 70% (т.е. делает компонент видимым) при нажатии
на него левой кнопки мыши. 

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


событие MouseLeftButtonDown
Property="Opacity" Value="0.7"


Можно ли делать EventTrigger с двумя условиями?

Как в DataTrigger "забиндить" событие MouseLeftButtonDown?

   

    


Ответы

Ответ 1



Можно обойтись без code-behind, почти. Вам нужно сделать attached property, значение которого будет выставляться через EventTrigger, в вашем случае при нажатии левой кнопки мыши. А рядом положить MultiTrigger, который будет срабатывать при условии наличия значения в упомянутом выше свойстве. UPD: код. Модель: public class Model : INotifyPropertyChanged { private bool _isPropertySet; public event PropertyChangedEventHandler PropertyChanged; [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public Model() { SetPropertyCommand = new DelegateCommand(o => { IsPropertySet = !IsPropertySet; }); } public bool IsPropertySet { get { return _isPropertySet; } set { _isPropertySet = value; OnPropertyChanged(nameof(IsPropertySet)); } } public ICommand SetPropertyCommand { get; set; } View: Вам нужен один триггер на событие для установки свойства, и один триггер, который биндится на это свойство и выставляет нужное значение Opacity.

четверг, 23 января 2020 г.

yii2 события в контроллерах

#php #yii2 #события


Есть два модуля - Comments и Pages со своей структурой, т.е. реализация не стандартная
как по умолчанию в Yii2. Соответственно два контроллера 

class CommentsController extends BaseController
{            
    public function actionIndex()
    {
        return $this->render('index');
    }
}

Event::on(PagesController::className(), PagesController::EVENT_GET_COMMENTS, 
function ($event) {
       echo 'comments';
    });


ну и аналогично для Pages

class PagesController extends BaseController
{   
    const EVENT_GET_COMMENTS = '';

    public function actionIndex()
    {
        $this->trigger(self::EVENT_GET_COMMENTS);

        return $this->render('index');
    }
}


В теории при вызове контроллера Pages действия index должно срабатывать событие EVENT_GET_COMMENTS
и выводиться comments, но этого не происходит :(
    


Ответы

Ответ 1



У вас есть 3 способа: №1 (глобально): Создать компонент с необходимой логикой Добавить в конфигурационный файл 'components' => [ 'myComponent' => [ 'class'=>'app\components\MyComponent' ], //other components ] и не забыть про 'bootstrap' => ['log','myComponent'] №2: Унаследовать метод в контроллере public function beforeAction($event) { // ваш код return parent::beforeAction($event); } №3: Создать поведение: http://www.yiiframework.com/doc-2.0/guide-concept-behaviors.html, см. как Добавить написанное поведение в контроллер, например как AccessControl

среда, 22 января 2020 г.

dbms_alert Интервалы опроса

#oracle #plsql #события


Объясните, пожалуйста, вот этот абзац из документации


  WAITANY procedure. If you use the WAITANY procedure, and if a signalling session
does a signal but does not commit within one second of the signal, a polling loop is
required so that this uncommitted alert does not camouflage other alerts. The polling
loop begins at a one second interval and exponentially backs off to 30-second intervals.


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

function WaitAny(ATimeout) {
  const intervals = [0, 1, ....., 30);
  for (i = 0; i < intervals.length; i++) {
    Sleep(min(intervals[i], ATimeout))
    if (IsExistsEvents())
      return 0;
    ATimeout -= intervals[i];
    if (ATimeout <= 0)
      return 1;
  }
  maxInterval = intervals[intervals.length - 1];
  while (ATimeout > 0) {
    Sleep(min(maxInterval, ATimeout))
    if (IsExistsEvents())
      return 0;
    ATimeout -= maxInterval;
  }
  return 1;
}

    


Ответы

Ответ 1



TL;DR: Нет, при получении события, оповещение о нём будет практически сразу же передано в обработчик, то есть возврат из функции waitany. Но в определённых случаях задержка возможна (см. далее). Передача события (signal) между отправителем и приёмником в dbms_alert транзакциональна и состоит из двух частей: Не транзакциональная передача события посредством database pipe механизма (реализовано на dbms_pipe). Подтверждение события посредством commit в отправителе. В приёмнике это реализовано стандартным lock меанизмом БД. В нормальном случае, приёмник ждёт получение события из pipe. При его получении, оно только регистрируется как принятое, но не подтверждённое. При наличии таких событий в приёмнике, waitany опрашивает статус сессии на предмет завершения транзакции, в которой событие было послано. Если транзакция завершается с commit, то waitany завершается и передаёт текущее событие в приёмник для дальнейшей обработки, в противном случае - rollback - событие удаляется из очереди принятых в waitany. В исключительном, случае, о котором идёт речь в цитате из вопроса, событие ещё не зафиксировано. т.е. не подтверждено в сессии отправителя. Так как бесконечное ожидание на подтверждение будет блокировать получение других событий из pipe, начинается опрос с интервалом начиная с 1-ой с возрастанием до 30-ти секунд. То есть приёмник ожидает подтверждения завершения транзакции с текущим интервалом ожидания (1..30 сек.) и если оно не происходит, возвращается к считыванию из pipe новых событий, после чего цикл повторяется. Почему последний случай исключительный? Если событие отправленно, но не зафиксировано сразу же, то это, как будет видно в примере ниже, не обеспечит гарантированной асинхронной обработки событий. Поэтому, или устранить задержку между signal и commit, или, если это не представляется возможным, отказаться от dbms_alert и посмотреть в сторону Advanced gueuing (dbms_aq). Пример для наглядности. Понадобится три сесси: приёмнк, "ленивый" отправитель (PROCL=lazy SID=26) и "правильный" отправитель (PROCQ=quick SID=270). Запустим приёмник событий: SQL> set serveroutput on size unlimited exec dbms_alert.register ('PROCQ'); - dbms_alert.register ('PROCL'); - dbms_alert.register ('EXIT'); exec receiveSignals В отправителе SID=26 пошлём событие с задержкой подтверждения: SQL> exec sendSignal ('PROCL',delayed=>true) PROCL sent 14:02:10.482 from 26 delayed В отправителе SID=270 пошлём событие и зафиксируем его сразу: SQL> exec sendSignal ('PROCQ',delayed=>false) PROCQ sent 14:03:20.842 from 270 Вернёмся в SID=26 и подтвердим событие: SQL> exec sendSignal (null,delayed=>false) none sent 14:03:34.272 from 26 В отправителе SID=270 пошлём событие EXIT: SQL> exec sendSignal ('EXIT',delayed=>false) EXIT sent 14:03:41.849 from 270 Вывод в приёмнике после приёма события EXIT: stat=0,sig=PROCL,received=14:03:34.274: msg=sent 14:02:10.482 from 26 delayed stat=0,sig=PROCQ,received=14:03:34.275: msg=sent 14:03:20.842 from 270 stat=0,sig=EXIT,received=14:03:41.852: msg=sent 14:03:41.849 from 270 Видно, что задержка в SID=26 вызвана поздним подтверждением и была получена в приёмнике сразу же после commit в отправителе (14:03:34). Но ожидание на подтверждение привело к задержке почти 15 сек на получения события от SID=270. (отпр. 14:03:20, получ. 14:03:34), т.е функция waitany в момент отправки подтверждённого события от SID=270, находилась в ожидании подтверждения от SID=26. PS: Этот ответ не является переводом, ни прямым, ни вольным, ответа сотрудника компании Oracle на аналогичный вопрос ТС на engl. SO, он скорее всего попытка более наглядного пояснения ситуации. Функции, которые использованы в воиспроизводимом примере выше: create or replace procedure receiveSignals is sig varchar2 (32); stat number; msg varchar2 (64); begin loop dbms_alert.waitany (sig, msg, stat); dbms_output.put_line ( 'stat='||stat||',sig='||sig||',received='||to_char (systimestamp, 'hh24:mi:ss.ff3')||': msg='||msg); exit when sig = 'EXIT'; end loop; end; / create or replace procedure sendSignal (sig varchar2, delayed boolean := true) is msg varchar2 (1800) := 'sent '||to_char (systimestamp, 'hh24:mi:ss.ff3')||' from '|| sys_context ('USERENV', 'SID')||case when delayed then ' delayed' end; begin if sig is not null then dbms_alert.signal (sig, msg); end if; if not delayed then commit; end if; dbms_output.put_line (case when sig is null then 'none' else sig end||' '||msg); end; /

События и сборка мусора в c#

#c_sharp #winforms #события #сборщик_мусора


Начал изучать концепцию событий в c#. У меня есть следующие классы:

class CustomTimer
    {
        public delegate void DateAndTimeHandler(DateTime dateTime);

        DateAndTimeHandler dateOrTimeUpdated;

        public event DateAndTimeHandler DateOrTimeUpdated
        {
            add { lock (this) dateOrTimeUpdated += value; }
            remove { lock (this) dateOrTimeUpdated -= value; }
        }

        public CustomTimer()
        {
            InitialStartedTime = DateTime.Now;
            int num = 0;

            TimerCallback tm = new TimerCallback(ProcessTime);

            System.Threading.Timer timer = new System.Threading.Timer(tm, num, 0, 1000);

        }

        private void ProcessTime(object obj)
        {
            dateOrTimeUpdated?.Invoke(DateTime.Now);
        }

    }

    class SuperCore
    {
        public CustomTimer timer = new CustomTimer();
    }


И небольшой пример работы с этими классами в WinForms:

public partial class Form1 : Form
{
    public string StringTime
    {
        get { try { return label1.Text; } catch { return ""; }; }
        set { try { Invoke(new Action(() => { label1.Text = value; })); } catch { } }
    }

    SuperCore superCore = new SuperCore();
    public Form1()
    {
        InitializeComponent();
        superCore.timer.DateOrTimeUpdated += TimeUpdate;
    }

    void TimeUpdate(DateTime dt)
    {
        StringTime = dt.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        GC.Collect();
    }
}


Я заметил, что при сборке мусора у меня перестает обновляться время на label1, т.е.
происходит уничтожение события. Чтобы проверить это и убедиться, что так и есть, я
при нажатии на button1 вызываю сборщик мусора. Гипотеза подтвердилась.

Это приложение является просто демонстрацией проблемы.

Вопрос:
Как мне сделать так, чтобы подписка на событие сохранялась? Чтобы время обновлялось
на label1?
    


Ответы

Ответ 1



Необходимо сделать timer полем класса CustomTimer. Код класса CustomTimer будет выглядеть так: class CustomTimer { public delegate void DateAndTimeHandler(DateTime dateTime); DateAndTimeHandler dateOrTimeUpdated; public event DateAndTimeHandler DateOrTimeUpdated { add { lock (this) dateOrTimeUpdated += value; } remove { lock (this) dateOrTimeUpdated -= value; } } System.Threading.Timer timer; public CustomTimer() { int num = 0; TimerCallback tm = new TimerCallback(ProcessTime); timer = new System.Threading.Timer(tm, num, 0, 1000); } private void ProcessTime(object obj) { dateOrTimeUpdated?.Invoke(DateTime.Now); } } За ответ в комментариях на вопрос спасибо Alexander Petrov и tym32167.

четверг, 2 января 2020 г.

JQuery поиск обработчика события объекта

#jquery #dom #события


Мне нужно найти, какие обработчики событий записаны на объекте.

Например:

$("#el").click(function() {...});
$("#el").mouseover(function() {...});


На $("#el") записаны события click и mouseover.

Есть ли функция, чтобы узнать это, и можно ли выполнить итерацию по обработчикам событий?

Если это невозможно в объекте jQuery с помощью правильных методов, возможно ли это
для обычного объекта DOM? 

Переведено с: https://stackoverflow.com/questions/2518421/
    


Ответы

Ответ 1



Начиная с jQuery 1.8, информация о событиях больше не доступна из «public API» для данных. Прочтите это сообщение в блоге jQuery. Теперь, для того чтобы узнать список событий записанных на объекте, нужно использовать это: jQuery._data( elem, "events" ); elem должен быть элементом HTML, а не объектом jQuery или селектором. Обратите внимание, что это внутренняя, «частная» структура, и ее не следует изменять. Используйте это только для целей отладки. В старых версиях jQuery вам может потребоваться использовать старый метод: jQuery( elem ).data( "events" ); Пример: $('#el').click(function() { $(this).text('Нажали!'); }) $('#el').mouseover(function() { $(this).text('Поводили мышкой!'); }); // Получаем события var elem = $('#el').get(0); console.log( $._data(elem, "events") );
Текст