DialogForm Validation(对话框及表单的确认)

From wiki.visual-prolog.com

Revision as of 02:05, 5 July 2015 by Yiding (talk | contribs)

(以下内容,译自Category:Tutorials中的DialogForm Validation。更多内容可以参看Category:Tutorials部分中文译文Category:Chinese。)


用户按了对话框中的OK按钮后,就意味着将要出现某件事情。不过只有对话框或表单中的数据有效时,事情才会出现。对话框和表单必须经过 有效性确认。本专题将描述由PFC GUI支持的有效性确认机制,还要介绍如何使用校验控件integerControlrealControl 及如何确认对话框表单中其它的控件。

本文将演示如何确认在对话框或表单中的控件。首先,要介绍有效性确认的概念。我们会看到integerControl和realControl是如何使用有效性确认概念的。接着,我们要考虑在容器控件中的有效性确认问题。最后,来看几个常用控件的有效性确认,这些控件有:editControl、listBox、新建用户控件。

下载 本文使用的示例工程源文件:


有效性确认的概念

有效性确认的概念基础思想是:“控件值应该是有效的”。有效性的确认发生在对话框或表单中按动OK按钮时,但确认工作也可以由程序安排。

控件负责声明自己的内容是有效的,因此,可以对控件设置有效性确认响应器。

对话框或表单作有效性确认时,是逐个控件依次进行的,但如果结果导致

contentsInvalid(Source, FocusControl, ErrorMessage)

则确认工作就终止了。

integerControl和realControl中的有效性确认

我们来创建一个表单,并用类integerControl和realControl加入两个 custom controls (用户控件)。可以在提供的示例工程integerControlAndRealControl看到相应的表单结果。

示例生成的代码如下:

integerControl_ctl := integercontrol::new(This),
integerControl_ctl:setPosition(92, 4),
integerControl_ctl:setSize(60,12),
realControl_ctl := realcontrol::new(This),
realControl_ctl:setPosition(92, 20),
realControl_ctl:setSize(60,12),

还需要加上对 integerControlAndRealControl 表单的调用:

predicates
    onFileIntegercontrolRealcontrol : window::menuItemListener.
clauses
    onFileIntegercontrolRealcontrol(Source, _MenuTag) :-
        Form = integerControlAndRealControl::new(Source),
        Form:show().

运行这个工程,如果输入了非整数值,将会看到一个说明错误的消息框。

我们也可以加入 onOK 响应器来获取确认后的值:

predicates
    onOk : button::clickResponder.
clauses
    onOk(_) = button::defaultAction() :-
        Integer = integerControl_ctl:getInteger(),
        Real = realControl_ctl:getReal(),
        stdIO::write("Integer value = ",Integer, "\n"),
        stdIO::write("Real value = ",Real, "\n").

要注意,如果有效性确认不成功,是不会调用 onOK 响应器的,而且该响应器的调用是发生在所有确认谓词之后。

我们来看一下源文件 \pfc\gui\controls\integerControl.pro ,看看有效性确认是如何实现的。

clauses
    new() :-
        editControl::new(),
        addValidateResponder(onIntValidate).
 
predicates
    onIntValidate : validateResponder.
clauses
    onIntValidate(_) = contentsInvalid(This,This, ErrorMessage) :-
        string(ErrorMessage) = checkContent(getText()),
        !.
    onIntValidate(_) = contentsOk.

也就是说,如果局部谓词checkContent认为文本内容是 integer 则确认成功。

上面我们说过,确认工作也可以强制程序安排进行。可以这样加一个按钮 TryValidation 及相应的代码:

predicates
    onTryValidation : button::clickResponder.
clauses
    onTryValidation(_Source) = button::defaultAction() :-
        tryValidateWithErrorDialog(),
        !,
        stdIO::write("All controls are valid\n").
    onTryValidation(_Source) = button::defaultAction().

容器控件中的有效性确认

考查容器控件中的有效性确认,我们先来创建一个这样的控件:在工程中创建一个新的控件fromTo,再在其中加入两个integerControl控件。

考虑到只有当From的值小于To的值控件fromTo才是有效的,因此可以这样设置fromTo控件的有效性确认响应器:

predicates
    validateFromTo : control::validateResponder.
clauses
    validateFromTo (Source) = control::contentsInvalid(Source,from_ctl,
      "From value must be less than To value") :-
        from_ctl:getInteger() >= to_ctl:getInteger(),
        !.
    validateFromTo (_) = control::contentsOk.

请注意,如果有效性确认不成功,控件 from_ctl 会得到焦点。

常用控件的有效性确认

我们在工程中创建一个新控件 myControl ,再创建一个表单并在其中添加三个控件:

  • edit 控件;
  • listbox 控件;
  • myControl 类的用户控件。

可以在提供的示例usualControls中看到表单的结果。

初始化代码中包含了响应器的设置及对三个控件的初始化内容:

clauses
    new(Parent) :-
        formWindow::new(Parent),
        generatedInitialize(),
        edit_ctl:addValidateResponder(validateEditCtl),
        listbox_ctl:addList(["First","Second","Third"]),
        listbox_ctl:addValidateResponder(validateListBox).

有效性确认响应器是这样的:

predicates
    validateEditCtl : control::validateResponder.
clauses
    validateEditCtl(_) = control::contentsOk :-
        "OK" = edit_ctl:getText(),
        !.
    validateEditCtl(Source) = control::contentsInvalid(
          Source, Source,
          "Edit control expects to have the text 'OK'").
 
predicates
    validateListBox : control::validateResponder.
clauses
    validateListBox(Source) = control::contentsInvalid(
          Source,Source,
          "Selection of the first row is not allowed") :-
        0 = listbox_ctl:tryGetSelectedIndex(),
        !.
    validateListBox(_) = control::contentsOk().
 
predicates
    validateMyControl : control::validateResponder.
clauses
    validateMyControl(Source) = control::contentsInvalid(
          Source,Source,
          string::concat("A marker in the ",Missed,
            " part is mandatory")) :-
        Missed = toString(isMandatoryMarkNotActive(
          mandatoryMark, activatedMark)),
        !.
    validateMyControl(_) = control::contentsOk().

可以看到,对控件的有效性确认可以有各种不同的方法。

参考