Първи стъпки в програмирането на Java, PC World, издателство Open Systems
Урок пети Светът на съобщенията Хващайте се за работа! Елементарни събития в програма на Java Както беше обещано, в този урок започваме да практикуваме писането на програми на езика Java. Понякога обаче по пътя
Урок пети
Както обещахме, от този урок започваме да практикуваме писане на програми на езика Java. Понякога обаче по пътя ще се докоснем до някои теоретични точки, ако това е необходимо за разбиране на работата на програмата. В този урок ще разработим аплет, който ще ни помогне да разберем механизма за съобщения на езика Java. Ето защо, за начало, нека разгледаме основните събития, които се случват по време на работата на Java програмите, и методите за тяхното прихващане.
Свят на съобщенията
Както знаете, работата на всяко Windows приложение се основава на обработка на съобщения. Съобщенията са асинхронни (т.е. могат да се случат по всяко време) извиквания към специални методи, наречени манипулатори на съобщения. Чрез извиквания към манипулатори на съобщения системата уведомява, че в програмата е настъпило някакво събитие, например щракване с мишката в прозореца на програмата. Ако системата Windows има списък от стотици събития, които могат да възникнат по време на програмата, тогава Java приложенията са много по-прости в това отношение. Само 13 елементарни събития могат да се случат в Java програма.
Тези така наречени елементарни събития могат от своя страна да предизвикат по-сложни събития. Например, ако потребителят щракне с мишката в прозореца на програма на Java, възниква събитието MOUSE_DOWN, но ако го е направил в лентата за превъртане, се задейства друго събитие, да речем SCROLL_LINE_UP. Това е второстепенно събитие.
Не се страхувайте, че описанията на съобщенията изглеждат малко объркващи - много рядко ще ви се налагасправя се с тях. Самият език Java ви предлага цялата възможна помощ чрез извикване на отделен метод за манипулиране за всяко от съобщенията, описани по-горе. Всичко, което трябва да направите, е да опишете желания манипулатор на събития във вашия клас и самата Java Virtual Machine ще го извика в момента, в който се случи това събитие. Единственото условие, когато пишете такива методи за обработка на събития, е да следвате синтаксиса, определен от спецификацията на езика Java. Ако направите грешка в описанието, в най-добрия случай компилаторът ще докладва за това, в най-лошия ще бъде създаден претоварен метод (не забравяйте, че Java, подобно на C++, позволява претоварени методи), който никога няма да бъде извикан.
Обърнете внимание, че аргументът evt от тип Event е същото събитие, което е накарало системата да извика манипулатора за това или онова събитие. Този параметър се използва рядко, освен ако няма някаква конкретна нужда да се знае за настъпилото събитие, като например точното време, в което се е случило.
Друг важен момент, който трябва да запомните, е върнатата стойност на манипулаторите. Ако съобщението се обработва от вашия метод, то връща true, в противен случай съобщението ще бъде предадено по веригата нагоре в йерархията на компонентите, докато не бъде обработено. С редки изключения манипулаторите на потребителски програмни събития винаги ще връщат true.
Време е да напиша някакъв аплет. Използвам Java Developer Kit 1.1 (JDK) в работата си. И не защото е удобно. Точно обратното: Symantec Visual Cafe или Microsoft Visual J++ са много по-добри за работата. Но JDK е стандартен инструмент и освен това може да бъде получен напълно безплатно от сървъра http://java.sun.com.
За да разберем как съобщенията се движат през програма, нека напишем аплет, койтоще ни разкаже за всички събития, които се случват. За показване на съобщения ще използваме стандартния изходен поток, тоест екрана на монитора. Изходът на съобщенията ще бъде произведен чрез извиквания на изходните функции на System. out.println(), които често се използват за проследяване на различни данни по време на отстраняване на грешки. Система. out.println() показва указания от вас ред на екрана и премества курсора на следващия ред. Ако не се изисква транслация на курсора, може да се използва функцията System.out.print().
Въведете следния изходен код във файл с име Events.java:
Ако ще използвате JDK, компилирайте изходния код с командата
Разбира се, трябва да сте сигурни, че вашият проект е видим за компилатора, в противен случай компилаторът няма да може да намери изходния файл.
Следващата стъпка е да създадете уеб страница с връзка към получения аплет. Нека направим файл Events.html и напишем следния HTML източник:
Всичко готово ли е? След това стартираме нашия аплет:
Експериментирайте с натискане на бутоните на мишката и клавиатурата. Потърсете в прозореца на DOS протокола, получен в резултат на кликванията. Обърнете внимание на някои странности в поведението на нашия аплет. Първо, когато показалецът на мишката влезе в контролите, възниква събитието MOUSE_EXIT и когато показалецът на мишката се премести обратно в прозореца на аплета, следва събитието MOUSE_ENTER.
Заключение: областите, заети от елементи на интерфейса, се изключват от прозореца на аплета и събитията с мишката в тези области не се обработват.
Второ, няма нито едно обаждане до манипулаторите за натискане и освобождаване на клавишите на клавиатурата. Това показва, че аплетът няма фокус за въвеждане. Няма акцент и върху интерфейсните елементи. Натискането на клавиша не прехвърля фокуса.
Заключение: след създаването на аплета няма фокус на въвежданеедин интерфейсен елемент.
Ако искате аплетът да проследява натисканията на клавиши, трябва да се уверите, че аплетът получава фокус. Всъщност вече има такъв ред:
По-голямата част от работата, свързана с обработката на съобщения на аплет, се обработва от метода handleEvent(). За да проверим това, нека напишем наш собствен манипулатор на съобщения handleEvent():
Последният ред връща константата false, което показва, че съобщението не е обработено. Нека компилираме и стартираме модифицираната версия на аплета, като наблюдаваме диагностичните съобщения в прозореца на DOS. Както можете да видите, сега целият процес на обработка на съобщения се свежда до извиквания на метода handleEvent(), след което нищо не се случва. Нека сменим линията
за извикване на метода handleEvent() на класа Applet, който е предшественикът на нашия аплет:
Нека ви напомня, че ключовата дума super обозначава препратка към непосредствения предшественик на класа. По принцип това е еквивалентно на следния ред:
За съжаление компилаторът на Java ще издаде съобщение за грешка за този израз, отказвайки да направи статична препратка към метода на обекта. Следователно все още трябва да използвате думата супер.
След като променихме съдържанието на метода handleEvent(), извикванията към елементарни манипулатори на съобщения (като mouseMove() и т.н.) отново паднаха като рог на изобилието. Потокът от извиквания към метода action() също е възстановен. Имайте предвид, че всяко извикване на елементарен манипулатор на съобщения се предшества от извикване на метода handleEvent().
Заключение: всяко съобщение се предава на метода handleEvent(), който трябва или да го обработи сам, или да го предаде на метода handleEvent() на класа предшественик. Последният вече анализира съобщенията на елементарни и извиква съответните им манипулатори. МетодhandleEvent() на класа предшественик също изпраща извиквания към метода action().
Следващата стъпка в нашия експеримент е да тестваме препращането на съобщения между елементите на потребителския интерфейс и аплета. Нека създадем наш собствен клас бутони и да го наречем MyButton. Добавете следния изходен код към файла Events.java:
Също така заменете всички препратки към класа Button в изходния код на аплета с MyButton. Прекомпилирайте и стартирайте аплета. Опитайте да експериментирате с щраквания върху бутони. Както можете да видите, всички събития се предават директно на класа на бутона. Същото се случва и при натискане на бутоните на клавиатурата.
Заключение: всички събития първо се предават на елемента на интерфейса, с който работи потребителят, и едва след това, ако манипулаторът на събития позволява, се предават на класа контейнер, в който се съдържа този елемент. За такова прехвърляне на съобщение манипулаторът трябва да върне стойността false.
Друга странност се наблюдава, когато фокусът за въвеждане е зададен върху бутона. Ако сега натиснете клавиша, нищо няма да се случи. Фокусът ще остане върху бутона и няма да бъде прехвърлен към реда за въвеждане, както се очаква. Тайната е проста: нашият клас не пропуска следващия. За да коригирате ситуацията, вмъкнете следния ред в манипулатора keyDown():
Сега, ако кодът на натиснатия клавиш е равен на кода на клавиша, т.е. равен на 9, тогава ние не обработваме събитието, а връщаме false, предавайки го допълнително на системата. Заключение: в програмите на Java няма разлика между функционалните клавиши и нормалните клавиши. Следователно трябва сами да проследите съмнителните моменти.
Стига за днес. Имате възможност да експериментирате сами с готов аплет.