Howto read from a prolog predicate in XPCE
I have the following simple prolog predicate:
tst(In, Out) :- Out = In.
The idea is clear, simply return the same in "Out" as was received in "In". Ok, now I want to include this prolog predicate in a XPCE program. I have created a window and added a button that should call this prolog predicate, then display the value returned in "Out". I thought achieving this task would be as simple as
send(Dialog, append(button(execute_command, and(
message(@pr开发者_JS百科olog, tst, InputText?selection, prolog(Output)),
message(@prolog, write, prolog(Output)),
message(@prolog, nl))))),
but unfortunately, that does not work exactly as I want it to. Instead it now prints out the internal reference of "Out". For example:
?- _L204
Any ideas what is my mistake here?
From Prolog setting values in PCE is easy,using send/3, or send/4. So one way around this is to have the Prolog predicate invoke a method that sets a value on a PCE object.
Objects can contain other objects, and have class and instance variables in scope. All the Prolog code needs is a reference to the object: By calling the predicate with an object reference, the predicate can invoke an appropriate method to communicate a value.
Here is some code that creates an object based on the dialog class. A button in the object, when pressed, will call a predicate (similar to the one in this question) that will create a value based on the one passed-in, then set that value in an instance variable of the dialog. It will also put the value in the text_ item control.
This program source is textfield.pl and can be run with
swipl -s textfield.pl -g run
Default Text:
User Input
Text updated by the program via messages sent to the GUI from a predicate invoked by the pushbutton:
The demo class:
:- use_module(library(pce)).
:- pce_begin_class(demo, dialog).
/* Instance variables*
name, type, access, description */
variable(result, name*, get, "Result from Prolog Callback").
initialise(Demo) :->
"Create something that get/4 and send/3 can work with."::
send(Demo, send_super, initialise, 'Demo'),
send(Demo, append, new(InputText, text_item(input, 'Demo Text'))),
send(Demo, append,
button(execute_command,
and(message(@prolog,doIt, Demo,InputText?selection),
message(@prolog,printIt,Demo)))).
:- pce_end_class.
Code called by the pushbutton:
%%% Create a new value based on the input string
%%% Write the new value back to the 'input' member of the
%%% 'demo' object. Also put the value int the 'result' slot.
doIt(Demo,Word) :-
concat_atom(['*** ' , Word, ' *** '] ,WordGotDid),
format("doIt: Setting result: ~w...~n", [WordGotDid]),
get(Demo,member,input,InputText),
send(InputText,selection,WordGotDid),
send(Demo,slot,result,WordGotDid).
%%% Read and display the 'result' slot.
printIt(Demo) :-
get(Demo,slot,result,Result),
write('\nResult: "'),
write(Result),
write('"\n').
Main program:
%%% Create an object that has fields that can be mutated.
run :- new(Demo,demo),
send(Demo,open).
After looking at the demos and coding this one, this is my opinion which could change, once I finish studying XPCE: Even though, it is somewhat possible to program in Prolog via messages from XPCE, looking at the demo code, this isn't the way it's done. The programming is done in Prolog or some other language and with Prolog as the glue, while XPCE is mostly a passive GUI, sort of like HTML forms. The program creates XPCE objects, changes their state and reads values from them. XPCE doesn't normally write to the program other than some small GUI-related messaging; but even that is usually done in the methods of XPCE objects.
精彩评论