poniedziałek, 11 października 2010

GUI - koncepcja odbioru zdarzeń myszki


Wczoraj trochę(nawet więcej) poszedłem myślami do przodu, a mianowicie do projektowania GUI(graficznego interfejsu użytkownika). Na początek rozważałem zdarzenia myszki i żeby optymalnie je obsługiwać wymyśliłem to:

- jeśli byśmy sprawdzali kolizje z myszką na każdej kontrolce, to zajęłoby to dużo czasu(wyobraź sobie z 100 kontrolek ), a przecież nie musimy sprawdzać wszystkich. Można, więc wykorzystać drzewo czwórkowe, które posłuży do eliminacji kontrolek, których i tak zdarzenie nie będzie dotyczyć. Zanim omówię, jak wykorzystać to w praktyce, trzeba wyjaśnić czym jest to drzewo, otóż wyobraźmy sobie kwadratową(dla uproszczenia)kartkę papieru, teraz dzielimy ją  na cztery równe części:

Proszę nic nie sugerować, kolory nie są tak istotne :)
Teraz każdą z tych części dzielimy na cztery równe:


Możemy dalej dzielić te komórki, aż dojdziemy do pojedynczych pikseli,które z reguły są nie podzielne:). Do GUI możemy pozostać na tym poziomie podziału. Teraz skoro już wiemy jak wygląda takie drzewo możemy przejść dalej:
- pierwszy poziom podziału to cztery(a jaka inna liczba powinna być w drzewie czwórkowym??) komórki, możemy, więc stworzyć tablicę Tab1[4][4] - jej typem będzie lista kontrolek które będą znajdowały się w danej komórce. My sprawdzamy hit testem w której komórce jest kursor myszy(najpierw na pierwszym poziomie, potem na drugim, te dane przekazujemy do tabeli i przechodzimy po liście(sprawdzamy kolizje)). Oczywiście tą tabelę musimy wygenerować przed wykorzystaniem. Takie rozwiązanie problemu z myszką powinno zaowocować wydajną pracą GUI(nie musimy sprawdzać wszystkich kontrolek, jeśli jest to nie potrzebne). 
Jeśli coś byłoby nie jasne to śmiało można pisać komentarze. A może ktoś rozwiązałby ten problem inaczej. Proszę o opinie na temat tego rozwiązania.

5 komentarzy:

  1. Podział przestrzeni dla GUI? Nie uważasz, że to "lekki" przerost formy nad treścią? Czy, nawet to sto kontrolek, to dużo?
    Nie wydaje mi się - jako iż przeważnie kontrolki można uprościć do prostokąta to sprawdzenie, czy myszka jest nad którąś to aż 4 porównania(x>=lewo && x<=prawo && y>=gora && y<=dol), więc nawet dla 100 kontrolek w najgorszym przypadku to 400 porównań czyli nic ;) Koszt implementacji drzewa będzie o wiele większy(a niekoniecznie zwiększy wydajność, 100 kontrolek na raz to "dość" dużo ;)).

    Oczywiście nie mówię, byś tego w ogóle nie robił - zawsze to doświadczenie, które może okazać się pomocne później.

    OdpowiedzUsuń
  2. Ja u siebie zrobiłem to w ten sposób, że kontrolki są przypisywane do paneli czy jak kto woli okienek. Naciśnięcie przycisku myszy wywoływane jest dla tych właśnie tworów, następnie wewnętrzna funkcja w panelu wywołuje zdarzenie dla kontrolki, jeśli jakaś została "trafiona".
    Daje to pewną plastyczność, bo część paneli może być sobie ukryta i wtedy ich nawet nie sprawdzamy. Poza tym ilość paneli jest znacznie mniejsza niż ilość kontrolek, przez co zmniejsza nam się ilość porównań.

    Tak więc: pomimo tego, że dodatkowo musimy sprawdzić koordynaty panelu, to w tym momencie ilość kontrolek do sprawdzenia drastycznie spada ; )
    Poza tym, w przeciwieństwie do Twojego rozwiązania, daje to możliwość łatwego przemieszczania kontrolek. Przypisanie ich do panelu sprawia, że pozycja "aktualizuje się" wraz z jego przemieszczeniem. I nie potrzeba do tego żadnej funkcji dodatkowej ; )

    Napisałem "aktualizuje się", bo w gruncie rzeczy się nie zmienia. Jeśli panel zaczyna się w (0,10) a kontrolka zaczyna się w (10, 20), to jej koordynaty to (10, 10). Po prostu przy rysowaniu trzeba dodać do tego pozycję panelu i wszystko gra.
    No i dodatkowo mamy ładną hierarchię obiektów.
    Główne okno-> Panele-> Kontrolki.

    OdpowiedzUsuń
  3. Tak 400 porównanie to nic, ale dolicz do tego obliczenia fizyki, rysowanie i jakieś inne obliczenia. Jeśli można ograniczyć te porównania do powiedzmy 10 to warto inwestować w takie drzewo(wbrew pozorom nie będzie to takie trudne w implementacji: wystarczy nam jedna, dwie klasy)

    OdpowiedzUsuń
  4. pomysł nie głupi..... jeśli każdy element silnika jest tak przemyślany to chwała autorowi.... a można już jakos wykorzystac ten silnik w swoim projekcie bo ja narazie męcze stare HGE....

    OdpowiedzUsuń
  5. Coś z tego silnika można wykrzesać:
    -jest wyświetlanie obrazów z plików,obsługa klawiatury, są animacje, manager,można wyświetlać tekst,rysować prymitywy. Ma nawet loggera wielowyjściowego(na konsole dosa i do pliku).
    Jednak na razie nie ma klasy do pętli głównej, ale mogę udostępnić wersję tej pętli z testów.

    OdpowiedzUsuń