Program sterowany zdarzeniami.

Program sterowany zdarzeniami.
NE
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 13 lat
  • Postów:4
0

Witam. Mam drobny problem.
Nie będę zamieszczał żadnego kodu gdyż w tym przypadku mija się to z celem. Będę pisał w uproszczeniu.
Napisałem program. Jest w nim funkcja A i funkcja B. Początkowo tak się zkłada, że wywoływana jest funkcja A. Gdy wykona się funkcja A może zostać (powinna) wywołana funkcja B. Gdy funkcja B się wykona może zostać (powinna) zostać wywołana funkcja A, itd...
Na pierwszy rzut oka wygląda na nieskończoną rekurencję..., ale tak nie jest.
Chodzi mi o to, że na początku wywołujemy funkcję A. Jeżeli się ona wykona (podkreślam, wykona w całości) i jeżeli wszystko pójdzie dobrze (zostaną spełnione określone warunki) może zostać wywołana funkcja B. Podobna sytuacja ma się dla funkcji B.
Długo rozmyślałem jak rozwiązać ten problem i doszedłem (doczytałem), że najlepiej byłoby wprowadzić zdarzenia. To znaczy po wykonaniu funkcji A wstawialibyśmy do kolejki zdarzeń zdarzenie, w którym zawierałoby się wywołanie funkcji B, itd...
Jednakże tutaj urywa się moja twórczość. Nie wiem dokładnie jak miałbym to zrobić.
Bardzo proszę o pomoc....

lipkerson
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad 2 lata
1

Jak pisałem komunikacje socketu i czytanie danych - to miałem podobne dylematy. Jak przeczytał dane np. z dokumentu (całe) to uruchamiał komunikacje na sockecie- wysyłanie danych...i potem (a właściwie w innym wątku) cały czas czekał na kolejne wywolanie odczytania. Oczywiście wysył mógł się nie powieśc i bylo trzeba spróbowac jeszcze raz.

Ja to rozwiązałem nielubianymi nie wiem czemu polami statycznymi - one świetnie się nadają do flagowania takich rzeczy. W uproszczeniu:

Miałem pętle while - nieskonczoną w której to poprzez zwykłe ify sterowałem przebiegiem programu. Parametrami ifów były pola statyczne...coś w ten deseń:

public static boolean flagaZakonczeniaA = false;

...
metodaA();
while(true)
{
if(flagaZakonczeniaA )
{
flagaZakonczeniaA = false;
metodaB();
}
Thread.sleep(100);
}

Oczywiście jak się wykonuje metoda A to na końcu - jak wszystko odbrze pójdzie to trzeba zmienic statyczna metode sterujaca NazwaKlasy.flagaZakonczeniaA = true;

W bardzo fajny sposób mozna dodawać kolejne ify sterujace przebiegiem-jakieś wyjątki, komunikaty...na sockecie potrzebowałem asynchronicznej wymiany danych-też się sprawdziło.

A pola satyczne mozna umieścić w odrębnej klasie i je sprawnie monitorować.


Another jam from the world for the jam from the voices of the world......
RO
  • Rejestracja:ponad 17 lat
  • Ostatnio:prawie 4 lata
1
  1. stworzenie 2 kolejek (JMS - ewentualnie jednej typu publish-subscribe).Jak cokolwiek wrzucisz na kolejkę A to jej konsument przekaże to do metody A i metoda A jak uzna, że ma zostać wywołana metoda B to wrzuci coś (np jakieś dane do obróbki) do kolejki B.

  2. zrobić takie event listenery jak w swingu

  3. jeśli metoda A i B są w tej samej klasie to nie powinno być problemu z wzajemnym wywoływaniem, jeśli zaś w innych klasach to może klasa A powinna przechowywać referencję do obiektu B i vice versa?

4)wprowadzić jakiś obiekt nadrzędny, który będzie odpowiednio wywoływał metody A i B w zależności od tego co one zwrócą

Trochę mało szczegółów podałeś...jakiego typu komunikacji oczekujesz pomiędzy metodami A i B(np asynchroniczny)? Musisz tutaj zwrócić uwagę, aby nie wpaść w jakąś nieskończoną rekurencję. Podaj więcej szczegółów, ewentualnie wskaż, które rozwiązanie najbardziej odpowiada twoim potrzebom to postaram się coś rozwinąć.

NE
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 13 lat
  • Postów:4
0

Ok. Zatem podaję więcej szczegółów.
Stworzyłem prosty programik z interfejsem graficznym.
Moja metoda main wygląda tak:

Kopiuj
MyFrame myApp = new MyFrame();
myApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myApp.setVisible(true); 

dlatego od razu rozwiązanie z pętlą while i sprawdzaniem warunków odrzucamy.
Mój program to klasyczna gra logiczna, w której użytkownik i komputer wykonują naprzemiennie ruchy.
Załóżmy na razie dla uproszczenia, że grę zaczyna użytkownik. Użytkownik wskazuje myszą pole na planszy, na którym ma pojawić się piłeczka.
Po tym zdarzeniu (kliknięcie w odpowiednie pole) Następuje odtworzenie animacji (piłeczka spada w odpowiednie pole). Gdy to się wykona rolę powinien przejąć komputer. On sobie wybiera pole i tam też opada piłeczka (oczywiście po każdym ruchu sprawdzamy, czy gra się nie zakończyła). Następnie rolę może przejąć użytkownik, tzn. oczekujemy na zdarzenie kliknięcia od użytkownika itd...
Teraz jak to jest zorganizowane.
Mam klasę A.
W klasie są dwie publiczne metody.

  1. metoda: wykonajRuchUżytkownik
  2. metoda: wykonajRuchKomputer
    Metody te głównie odpowiadają za otworzenie animacji i zaznaczenie na planszy (tablicy) zajętego pola. (współpraca z metodą paintComponent i praoma atrybutami klasy).

Oczywiście w klasie A są dodatkowo zaimplementowane interfjsy do obsługi zdarzeń pochodzących od myszki, tak więc z tym, z nie ma problemu.
Początkowo robiłem to tak:
stworzyłem sobie flagę (atrybut w danej klasie, gdzie są zaimplementowane metody) wskazujące czy ruch może wykonać użytkownik (tzn. czy kliknięcie przez użytkownika będzie mogło być właściwie obsłużone).
Jeżeli flaga pozwalała na ruch użytkownika, to metoda obsługująca to zdarzenie (zdarzenie kliknięcia) zawierała w sobie kod odpowiedzialny za ruch użytkownika (wykonajRuchUżytkownik) a następnie wykonywała kod wykonajRuchKomputer).
Niestety takie rozwiązanie (mimo iż może nie wydawać się wprost logiczne) doprowadziło do błędnie działającego problemu). Odpowiednie metody były wywoływane w różnej kolejności (tzn. część instrukcji najpierw, później inna część instrukcji i prowadziło to do błędów, nie wiem czemu ale jakoś dziwnie była wówczas obsługiwana kolejka zadań systemowych). Dlatego doszedłem do wniosku, że lepiej byłoby rozwiązać to w ten sposób:
Gdy pojawi się zdarzenie kliknięcia to generujemy zdarzenie wykonania metody: wykonajRuchUżytkownik.
Gdy metoda wykonajRuchUżytkownik się wykona to generujemy zdarzenie wykonania ruchu przez komputer (zdarzenie będzie polegało de facto na wykonaniu metody wykonajRuchKomputer), następnie po obsłużeniu tego zdarzenia ustawiamy flagę logiczną w klasie umożliwiająca odpowiednie obsłużenie zdarzenia kliknięcia (a tym samym ponownego wykonania ruchu przez użytkownika) itd.....

Mój proble objawia też się w innej sytuacji. Załóżmy, że grę rozpoczyna komputer. Po kliknięciu na przycisku ZacznijGrę powinna zostać wykonanna metoda obsugująca to zdarzanie. Taka metoda jest zaimplementowana. Jej działanie polega wykonaniu pewnej części kodu (m. in. ustawia dany przycik na niewidoczny setVisible(false) a następnie odtwarza animację związaną z ruchem komputera). Jednakże uruchomienie programu daje inne rezultaty. Przebieg programu jest inny niż wskazywałby kod. Najpierw zostaje odtwrzonoa animacja związana z ruchem komputera (na błędnych wartościach) a dopiero później są wykonywane czynności (które były zapisane przed tą instrukcją) m.in ustawianie odpowiednich atrybutów i ustawienie przycisku jako niewidoczny. Tak więc jeżeli ktoś to rozumie co napisałem i wie mniej wiecej o co chodzi to prosiłbym o odpowiedź jak można to obejść. Bardzo mi na tym zależy, gdyż nie mam pomysłu a trochę się napisałem ;)

Niestety nie wiem jak wykonać obsługę tych zdarzeń. Może wykonać należy to w inny sposób? Jaki? Proszę o pomoc.

edytowany 1x, ostatnio: netfreex
NE
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 13 lat
  • Postów:4
0

OK. Przepraszam za ewentualny kłopot ;).
Problem już został przeze mnie rozwiązany. Miałem jeden drobny błąd w kodzie plus dołożyłem jedną flagę.
Pozdrawiam.

Wibowit
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 3 godziny
0

autor:
Polecam Scala Actors: http://www.scala-lang.org/node/242


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)