Przykład z przyciskiem GUI
Jeśli użytkownik kliknie dwa razy przycisk, to polecenie do niego przypisane zostanie zainicjowane dwa razy, chyba że programista stosuje jakieś mechanizmy zabezpieczające.
Wiem, że powyższy problem jest na przykład rozwiązany w wielu formularzach GUI, które zawierają przycisk “Dalej” oraz w oknach konfiguracji, które zawierają przycisk “Zastosuj”. W pierwszym przypadku stan przycisków formularza jest dostosowywany. Na przykład użytkownik wprowadził jakieś akceptowalne dane, to przycisk “Dalej” jest włączany, w przeciwnym przypadku – wyłączany. W drugim przypadku przycisk “Zastosuj” jest wyłączany po wprowadzeniu zmian, a po dokonaniu jakichś zmian w oknie konfiguracji – włączany.
Przykład z poleceniem z menu GUI
W tym przypadku po kliknięciu polecenia menu zamyka się ono, a polecenie zaczyna być wykonywane. Kompletnie nie wiem, jaki wtedy miałby być stan aplikacji GUI, by nie wykonywać ponownie tego samego polecenia.
Opis problemu
Wiadomo, że implementacje interfejsów GUI są zdarzeniowe, czyli w podanych przykładach zachodzi jakaś interakcja użytkownika (np. kliknięcie) i zostaje rozpoczęte wykonywanie procedury obsługi tego zdarzenia. Kolejna interakcja użytkownika nic nie wie o właśnie wykonywanej i zaczyna się (na poziomie abstrakcji GUI) niezależnie od poprzedniej.
Z tego powodu występują dwie przyczyny błędów kliknięcia elementu GUI:
- Ponowne kliknięcie nie chciane, gdy już się wykonuje polecenie uruchomione poprzednim kliknięciem.
- Kliknięcie nie zamierzone, które uruchamia polecenie, a użytkownik nie zamierzał kliknąć, lecz wykonał jakieś nietypowe naciśnięcie klawisza bądź przeciągnięcie wskaźnika myszy. Czyli nie zgadza się ze specyfiką klikania.
Na przykład można (i tak często się u mnie dzieje) kliknąć dwukrotnie na ikonie pliku/katalogu, by otworzyć, a wtedy z powodu opóźnień dysku, na którym znajduje się ten plik/katalog, kliknąć ponownie, i niezamierzenie wykona się drugi raz to polecenie albo na tej samej ikonie, albo na tym, co pojawi się w otwartym katalogu. Można też kliknąć dwukrotnie, ale nie trafić dokładnie w ikonę pliku/katalogu (która jest częściowo przezroczysta lub przy granicach), i wtedy wykona się dwa razy pojedyncze kliknięcie na dwóch różnych elementach GUI, np. ikonie i tle ikony.
Moje implementacje
Podczas implementacji eksperymentalnego GUI z użyciem xcb, dla której mój sterownik zdarzeń GUI znajduje się tutaj, przyjąłem dozwoloną charakterystykę kliknięcia i wielokrotnego kliknięcia. Mianowicie określiłem maksymalne opóźnienia dla zwolnienia przycisku oraz ponownego wciśnięcia przycisku. Jeśli któryś z nich zostanie przekroczony (np. użytkownik czeka zbyt długo ze zwolnieniem przycisku lub jego ponownym naciśnięciem), to wtedy uznana zostaje tylko sekwencja kliknięć wykonana poprawnie do pierwszego przekroczenia czasu. Ponadto określiłem też minimalne opóźnienie po uznaniu takiej sekwencji do odblokowania możliwości realizacji kolejnej sekwencji kliknięć.
Stąd powstała uniwersalna obsługa sekwencji kliknięć w sterowniku zdarzeń GUI, której wynikiem interpretacji są dwa parametry: który przycisk myszy użyty oraz ile razy naciśnięto lub zwolniono ten przycisk. (Można na przykład nacisnąć, zwolnić, nacisnąć i w wyniku jest 3. Coś jakby klik i rozpoczęcie uchwycenia obiektu GUI.)
Jednak (jak sprawdzam w przykładowym programie GUI) mimo poprawy ogólnej interpretacji kliknięć, czyli eliminacji pomyłkowych kliknięć, da się też zauważyć tym razem zignorowane kliknięcia. To ostatnie wynika z tego, że w moim sterowniku zdarzeń GUI w pętli zdarzeń od razu po odczycie zdarzenia GUI zapisuję jego parametry startowe do użycia na później, a dopiero po wykonaniu się pętli czytania wszystkich zdarzeń GUI dokonuję ich interpretacji. Z tego powodu niekiedy upływa już czas maksymalnego opóźnienia od pierwszego naciśnięcia przycisku do kolejnego zanim sterownik dokona interpretacji. Nie wiem, jak to rozwiązać.
Pytania
- W jaki sposób zaprojektować abstrakcję stanu wizualnego aplikacji GUI w zależności od tego, co się w niej obecnie dzieje ze względu na interakcję z użytkownikiem? Czy istnieją do tego jakieś gotowe przykłady, szablony?
- Czy istnieje jakiś system GUI, w którym byłby bezpośredni związek między specyfiką klikania przez użytkownika a graficzną wizualizacją stanu? Tak by system GUI interpretował kliknięcia i uruchamiał polecenia tylko wtedy, gdy użytkownik się nie pomylił.