Aller au contenu

Messages recommandés

Posté(e)

Bonjour à tous,

 

une fois de plus je viens solliciter votre connaissance du LISP.

Je me suis attaqué aux boites de dialogue et j'ai du mal à m'en sortir.

Ci dessous la défintion de la boite de dialogue que j'ai créé et le LISP qui la pilote.

Le but est d'obtenir l'équivalent de la commande française. Seulement j'obtiens (0 0) au lieu de la traduction de la commande.

Pourquoi et qu'est ce que (0 0)?

 

Merci.

 

TEST : dialog {
label = "Traduction commande";
: edit_box {
key = "Edit";
label = "Français : ";
edit_width = 20;
value = "";
}
: row {
: button {
   key = "accept";
   label = "OK";
   is_default = true;
 }
 : button {
   key = "cancel";
   label = "annuler";
   is_default = false;
   is_cancel = true;
 }
 }
 } 

 

(defun c:NOM ()
 (setq Id (load_dialog "NOM.dcl"))
 (new_dialog "TEST" Id)
 (getcname (get_tile "Edit"))
 (start_dialog)
 (done_dialog)
) 

 

[Edité le 26/3/2011 par Bortch59]

Posté(e)

Salut,

 

Pourquoi et qu'est ce que (0 0)?

 

Une routine LISP retourne toujours le résultat de l'évaluation de la dernière expression.

Ici, la dernière expression est (done_dialog) et done_dialog retourne un point 2d correspondant (d'après l'aide) à la position de la boite de dialogue au moment où elle se ferme.

 

Ton code ne peut pas retourner le résultat de getcname dans la mesure où la valeur retournée n'est affectée à aucune variable et où il n'y a aucune action affectée aux contrôle de la boite.

 

Il faut, au minimum définir une une réaction (callback) au bouton OK. Pour ce faire on utilise la fonction action_tile qui requiert 2 arguments : la clé du contrôle (tile) et une chaîne contenant les expression LISP à évaluer. C'est dans cette réaction qu'on met les appels à done_dialog.

 

Par ailleurs, il est d'usage d'utiliser une expression (if ...) avec new_dialog pour éviter une erreur au cas où il retournerait nil.

Il faut aussi décharger la boite de dialogue à la fin du code avec unload_dialog.

 

Voilà donc ce que pourrait être ton code dans sa version la plus sommaire :

 

(defun c:NOM (/ id name)
 (setq Id (load_dialog "NOM.dcl"))
 (if (new_dialog "TEST" Id)
   (progn
     (action_tile
"accept"
"(print (getcname (get_tile \"Edit\")))
(done_dialog)")
     (start_dialog)
   )
 )
 (unload_dialog id)
 (princ)
)

 

 

Du côté du code DCL, il existe un contrôle ok_cancel qui évite de définir une rangée avec deux boutons.

 

Voilà donc comment j'aurais écrit le DCL :

TEST : dialog {
 label = "Traduction commande";
 initial_focus = "Edit";
 : edit_box {
   key = "Edit";
   label = "Français : ";
   edit_width = 20;
   allow_accept = true;
 }
 ok_cancel;
}

 

Et un manière plus explicite d'écrire le LISP en utilisant une action par contrôle. Dans ce code, on récupère dans la valeur retournée par start_dialog qui correspond à l'argument passé à done_dialog suivant le bouton cliqué.

(defun c:NOM (/ id name status)
 (setq id (load_dialog "NOM.dcl"))
 (if (not (new_dialog "TEST" Id))
   (exit)
 )
 (action_tile "Edit" "(setq name (getcname $value))")
 (action_tile "accept" "(done_dialog 1)")
 (action_tile "cancel" "(done_dialog 0)")
 (setq status (start_dialog))
 (unload_dialog id)
 (if (= 1 status)
   (if	name
     (alert name)
     (alert "Commande inconue")
   )
   (alert "Fonction annulée")
 )
 (princ)
)

 

 

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Salut,

 

encore une fois une explication très claire, merci.

J'ai encore la dernière partie à plancher car je n'ai pas tout saisi.

 

Je vais essayer de mettre tout ça en pratique sur mon code PAS.

 

Un autre point:

si l'on doit saisir un point par pointage à l'écran, quelle est la bonne méthode?

 

Une fonction permet de rervenir à la boite de dialogue ou faut-il demander à saisir le point après (start_dialog)?

 

Posté(e)

Salut,

 

Avec DCL on ne peut définir que des boites de dialogue dites "modales", c'est à dire qui empêche l'accès à AutoCAD quand elles sont visibles (contrairement aux boites non modales (modeless) comme les palettes).

 

Pour pouvoir accéder à AutoCAD, pour spécifier un point à l'écran par exemple, il va donc falloir fermer temporairement la boite de dialogue.

Pour se faire, on utilise une boucle avec la valeur passée à done_dialog qui est retournée par start_dialog.

 

start_dialog retourne une valeur (entier) qui renseigne sur la façon dont a été fermée la boite de dialogue, à savoir la valeur passée à done_dialog ou 0 si done_dialog a été appelée sans argument.

 

Un appel à done_dialog ferme la boite de dialogue. done_dialog peut-être appelé sans argument ou avec un argument (nombre entier).

Appeler done_dialog avec un argument permet à l'application de savoir comment s'est fermée la boite de dialogue en récupérant la valeur retournée par start_dialog.

On utilise généralement 0 (cancel) pour annuler et 1 pour OK (accept), c'est ce que j'ai fait dans le dernier exemple ci-dessus.

 

On peut aussi passer à done_dialog des valeurs supérieures à 1, c'est alors à l'application de gérer ce qui doit se passer dans ces cas.

 

C'est cette dernière méthode qu'on utilise pour fermer temporairement une boite de dialogue.

On affecte une valeur initiale supérieure à 1 à une variable (nommée status dans les exemples) et on utilise une boucle (while ...) qui ouvre la boite de dialogue tant que status est supérieur à 1.

C'est dans les expression action_tile des différents contrôles qu'on passe une valeur à done_dialog : 0 pour cancel et 1 pour accept ferment la boite définitivement (on sort de la boucle), toute valeur supérieure la ferme temporairement (on reste dans la boucle).

 

Dans le code, à l'intérieur de la boucle (while ...) on récupère la manière dont a été fermée la boite de dialogue en affectant la valeur retournée par start_dialog à status.

On peut ainsi évaluer cette valeur et effectuer les actions voulues en fonction de cette valeur.

 

Exemple pour sélectionner un point :

 

Le code DCL

getpoint :dialog{
 label="GetPoint";
 :boxed_column{
   label="Sélectionner un point";
   :row{
     :row{ 
       :button{
         label = "Choisir le point           key = "hide";
         alignment = centered;
       }
     }
     :column{
       :edit_box{
         label="X";
         key="x_coord";
         fixed_width=true;
         allow_accept=true;
       }
       :edit_box{
         label="Y";
         key="y_coord";
         fixed_width=true;
         allow_accept=true;
       }
       :edit_box{
         label="Z";
         key="z_coord";
         fixed_width=true;
         allow_accept=true;
       }
     }
   }
 }
 ok_cancel;
} 

 

Le LISP

(defun c:getpoint (/ id status pt)
 ;; initialisation et chargement du DCL
 (setq	pt     '(0. 0. 0.)
id     (load_dialog "GetPoint.dcl")
status 2
 )
 
 ;; boucle tant que status est supérieur  à 1
 (while (    (if	(not (new_dialog "getpoint" id))
     (exit)
   )
   
   ;; affectation des valeurs courantes aux contrôles edit_box
   (set_tile "x_coord" (rtos (car pt)))
   (set_tile "y_coord" (rtos (cadr pt)))
   (set_tile "z_coord" (rtos (caddr pt)))

   ;; réactions à effectuer pour les différents contrôles
   (action_tile
     "x_coord"
     "(if (distof $value)
(setq pt (list (distof $value) (cadr pt) (caddr pt)))
(progn
  (alert \"Nécessite un nombre valide\")
  (set_tile $key (rtos (car pt)))
  (mode_tile \"x_coord\" 2)
)
     )"
   )
   (action_tile
     "y_coord"
     "(if (distof $value)
(setq pt (list (car pt) (distof $value) (caddr pt)))
(progn
  (alert \"Nécessite un nombre valide\")
  (set_tile $key (rtos (cadr pt)))
  (mode_tile \"y_coord\" 2)
)
     )"
   )
   (action_tile
     "z_coord"
     "(if (distof $value)
(setq pt (list (car pt) (cadr pt) (distof $value)))
(progn
  (alert \"Nécessite un nombre valide\")
  (set_tile $key (rtos (caddr pt)))
  (mode_tile \"z_coord\" 2)
)
     )"
   )
   (action_tile "hide" "(done_dialog 2)")
   (action_tile "accept" "(done_dialog 1)")
   (action_tile "cancel" "(done_dialog 0)")

   ;; récupération de la valeur passée à done_dialog
   (setq status (start_dialog))

   ;; action à effectuer si cette valeur est égale à 2
   (if	(= status 2)
     (if (setq p (getpoint "\nSpécifiez un point: "))
(setq pt p)
     )
   )
 )

 ;; déchargement du DCL
 (unload_dialog id)

 ;; Action en fonction de la valeur de status (0 ou 1)
 (if (= status 1)
   (alert (strcat (rtos (car pt)) ", " (rtos (cadr pt)) ", " (rtos (caddr pt))))
   (alert "Fonction annulée")
   )
 (princ)
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Salut,

 

Wahou! Là j'ai de quoi potasser...

 

Pour être honnête, je n'ai pas tout saisi mais je ne désespère pas. Il faut que je décortique tout ça.

 

 

  • 1 mois après...
Posté(e)

Salut,

 

je me rend compte que je n'ai rien compris (du moins pas tout).

 

j'ai écrit ce petit code qui fait une simple addition et je n'obtiens que 0.0 comme résultat car mes variables sont vides...

Je n'ai pas compris comment on transmet les valeurs de la boite aux variables.

 

 

la boite:

 somme : dialog {
label = "somme";
initial_focus = "Edit";
: edit_box {
key = "a";
label = "nb1 : ";
edit_width = 20;
allow_accept = true;
}
: edit_box {
key = "b";
label = "nb2 : ";
edit_width = 20;
allow_accept = true;
}
ok_cancel;
 }

 

le code:

 (defun c:test ()
      (setq id (load_dialog "test_bdd.dcl"))

 (new_dialog "somme" id)

 (setq	a (atof (get_tile "a"))
b (atof (get_tile "b"))
 )

 (action_tile "accept" "(print (+ a b)) (done_dialog)")
 (start_dialog)
 (unload_dialog id)
 (princ)

)

Posté(e)

Salut,

 

Au moment où tu fais :

  (setq	a (atof (get_tile "a"))
b (atof (get_tile "b"))
 )

La boite de dialogue s'initialise donc les cases ne contiennent qu'une chaîne vide ("")

 

En mettant cette expression dans le (action_tile "accept" ...) tu récupèreras les valeurs au moment où l'utilisateur fait OK.

Mais attention, en l'état, rien ne t'assure que les cases ont été remplies ni que les caînes sont convertibles en nombre avec atof.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Salut,

 

effectivement dans (action_tile) ça fonctionne quand j'écris ça:

 

 (defun c:test ()
 (setq id (load_dialog "test_bdd.dcl"))

 (new_dialog "somme" id)

 (action_tile
   "accept"
   "(print (+ (atof (get_tile \"a\")) (atof (get_tile \"b\")))) (done_dialog)"
 )
 (start_dialog)
 (unload_dialog id)
 (princ)
)

 

mais pas ça

 

 (defun c:test ()
 (setq id (load_dialog "test_bdd.dcl"))

 (new_dialog "somme" id)

 (action_tile
   "accept"
   "
   (setq a (atof (get_tile \"a\"))
         b (atof (get_tile \"b\")))
   (print (+ a b)) (done_dialog)"
 )
 (start_dialog)
 (unload_dialog id)
 (princ)
)

 

Le premier me renvoie bien la somme des deux nombres mais le deuxième ne me renvoie rien du tout.

Posté(e)

Salut,

 

Je ne vois pas d'erreur dans ton code, juste une absence totale de contrôle des valeurs entrées.

 

Donc, si les valeurs entrées dans les cases d'édition représentent bien des nombres (autrement dit, sont convertibles en nombre avec atof), ça devrait fonctionner.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité