R03-03.DOC

(724 KB) Pobierz
Szablon dla tlumaczy

Interfejs użytkownika

Jedną z zalet C++Buildera, jako narzędzia RAD, jest możliwość łatwego i szybkiego budowania interfejsu użytkownika aplikacji za pomocą użytecznych narzędzi wizualnych. Same narzędzia jednak nie wystarczą – aby interfejs aplikacji spełnił oczekiwania użytkownika i spotkał się z jego akceptacją, konieczne jest kierowanie się pewnymi zasadami jego budowy. Zasady te, wynikające przede wszystkim ze sposobu użytkowania komputera przez (typowego) użytkownika, muszą być znane każdemu projektantowi, jeżeli chce on tworzyć aplikacje obsługiwane w sposób nieskomplikowany, zgodnie z intuicją i wymogami wygody użytkownika.

 

Rozdział ten rozpoczniemy od przedstawienia ogólnych przesłanek funkcjonowania interfejsu użytkownika i wynikających stąd zasad jego konstrukcji; w pozostałej jego części zaprezentujemy praktyczne zastosowanie tych zasad na przykładzie kilku wybranych aplikacji.

Podstawowe zasady konstrukcji interfejsu użytkownika

Gdy przyjrzeć się przedstawionym poniżej regułom, określającym zasady budowania interfejsu użytkownika, większość z nich wydaje się być intuicyjnie jasna, ale nie wszystkie są aż tak oczywiste. Ich przestrzeganie jest jednak niezbędne do tego, by interfejs użytkownika – stanowiący zgodnie z nazwą pewną platformę współpracy użytkownika z aplikacją – nie stał się w tej współpracy przeszkodą. Sekwencyjny charakter tekstu wymusza co prawda omówienie wspomnianych reguł w określonej kolejności, jednak każda z nich jest nie mniej ważna od pozostałych.

 

·         Spełnienie oczekiwań użytkownika – na ogólnie rozumianą przydatność aplikacji dla użytkownika składają się nie tylko wykonywane przez nią czynności, lecz również i komfort jej obsługi; ten ostatni zdeterminowany jest przede wszystkim przez jej interfejs użytkownika.

·         Przejrzystość i klarowność – aby interfejs nie odwracał uwagi użytkownika od zasadniczych czynności spełnianych przez aplikację, jego wygląd powinien pozostawać w ścisłym, intuicyjnie jasnym związku ze spełnianymi przez niego funkcjami. Elementy wykonujące powiązane ze sobą funkcje powinny być w widoczny sposób pogrupowane, należy jednak unikać nadmiernego ich zagęszczenia; nawigacja pomiędzy różnymi częściami interfejsu powinna odbywać się w prosty sposób. Kontrolki obsługiwane myszą powinny mieć rozmiary wystarczająco duże, my można było w nie „trafić” kursorem bez kłopotu, a kontrolki używane szczególnie często jedna po drugiej nie powinny znajdować się w zbyt dużej odległości od siebie ze względów ergonomicznych – dla użytkownika nie ma nic bardziej męczącego niż kłopotliwe pozycjonowanie myszy na mikroskopijnych przyciskach i „dzikie” skoki kursora przez połowę ekranu.

·         Intuicyjność i logika – poszczególne funkcje oferowane przez interfejs użytkownika powinny być dostępne w oczywisty, intuicyjny sposób, nie wymagający wykoncypowanych przemyśleń ani też zaawansowanych kwalifikacji. W przeciwnym razie aplikacja może stać się trudna w obsłudze dla początkującego użytkownika i może nie zostać przez niego zaakceptowana, mimo wysokiego stopnia zaawansowania spełnianych przez nią funkcji.

·         Przyjazność – interfejs skonstruowany w przyjazny dla użytkownika sposób wymaga mniej czasu na nauczenie się jego obsługi, jak również mniej wysiłku przy samej obsłudze.

·         „Sprzężenie zwrotne” – użytkownik powinien mieć pewność, iż oczekiwane przez niego zachowania aplikacji rzeczywiście występują; upewnieniu takiemu służyć mogą różnorakie komunikaty potwierdzające wykonanie różnych operacji, czy też informujące o stopniu zaawansowania operacji długotrwałych, chociaż przejawy owego „sprzężenia zwrotnego” przybierają niekiedy postać bardziej elementarną, jak np. zmiana wyglądu przycisku po jego „naciśnięciu” czy sygnał dźwiękowy w reakcji na niewłaściwy klawisz albo kliknięcie w niewłaściwym miejscu – mimo swej elementarności środki takie nie powinny być jednak traktowane marginalnie. W szczególnych przypadkach interfejs może oferować użytkownikowi dodatkowe środki informacyjne, jak np. migotanie paska tytułowego czy obrzeża ekranu towarzyszące sygnałowi dźwiękowemu, przydatne np. dla osób z upośledzeniem słuchu.

·         Dostępność – poszczególne funkcje interfejsu powinny być dostępne w możliwie największym stopniu – oprócz klawiatury i myszy może okazać się uzasadnione zaimplementowanie alternatywnych środków wprowadzania informacji, jak np. sterowanie głosem przeznaczone dla użytkowników z utrudnieniami obsługi standardowych urządzeń wejściowych.

·         System pomocy – ze względu na mnogość funkcji realizowanych przez typowy interfejs użytkownika wielu ich aspektów nie da się wyrazić wprost poprzez konstrukcję samego interfejsu, bez względu na to, jak wysoce intuicyjny i przyjazny by on nie był; uzupełniającą rolę w tej mierze spełniają wbudowane w aplikację systemy pomocy  (online help) oraz dokumentacja i ew. obsługa techniczna – „gorąca linia” lub poczta elektroniczna.

·         Konfigurowalność – należy umożliwić przystosowywanie rozmaitych aspektów wyglądu i działania interfejsu do indywidualnych potrzeb użytkowników. Przykładem takiego przystosowywania może być dobór kolorystyki poszczególnych elementów, lecz pojęcie konfigurowalności interfejsu nie ogranicza się bynajmniej do samego jego wyglądu – różni użytkownicy mogą korzystać z różną częstotliwością z różnych funkcji aplikacji, należy zatem pozwolić im na takie skonfigurowanie elementów interfejsu, by funkcje używane najczęściej dostępne były jak najszybciej i uruchamiane w jak najprostszy sposób.

·         Możliwość odwrotu – nikt z nas nie jest nieomylny; użytkownicy komputerów popełniają więc błędy i możliwość anulowania skutków błędnej operacji czy wycofania się z błędnie wybranej opcji może mieć niekiedy kluczowe znaczenie. Przykładem tego rodzaju mechanizmów są powszechnie stosowane funkcje „Cofnij” (w wersji angielskiej „Undo”), a także wycofywanie się na poprzedni poziom dialogu za pomocą klawisza (najczęściej) Esc.

·         Czytelna informacja o błędach – niezależnie od tego, jak „idiotoodporna” byłaby aplikacja, nie jest ona w stanie wykonać bezsensownych żądań użytkownika, ani też zaradzić różnorodnym „nieszczęściom” zewnętrznym w rodzaju niewystarczającej pamięci czy błędów zapisu na dysk. Sytuacje takie powinny być komunikowane użytkownikowi w sposób zrozumiały, wyrażony w kategoriach, w jakich postrzega on funkcjonowanie programu; niestety, wiele komunikatów o błędach ma tak lakoniczną formę i tak niezrozumiałą treść, iż nawet sami autorzy aplikacji (!) mają po pewnym czasie trudności z ich interpretacją i określeniem prawdziwej przyczyny błędu. W niektórych sytuacjach błąd ma charakter przejściowy i ponowna próba wykonania danej czynności może zakończyć się pomyślnie – czego przykładem może być brak dostępu do zablokowanego pliku w sieci – niektóre błędy, jak np. brak dyskietki w napędzie, wynikają też z przeoczenia użytkownika. Porządnie skonstruowana aplikacja powinna każdorazowo informować o takich uwarunkowaniach.

·         Symbolika graficzna – rozmaite symbole, ikony, zróżnicowana kolorystyka itp. czynią interfejs użytkownika bardziej intuicyjnym i łatwiejszym w obsłudze. Nie należy zapominać o oczywistym fakcie, iż postrzeganie symboli odbywa się znacznie szybciej niż odczytywanie napisów, ponadto określone funkcje aplikacji zazwyczaj łatwiej bywają kojarzone z symbolami graficznymi niż z opcjami menu. Te ostatnie są co prawda bardziej komunikatywne dla użytkownika rozpoczynającego pracę z aplikacją, lecz po rozpoznaniu poszczególnych jej funkcji będzie on najprawdopodobniej kojarzył te funkcje z poszczególnymi symbolami. Zróżnicowana kolorystyka może przyczynić się do lepszego uwypuklenia poszczególnych elementów funkcjonalności interfejsu, na przykład przez pogrupowanie powiązanych ze sobą opcji czy przycisków.

·         Mobilność –  poszczególne elementy interfejsu powinny być dostępne bez zbędnej fatygi użytkownika. Jeżeli przykładowo przypiszemy klawisze skrótu do poszczególnych opcji menu, uwolnimy być może użytkownika od ciągłego „przerzucania się” z klawiatury na mysz i vice versa. Zwiększy się przez to mobilność aplikacji, rozumiana jako ilość wykonanej przez nią pracy w przeliczeniu na wysiłek użytkownika.

 

Jak już napisaliśmy, większość z przedstawionych zasad wydaje się niemal oczywista, dlatego też często zapomina się o nich i nie od rzeczy było przypomnieć je tutaj – spędzając długie godziny nad debuggerem lub studiowaniem kodu źródłowego zapominamy niekiedy, iż aplikacja nasza trafić może do rąk człowieka nie tylko posługującego się innym językiem, lecz być może nie umiejącego wskazać naszego kraju na mapie…

 

Przykładowe projekty wykorzystywane w tym rozdziale

Jeden przykład wart jest tysiąca słów, więc po zwięzłym przedstawieniu zasad, jakimi rządzi się nowoczesny interfejs użytkownika, pora teraz pokazać, jak zasady te wykorzystywane powinny być w praktyce. W tym celu przedstawimy kilka przykładowych projektów i w kolejnych podrozdziałach omawiać będziemy poszczególne aspekty ich funkcjonowania, oczywiście ze szczególnym uwzględnieniem ich związku z interfejsem użytkownika.

Najczęściej odwoływać się będziemy do projektu realizującego prosty kalkulator – jego kompletny materiał źródłowy znajduje się na dołączonej do książki płycie CD-ROM. Niektóre podrozdziały, omawiające zagadnienia nie związane bezpośrednio z tym projektem, ilustrowane będą dodatkowymi aplikacjami, których wykaz – w kolejności pojawiania się w treści rozdziału – przedstawia tabela 3.1.

 

Tabela 3.1. Wykaz uzupełniających aplikacji demonstracyjnych używanych w tym rozdziale

Projekt

Wykorzystywany w podrozdziałach…

Focus.bpr

Kontrola migracji skupienia pomiędzy elementami interfejsu

MDIProject.bpr

Dostosowanie tła formularza głównego MDI

Scentralizowane sterowanie akcjami obiektu

Panels.bpr

Wyrównanie – właściwość Align

Zakotwiczenie – właściwość Anchors

Ograniczenia swobody zmiany rozmiarów – właściwość Constraints

ProgressCursor.bpr

Wykorzystanie komponentów TProgressbar i TCGauge

Wygląd kursora

ScreenInfo.bpr

Zróżnicowane konfiguracje graficzne

 

Wśród wymienionych w tabeli projektów uzupełniających jeden z nich – MDIProject.bpr – wyraźnie odróżnia się od pozostałych, gdyż realizuje wielodokumentowy model interfejsu użytkownika (ang. MDI – Multiple Document Interface), podczas gdy pozostałe należą do kategorii aplikacji jednodokumentowych (ang. SDI – Single Document Interface). Aplikacje jednodokumentowe posiadają jeden formularz główny i opcjonalnie dowolną liczbę formularzy pomocniczych, z których każdy może być wyświetlany w sposób modalny lub niemodalny; owe formularze pomocnicze nie są jednak związane z formularzem głównym relacjami „potomny – rodzicielski” (ang. child – parent). W przypadku aplikacji wielodokumentowej formularze pomocnicze są formularzami potomnymi w stosunku do formularza głównego, co w pierwszym rzędzie uwidacznia się w ten sposób, iż obszar ich widoczności ograniczony jest do obszaru klienta formularza głównego – innymi słowy formularz główny spełnia rolę swoistego „kontenera wizualnego” dla swych formularzy potomnych. Formularze potomne wyświetlane są w sposób niemodalny, co umożliwia łatwe przełączanie się pomiędzy nimi. Funkcjonalność aplikacji wielodokumentowej charakteryzuje się kilkoma unikatowymi cechami, m.in. możliwością rozmaitego aranżowania układu formularzy potomnych, łączenia menu formularza głównego z menu formularza potomnego (ang. menu merging) – można je prześledzić, studiując wspomniany projekt MDIProject.bpr.

 

Kalkulator – wprowadzenie do projektu

 

Projekt MiniCalculatorProject.bpr realizuje aplikację oferującą podstawowe funkcje prostego kalkulatora, poszerzone o elementy charakterystyczne dla typowej aplikacji dla Windows. To ważny aspekt projektowy – interfejs użytkownika skonstruowany w konwencji (zrozumiałej dla wszystkich) obsługi kalkulatora uwalnia jednocześnie użytkownika od wielu uciążliwości związanych z tą obsługą; zajmiemy się dokładniej tym zagadnieniem w jednym z następnych podrozdziałów.

Rysunek 3.1 przedstawia widok działającego programu, oczywisty dla każdego, kto choć raz w życiu posługiwał się kalkulatorem, nietrudno jednak zauważyć dodatkowe elementy charakterystyczne nie dla samego kalkulatora, lecz właśnie dla jego realizacji w postaci aplikacji dla Windows.

 

 

 

Rysunek 3.1. Kalkulator jako aplikacja dla Windows

 

 

W projekcie MiniCalculatorProject.bpr wykorzystano wyłącznie rodzime komponenty C++Buildera – bez uciekania się do komponentów kategorii third-party – co samo w sobie stanowi niezłą ilustrację jego możliwości. Użyte komponenty, w podziale na zawierające je strony palety komponentów, przedstawione zostały w tabeli 3.2.

 

Tabela 3.2. Komponenty wykorzystane w projekcie MiniCalculatorProject.bpr

 

Strona palety komponentów

Komponenty

Standard

TActionList

TMainMenu

TPanel

TPopupMenu

Additional

TApplicationEvents

TBevel

TBitBtn

TControlBar

ITImage

TSpeedButton

Win32

TImageList

TStatusBar

Dialog

TColorDialog

 

Podczas projektowania aplikacji spory wysiłek włożony został w nadanie jej odpowiedniego wyglądu graficznego, w szczególności – w wykonanie niezbędnych do tego ikon i obrazków; posłużono się przy tym pakietem Paint Shop Pro firmy JASC, którego ewaluacyjna wersja 7.00 znajduje się na dołączonej do książki płycie CD-ROM.

 

UWAGA – w tym miejscu jest mowa o tym, iż na CD-ROMie znajduje się evaluate version PaintShop Pro 7.00

 

Zwiększanie użyteczności aplikacji drogą sprzężenia zwrotnego

Idea sprzężenia zwrotnego realizowana jest w aplikacjach Windows za pomocą rozmaitych środków, udostępniających użytkownikowi informacje na temat stanu aplikacji lub stopnia zaawansowania wykonywanych przez nią operacji. Do środków tych należą m.in. wszelkiego rodzaju komunikaty (message boxes), paski statusowe (status bars), rozmaite odmiany pasków i wskaźników postępu (progress bars, gauges), a także podpowiedzi (hints) czy sugestywny wygląd kursora, sugerujący użytkownikowi możliwość wykonania określonych operacji w kontekście wskazywanej aktualnie przez ten kursor kontrolki – na przykład kursor w kształcie dłoni sugeruje najczęściej, iż mamy właśnie do czynienia z hiperłączem.

W kolejnych punktach przyjrzymy się dokładniej zasadom funkcjonowania wymienionych przed chwilą komponentów.

 

Wykorzystanie komponentów TProgressbar i TCGauge

Paski postępu (progress bars) stanowią wygodne narzędzie uwidaczniania stopnia zaawansowania długotrwałych operacji wykonywanych przez aplikacje; w niektórych sytuacjach są one jedynym świadectwem tego, iż dana aplikacja wciąż funkcjonuje, a zlecone jej zadanie, chociaż powoli, wciąż jest realizowane.

Reprezentujący pasek postępu komponent TProgressBar znajduje się na stronie Win32 palety komponentów. Jej strona Samples również zawiera komponent tego rodzaju o nazwie TCGauge. Jest on nieco bardziej zaawansowany od swego kolegi, może bowiem przybierać różne formy geometryczne, zaś wyświetlana przez niego informacja ma bardziej czytelną postać i może zostać wyrażona w formie liczbowej. Segmentowana, „skokowa” natura paska TProgressBar wydaje się nie mieć odniesienia do posuwającej się wciąż naprzód operacji, a wyświetlana przezeń informacja umożliwia co najwyżej szacunkowe określenie ilości wykonanej przez aplikację pracy.

Tym niemniej operacje wykonywane przez obydwa komponenty są do siebie podobne. Zakładając, iż komponenty te noszą w naszej aplikacji nazwy (odpowiednio) ProgressBar i CGauge, możemy ustawić wartości odpowiadające ich wskazaniom minimalnym i maksymalnym oraz bieżącej pozycji:

 

// minimum

ProgressBar–>Min = 0;

CGauge–>MinValue = 0;

 

// maksimum

ProgressBar–>Max = 0;

CGauge–>MaxValue = 0;

 

// bieżąca pozycja

ProgressBar–>Position = 0;

CGauge–>Progress = 0;

 

Możemy także zwiększyć o 1 wskazanie każdej z kontrolek:

 

// inkrementacja

ProgressBar–>Position = ProgressBar–>Position + 1;

CGauge–>Progress = CGauge–>Progress + 1;

 

W przypadku obydwu omawianych komponentów próba zwiększenia bieżącego wskazania poza wartość maksymalną nie daje żadnego efektu. TProgressBar dysponuje jednak metodami StepIt() oraz StepBy(), dokonującymi zwiększenia bieżącego wskazania o (odpowiednio) wartość właściwości Step lub specyfikowaną wartość typu int bez respektowania tegoż ograniczenia: wskazanie nie zatrzymuje się na wartości maksymalnej, lecz „zawija się” wokół wskazania minimalnego.

Porównanie możliwości komponentów TProgressBar i TCGauge jest treścią projektu ProgressCursor.bpr, znajdującego się na załączonej płycie CD-ROM. Wybór konkretnej kontrolki jest każdorazowo kwestią konkretnego zastosowania i preferencji projektowych, w każdym razie aplikacja realizująca długotrwałe operacje musi być wyposażona w jakikolwiek element interfejsu, komunikujący użytkownikowi swe funkcjonowanie.

Wygląd kursora

Zmiana wyglądu kursora myszy stosownie do jego położenia i bieżącego stanu aplikacji jest powszechnie stosowanym elementem współczesnych interfejsów użytkownika. W aplikacjach tworzonych z użyciem C++Buildera zmiany wyglądu kursora dokonywać można w dwojaki sposób.

Pierwszy z nich polega na zmianie właściwości typu TCursor kontrolki, w obszarze której kursor przybierać ma określony wygląd – i tak np. właściwość Cursor określa wygląd kursora w sytuacji jego znalezienia się na kontrolce w „zwykłych” warunkach, zaś właściwość DragCursor odpowiedzialna jest za wygląd kursora podczas „przeciągania” kontrolki.

...

Zgłoś jeśli naruszono regulamin