XPCE jest zorientowanym obiektowo podsystemem wizualizacji dla środowiska SWI-Prolog. Pełna dokumentacja XPCE znajduje się pod adresem: http://hcs.science.uva.nl/projects/xpce/UserGuide/
new/2 (new(?Reference, +NewTerm)) umożliwia tworzenie obiektów graficznych, pierwszy argument zwraca referencje do utworzonego obieku (unikalny identyfikator) z użyciem @/1, drugi argument jest rodzajem obiektu (klasą) do utworzenia.
Referencje może być utworzona przez new
:
?- new(P, point(10,20)). P = @772024
Albo zadana (nazwana) tzw. named reference:
?- new(@demo, dialog('Demo Window')).
free/1 (free(+Reference)) niszczy obiekty, argumentem jest identyfikator obiektu (pierwszy argument new/2).
?- free(@demo).
Uwaga: Wszystkie obiekty utworzone z wykorzysaniem named reference (@demo w powyższym przykładzie) muszą być usunięte za pomocą free/2 w celu uniknięcia wycieków pamięci. Jeżeli referenca obiektu nie jest nazwana (pierwszy argument new jest szukaną), obiekty takie są automatycznie usuwane.
Stan obiektu można zmodyfikować korzystając z predykatu: send/2. Pierwszym argumentem jest referencja obiektu, drugim metoda do wykonania. Poniższy przykład dodaje pole tekstowe do utworzonego wcześniej okna dialogowego.
?- send(@demo, append(text_item(nazwa))).
Aby wyświetlic tak utworzony obiekt należy użyc metody open
:
?- send(@demo, open).
send można również dekomponując term, zatem powyższy przykład można zapisać jako:
?- send(@demo, append, text_item(nazwa)).
zatem kolejne argumenty send licząc od 3-go będą argumentami metody append.
XPCE definiuje kilka standardowych obiektów m.in. @display oraz @prolog. @display reprezentuje ekran. @prolog jest obiektem reprezentującym maszynę wnioskującą. Dowolny predykat zdefiniowany w Prologu jest metodą, w nomenkleaturze XPCE. Zatem za pomocą send można uruchomic np. write/1:
?- send(@prolog, write('hello')).
get/3 (get(+Receiver, +Selector(+Argument…), -Result)) umożliwia uzyskanie informacji o stanie obiektu. Np. aby dowiedzieć się jaka jest szerokość obiektu:
?- get(@demo,width,X)
albo o wartości wpisanej do pola tekstowego (metoda member
wyszuka wlaściwy obiekt, po nazwie, jaka była uzyta do jego utworzenia w tym przypadku nazwa
):
?- get(@demo, member(nazwa), ObiektTekstowy), get(ObiektTekstowy, selection, ToCoUzytkownikWpisal).
Biorąc pod uwagę poniższy program:
:- new(@demo, dialog('Okno Testowe')), new(@txt,text_item('to Jest tekst:')), send(@demo,append(@txt)), send(@demo,open).
Zapytanie:
?- get(@txt,selection,X).
uzgodni z szukaną X
wartość wprowadzoną przez użytkownika.
Poniższe zapytanie uzgodni szerokość ekranu z szukaną X:
?- get(@display,width,X).
Aby zaprogramować zdarzenie związane z akcją użytkownika nalezy skorzystać z uśpionego send.
Poniższy kod utworzy okno o nazwie 'dialogowe' oraz przycisk 'nacisnij'. Po nacisnięciu przycisku na standardowym wyjściu pojawi się napiś 'au! nie naciskaj'.
?- new(@okno,dialog(dialogowe)), new(@but,button(nacisnij,message(@prolog,write,'au! nie naciskaj!\n'))), send(@okno,append,@but), send(@okno,open).
albo w krótszej wersji:
?- new(@okno,dialog(dialogowe)), send(@okno,append(button(nacisnij,message(@prolog,write,'au! nie naciskaj!\n')))), send(@okno,open).
wypisz(X):- new(Okno,dialog(wpisales)), send(Okno,append(text(X))), send(Okno,open). ui:- new(Okno,dialog(dialogowe)), send(Okno,append(new(Txt,text_item(pole_tekstowe)))), send(Okno,append(button(nacisnij,message(@prolog,wypisz,Txt?selection)))), send(Okno,open). :- ui.
W 9 lini występuje tzw. selektor. Pozwala on na wybranie określonej własności obiektu, która ma być przekazana.
W tym przypadku jest to wartość selection
pola tekstowego (szukana Txt
), czyli tekst wpisany w pole przez użytkownika.
Uwaga: Wszystkie referencje do obiektów (rezultaty predykatu new/2) w powyższym przykładzie tworzone są automatycznie (nie są to named references), nie trzeba stosować free/2, niszczeniem obiektów zajmie się garbage collector.
Okno modalne jest to zwykle okno dialogowe, które blokuje wykonanie programu do czasu, aż użytkownik wprowadzi dane.
Aby skorzystać z mechanizmu blokowania należy użyć metod: confirm
– do wyświetlenia okna (zablokowania wykonania programu), oraz return
do odblokowania.
zapytaj(Nazwa) :- new(D, dialog('Podaj nazwe')), send(D, append, new(TI, text_item(nazwa, ''))), send(D, append, button(ok, message(D, return, TI?selection))), % jeżeli przycisk nacisniety, odblokuj program send(D, append, button(porzuc, message(D, return, % jeżeli przycisk nacisniety, odblokuj program @nil))), send(D, default_button, ok), % Ok: domyslny przycisk get(D, confirm, Odpowiedz), % wyswietlenie okna, zablokowanie wykonania programu send(D, destroy), % analogiczne jak free(D) Odpowiedz \== @nil, % uzytkonik nacisnal 'porzuc' Nazwa = Odpowiedz.
Zatem wykonując zapytanie:
?- zapytaj(X).
zostanie wyświetlone okno dialogowe, gdy użytkownik wprowadzi nazwę i potwierdzi naciśnięciem przycisku ok
wprowadzona nazwa zostanie uzgodniona z szukaną X.
XPCE umożliwia wyświetlanie i manipulacje obiektów graficznych takich jak: strzałki, krzywe bezier, mapy bitowe, prostokąty, okręgi, elipsy, łuki, linie, łamane, oraz tekst.
Do wyświetlania obiektów graficznych często wykorzystywana jest klasa window
albo picture
(dodaje suwaki).
Przykładowo:
?- new(@p, picture('Demo Picture')), send(@p, open). ?- send(@p, display, new(@bo, box(100,100))). ?- send(@p, display, new(@ci, circle(50)), point(25,25)). ?- send(@p, display, new(@bm, bitmap('32x32/books.xpm')), point(100,100)). ?- send(@p, display, new(@tx, text('Hello')), point(120, 50)). ?- send(@p, display, new(@bz, bezier_curve(point(50,100), point(120,132), point(50, 160), point(120, 200)))).
Modyfikacje obiektów:
?- send(@bo, radius, 10). ?- send(@ci, fill_pattern, colour(orange)). ?- send(@tx, font, font(times, bold, 18)). ?- send(@bz, arrows, both).
Obiekty graficzne można ze sobą połączyć tworząc grupę obiektów (obiekt złożony) i wykonywać transformacje (zmiana koloru, położenia etc.) na całej grupie np:
?- new(@ic, device), send(@ic, display, bitmap('happy.bm')), send(@ic, display, text('Happy'), point(0, 64)), send(@p, display, @ic, point(250, 20)).
Następnie można przesunąć całą grupę:
?- send(@ic,x,100), send(@ic,y,120).
Obiekty również można ze sobą połączyć, tak aby modyfikacja jednego obiektu pociągała za sobą modyfikację innego. Przykład znajduje się w następnej sekcji.
Poniższy przykład umożliwia połączenie zdarzenia polegającego na przesunięciu obiektu mysza (przytrzymując lewy przycisk) z obiektem identyfikowanym przez @ic.
?- send(@ic, recogniser, move_gesture(left)).
Albo co ma się stać po dwukrotnym kliknięciu obiektu @ci:
?- send(@ci, recogniser, click_gesture(left, '', double, message(@pce, write_ln, hello))).
Poniższy przykład ilustruje tworzenie i manipulację obiektów połączonych.
:- pce_global(@in_out_link, make_in_out_link). make_in_out_link(L) :- new(L, link(in, out, line(arrows := second))). linked_box_demo :- new(P, picture('Linked Box demo')), send(P, open), send(P, display, new(B1, box(50,50)), point(20,20)), send(P, display, new(B2, box(25,25)), point(100,100)), send(B1, handle, handle(w, h/2, in)), send(B2, handle, handle(w/2, 0, out)), send_list([B1, B2], recogniser, new(move_gesture(left))), send(B1, connect, B2, @in_out_link).
Przetestuj poniższy program 1). send_list
działa podobnie jak send
przu czym uruchamia wskazaną metodę z argumentami będącymi kolejnymi elementami listy. Pojedynczy predykat send_list
zastępuje wiele predykatów send
.
:-dynamic(employee/2). ask_employee :- new(Dialog, dialog('Define employee')), send_list(Dialog, append, [ new(N1, text_item(first_name)), new(N2, text_item(family_name)), new(S, new(S, menu(sex))), new(A, int_item(age, low := 18, high := 65)), new(D, menu(department, cycle)), button(cancel, message(Dialog, destroy)), button(enter, and(message(@prolog, assert_employee, N1?selection, N2?selection, S?selection, A?selection, D?selection), message(Dialog, destroy))) ]), send_list(S, append, [male, female]), send_list(D, append, [research, development, marketing]), send(Dialog, default_button, enter), send(Dialog, open). assert_employee(FirstName, FamilyName, Sex, Age, Dept) :- assert(employee(FirstName, FamilyName, Sex, Age, Dept)).
Rozbuduj program z Ćwiczenia 1.
Dopisz redykat show_employees/0
umożliwiający przeglądanie danych pochodzących z employee/5
.
W celu znalezienia odpowiednich obiektów wyświetlających dane tekstowe zobacz: Programming in XPCE.
Dany jest następujący kod uzupełniający przykłady z rodziny wzięte:
go :- kobieta(X), wyswietl(X). go.
Zaprogramuj predykat wyświetl, tak aby wyświetlał w oknie dialogowym 1-szy argument oraz dwa przycski: Koniec
, Nastepny
.
Okno dilogowe powinno blokować wykonanie programu, aż do naciśnięcia jednego z przycisków.
Przy naciśnięciu Nastepny
predykat zwraca fałsz wymuszając nawrót, dla Koniec
zwraca prawdę.
Korzystając z predykatów określających koligacje rodzinne z prolog lab 1 oraz z XPCE napisz predykat generujący graf będący drzewem genealogicznym określającym potomków wskazanej osoby:
rysuj_potomek(+Kto,+Rodzic,+Kobieta,+Mezczyzna)
gdzie Kto to osoba, dla której zostanie wygenerowane drzewo potomków, pozostałe argumenty są nazwami predykatów określającymi odpowiednio kto jest czyim rodzicem, kto jest kobietą, kto jest mężczyzną. Przykładowe wywołanie:
rysuj_potomek(franek,rodzic/2,kobieta/1,mezczyzna/1)
Wygeneruje drzewo genealogiczne potomków dla osoby franek, przy czym rodzic/2, kobieta/1, mezczyzna/1 są zdefinowanymi predykatami, których klauzule przechowują informacje o koligacjach rodzinnych.
Podpowiedź: najpierw napisz predykat znajdujący potomków, potem dodaj generację danych dla GraphViz, następnie wizualizację.
Napisz predykat:
rysuj_drzewo(+Kto,+Rodzic,+Kobieta,+Meżczyzna)
rysujący kompletne drzewo dla wskazanej osoby.
Przykład drzewa genealogicznego:
TBD
Tu studenci mogą wpisywać swoje uwagi.
— Grzegorz J. Nalepa 2009/05/06 09:13
Wg. mnie trochę za dużo materiału - mi się udało na zajęciach zrobić tylko 3 pierwsze ćwiczenia.
— Tomek Kozera 2009/05/16 21:01
„Jeżeli referenca obiektu nie” Literówka - referencja powinno być
„Referencje może być utworzona przez new:” - jak wyżej
„działa podobnie jak send przu czym” - znowu literówka ;)
—Anonim „send można również dekomponując term, zatem powyższy przykład można zapisać jako:” – jakiś błąd logiczny, brakuje co najmniej jednego słowa („send można użyć(?)”) – Kamil Kuduk