JESS - файл .CLP не выполняется должным образом с помощью ActionListener

Я пытаюсь выполнить файл JESS .clp одним нажатием кнопки, используя Rete.batch() в Java. .clp, который я пытаюсь выполнить, похож на пример помощника по ремонту компьютеров в примерах Jess — с графическим интерфейсом. Когда я запускаю файл внутри ActionListener кнопки, я получаю кадр, но с пустым окном. Однако, если я выполняю файл в основном, не помещая его в ActionListeners, .clp работает нормально (фрейм появляется с содержимым). Любая помощь приветствуется. Спасибо.

Код прослушивателя действия кнопки:

JButton btnEnterNew = new JButton("Take Test!");
        btnEnterNew.setBounds(312, 439, 250, 30);
        contentPane.add(btnEnterNew);
        btnEnterNew.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
                Rete ret = new Rete();
                try {
                  ret.batch("computer.clp");                

                } catch (JessException e) {
                    e.printStackTrace();
                }
            }
        });

Код для Computer.clp :-

   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Graphical version of PC Diagnostic Assistant from part 4 of 
;; "Jess in Action"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Import some commonly-used classes
(import javax.swing.*)
(import java.awt.*)
(import java.awt.event.*)

;; Don't clear defglobals on (reset)
(set-reset-globals FALSE)

(defglobal ?*crlf* = "
")

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Question and answer templates

(deftemplate question
  (slot text)
  (slot type)
  (multislot valid)
  (slot ident))

(deftemplate answer
  (slot ident)
  (slot text))

(do-backward-chaining answer)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Module trigger

(defmodule trigger)

(defrule trigger::supply-answers
  (declare (auto-focus TRUE))
  (MAIN::need-answer (ident ?id))
  (not (MAIN::answer (ident ?id)))
  (not (MAIN::ask ?))
  =>
  (assert (MAIN::ask ?id))
  (return))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; power rules

(defrule MAIN::not-plugged-in
  (declare (auto-focus TRUE))
  (answer (ident sound) (text no))
  (answer (ident plugged-in) (text no))
  =>
  (recommend-action "plug in the computer")
  (halt))

(defrule MAIN::power-supply-broken
  (declare (auto-focus TRUE))
  (answer (ident sound) (text no))
  (answer (ident plugged-in) (text yes))
  =>
  (recommend-action "repair or replace power supply")
  (halt))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; sound rules

(defrule MAIN::check-ram
  (declare (auto-focus TRUE))
  (answer (ident sound) (text yes))
  (answer (ident seek) (text no))
  (answer (ident does-beep) (text yes))
  (answer (ident how-many-beeps) (text ?t))
  (test (< (integer ?t) 3))
  =>
  (assert (check loose-ram))
  (recommend-action "check for loose RAM, then continue"))

(defrule MAIN::unknown-sound
  (declare (auto-focus TRUE))
  (answer (ident sound) (text yes))
  (answer (ident seek) (text no))
  (answer (ident does-beep) (text no))
  =>
  (recommend-action "consult a human expert")
  (halt))

(defrule MAIN::motherboard-or-keyboard
  (declare (auto-focus TRUE))
  (answer (ident sound) (text yes))
  (answer (ident seek) (text no))
  (answer (ident does-beep) (text yes))
  (answer (ident how-many-beeps) (text ?t))
  (test (>= (integer ?t) 3))
  =>
  (recommend-action "check keyboard and motherboard")
  (halt))

(defrule MAIN::no-boot-start
  (declare (auto-focus TRUE))
  (answer (ident sound) (text yes))
  (answer (ident seek) (text yes))
  (answer (ident boot-begins) (text no))
  =>
  (recommend-action "check keyboard, RAM, motherboard, and power supply")
  (halt))

(defrule MAIN::boot-start
  (declare (auto-focus TRUE))
  (answer (ident sound) (text yes))
  (answer (ident seek) (text yes))
  (answer (ident boot-begins) (text yes))
  =>
  (recommend-action "consult a software expert")
  (halt))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; RAM rules

(defrule MAIN::loose-ram
  (declare (auto-focus TRUE))
  (check loose-ram)
  (answer (ident loose-ram) (text yes))
  =>
  (recommend-action "remove and reseat memory modules")
  (halt))

(defrule MAIN::faulty-ram
  (declare (auto-focus TRUE))
  (check loose-ram)
  (answer (ident loose-ram) (text no))
  =>
  (recommend-action "replace memory modules one by one and retest")
  (halt))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; domain rules

(defrule MAIN::right-architecture
  (declare (auto-focus TRUE))
  (explicit (answer (ident hardware) (text ~x86)))
  =>
  (recommend-action "consult a human expert")
  (halt))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Results output

(deffunction recommend-action (?action)
  "Give final instructions to the user"
  (call JOptionPane showMessageDialog ?*frame*
        (str-cat "I recommend that you " ?action)
        "Recommendation"
        (get-member JOptionPane INFORMATION_MESSAGE)))

(defadvice before halt (?*qfield* setText "Close window to exit"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Module ask

(defmodule ask)

(deffunction ask-user (?question ?type ?valid)
  "Set up the GUI to ask a question"
  (?*qfield* setText ?question)
  (?*apanel* removeAll)
  (if (eq ?type multi) then
    (?*apanel* add ?*acombo*)
    (?*apanel* add ?*acombo-ok*)
    (?*acombo* removeAllItems)
    (foreach ?item ?valid
             (?*acombo* addItem ?item))
    else
    (?*apanel* add ?*afield*)
    (?*apanel* add ?*afield-ok*)
    (?*afield* setText ""))
  (?*apanel* validate)
  (?*apanel* repaint))

(deffunction is-of-type (?answer ?type ?valid)
  "Check that the answer has the right form"
  (if (eq ?type multi) then
    (foreach ?item ?valid
             (if (eq (sym-cat ?answer) (sym-cat ?item)) then
               (return TRUE)))
    (return FALSE))

  (if (eq ?type number) then
    (return (is-a-number ?answer)))

  ;; plain text
  (return (> (str-length ?answer) 0)))

(deffunction is-a-number (?value)
  (try
   (integer ?value)
   (return TRUE)
   catch 
   (return FALSE)))

(defrule ask::ask-question-by-id
  "Given the identifier of a question, ask it"
  (declare (auto-focus TRUE))
  (MAIN::question (ident ?id) (text ?text) (valid $?valid) (type ?type))
  (not (MAIN::answer (ident ?id)))
  (MAIN::ask ?id)
  =>
  (ask-user ?text ?type ?valid)
  (engine))

(defrule ask::collect-user-input
  "Check an answer returned from the GUI, and optionally return it"
  (declare (auto-focus TRUE))
  (MAIN::question (ident ?id) (text ?text) (type ?type) (valid $?valid))
  (not (MAIN::answer (ident ?id)))
  ?user <- (user-input ?input)
  ?ask <- (MAIN::ask ?id)
  =>
  (if (is-of-type ?input ?type ?valid) then
    (retract ?ask ?user)
    (assert (MAIN::answer (ident ?id) (text ?input)))
    (return)
    else
    (retract ?ask ?user)
    (assert (MAIN::ask ?id))))

;; Main window
(defglobal ?*frame* = (new JFrame "Diagnostic Assistant"))
(?*frame* setDefaultCloseOperation (get-member JFrame EXIT_ON_CLOSE))
(?*frame* setSize 520 140)
(?*frame* setVisible TRUE)

;; Question field
(defglobal ?*qfield* = (new JTextArea 5 40))
(bind ?scroll (new JScrollPane ?*qfield*))
((?*frame* getContentPane) add ?scroll)
(?*qfield* setText "Please wait...")

;; Answer area
(defglobal ?*apanel* = (new JPanel))
(defglobal ?*afield* = (new JTextField 40))
(defglobal ?*afield-ok* = (new JButton OK))

(defglobal ?*acombo* = (new JComboBox (create$ "yes" "no")))
(defglobal ?*acombo-ok* = (new JButton OK))

(?*apanel* add ?*afield*)
(?*apanel* add ?*afield-ok*)
((?*frame* getContentPane) add ?*apanel* (get-member BorderLayout SOUTH))
(?*frame* validate)
(?*frame* repaint)

(deffunction read-input (?EVENT)
  "An event handler for the user input field"
  (assert (ask::user-input (sym-cat (?*afield* getText)))))

(bind ?handler (new jess.awt.ActionListener read-input (engine)))
(?*afield* addActionListener ?handler)
(?*afield-ok* addActionListener ?handler)

(deffunction combo-input (?EVENT)
  "An event handler for the combo box"
  (assert (ask::user-input (sym-cat (?*acombo* getSelectedItem)))))

(bind ?handler (new jess.awt.ActionListener combo-input (engine)))
(?*acombo-ok* addActionListener ?handler)

(deffacts MAIN::question-data
  (question (ident hardware) (type multi) (valid x86 Macintosh other)
            (text "What kind of hardware is it?"))
  (question (ident sound) (type multi) (valid yes no)
            (text "Does the computer make any sound?"))
  (question (ident plugged-in) (type multi) (valid yes no)
            (text "Is the computer plugged in?"))
  (question (ident seek) (type multi) (valid yes no)
            (text "Does the disk make \"seeking\" sounds?"))
  (question (ident does-beep) (type multi) (valid yes no)
            (text "Does the computer beep?"))
  (question (ident how-many-beeps) (type number) (valid)
            (text "How many times does it beep?"))
  (question (ident loose-ram) (type multi) (valid yes no)
            (text "Are any of the memory modules loose?"))
  (question (ident boot-begins) (type multi) (valid yes no)
            (text "Does the computer begin to boot?"))
  (ask hardware))


(reset)
(run-until-halt)

person DeeCode    schedule 03.05.2015    source источник
comment
Требуется полный набор кода, воспроизводящего проблему, с которой вы столкнулись. Подобное никому не помогает, и я не думаю, что смогу даже идентифицировать пример Джесс из вашего описания. (Есть такое понятие, как имя пути для идентификации файлов...)   -  person laune    schedule 03.05.2015
comment
Привет, извините за это ... добавил код. Путь правильный, и он даже выполняет файл .clp. Но содержимое внутри фрейма не видно, когда оно выполняется с помощью ActionListener. Мой поиск по этому вопросу до сих пор обнаружил, что причиной этого в следующем коде является вызов waitForActivations рядом с Engine. (defrule ask::ask-question-by-id Учитывая идентификатор вопроса, задайте его ............ (not (MAIN::answer (ident ?id))) (MAIN: :ask ?id) =› (ask-user ?text ?type ?valid) ((engine) waitForActivations )) до сих пор не смог найти обходной путь для этого...   -  person DeeCode    schedule 03.05.2015
comment
Этот код содержит ошибки. Для JCheckBox нет такого конструктора, как здесь. А как насчет тегов HTML <b> и </b>?   -  person laune    schedule 03.05.2015
comment
Извините, это просто попытка выделить это ключевое слово жирным шрифтом здесь. Пожалуйста, игнорируйте это :)   -  person DeeCode    schedule 03.05.2015
comment
Это не JCheckbox. Это JButton, добавленный в JPane.   -  person DeeCode    schedule 03.05.2015
comment
Нет ошибок в конструкторе JButton. Фактически, я упомянул в своем вопросе, что он выполняет файл .clp, как и ожидалось. Это код Джесс, который не выполняется должным образом.   -  person DeeCode    schedule 04.05.2015
comment
Когда я запускаю код файла clp, возникает ошибка `Конструктор не найден: (новый JCheckBox (create$ yes no))`.   -  person laune    schedule 04.05.2015
comment
Исправлена ​​ошибка JCheckBox в коде Jess и заменен код выше. Но проблема все еще существует, поскольку содержимое фрейма невидимо при выполнении щелчком кнопки .clp.   -  person DeeCode    schedule 04.05.2015


Ответы (1)


Вызов Rete для выполнения долго выполняющегося пакетного файла приводит к зависанию графической системы — обработчик события кнопки является обратным вызовом. Отсоедините поток для выполнения метода Rete, например.

public void actionPerformed(ActionEvent e) {
    Runnable r = new Runnable() {
        public void run() {
            Rete ret = new Rete();
            try {
                ret.batch("computer.clp");                
            } catch (JessException je) {
                je.printStackTrace();
            }           
        }
    };
    new Thread(r).start();
}
person laune    schedule 04.05.2015