broncos15 发表于 2022-7-5 17:35:07

While循环中的While循环

我有一个快速的问题,关于编写代码的最有效方式是什么,该代码将不断向用户询问源对象和目标对象。我知道如何为以下单个选择编写此代码:
我的问题是如何有效地为两个对象编写此代码(即,您将获得两个对象的错过提示或无效对象,然后在选择每个对象后,一个代码将运行,然后重复,直到用户点击escape或空格键。我已经编写了所有代码,只是这个while循环我无法正常工作。

BIGAL 发表于 2022-7-5 17:41:31

可能有2个defuns,但使用和来确认两者都符合标准。

Simon1976 发表于 2022-7-5 17:49:41

请看一下李的代码,这可能会有所帮助。我经常用它

Grrr 发表于 2022-7-5 17:51:11

我通常这样做:


(defun *error* ( msg ) ; sometimes we need an error handler, for example the osmode variable
(if osm (setvar 'osmode osm))
(if (not (member msg '("Function cancelled" "quit / exit abort")))
        (princ (strcat "\nError: " msg))
)
(princ)
)

(setq osm (getvar 'osmode))
(setvar 'osmode 0)

(while T ; start the overall loop
(setvar 'errno 0)
(while ; source object loop
        (not
                (and
                        (setq ent1 (car (entsel "\nSelect source object: ")))
                        (eq (cdr (assoc 0 (setq elist1 (entget ent1)))) "INSERT") ; optional filter
                )
        )
        (if (or (= (getvar 'errno) 7) (null ent1) ) (princ "\nYou missed try again!"))
)

(while ; destination object loop
        (not
                (and
                        (setq ent2 (car (entsel "\nSelect destination object: ")))
                        (eq (cdr (assoc 0 (setq elist2 (entget ent2)))) "INSERT") ; optional filter
                )
        )
        (if (or (= (getvar 'errno) 7) (null ent2) ) (princ "\nYou missed try again!"))
)

(progn
        ; (we got the source and destination objects, do the rest of your stuff here)
)
) ; end the overall loop

David Bethel 发表于 2022-7-5 17:56:00

如果我理解正确,有很多方法可以处理这些类型的选择:
 

(defun c:pick2 (/ s1 e1 s2 e2)
(and
    (princ "\nSelect Source INSERT")
    (setq s1 (ssget (list (cons 0 "INSERT"))))
    (= (sslength s1) 1)
    (setq e1 (ssname s1 0)))
(redraw e1 3)
(while
   (and
   (princ "\nSelect 1 Target INSERT")
   (setq s2 (ssget (list (cons 0 "INSERT"))))
   (= (sslength s1) 1)
   (setq e2 (ssname s2 0))
   (not (eq e1 e2)))

   (prin1 e2)

)
   (redraw)
   (prin1))

 
将(prin1 e2)调用替换为您想要完成的操作。
 
-大卫

broncos15 发表于 2022-7-5 18:00:51

Grr,这是另一个while循环的酷用法!我也在想如何通过按空格键退出,但我想不出来。我试着做一个条件,如果实体为null,那么我把它设为nil,但这不起作用。你能想到怎么做吗?David,我以前没有见过使用while循环的ssget,这非常灵活(不幸的是,我必须使用nentsel,因为我从外部参照中的对象获取信息)。

Lee Mac 发表于 2022-7-5 18:09:30

我建议将选择操作划分为一个单独的功能,例如:
(defun c:test ( / des prd src )
   (setq prd
      '(lambda ( x )
         (wcmatch
               (cdr (assoc 0 (entget x)))
               "LINE,ARC,CIRCLE,LWPOLYLINE,POLYLINE,RAY,XLINE,AECC_FEATURE_LINE"
         )
       )
   )
   (if
       (and
         (setq src (selectif "\nSelect source object: "      prd))
         (setq des (selectif "\nSelect destination object: " prd))
       )
       (princ "\nDo stuff.")
   )
   (princ)
)
(defun selectif ( msg prd / ent )
   (while
       (progn (setq ent (car (entsel msg)))
         (cond
               (   (= 7 (getvar 'errno))
                   (princ "\nMissed, try again.")
               )
               (   (not ent) nil)
               (   (not (apply prd (list ent)))
                   (princ "\nInvalid object selected.")
               )
         )
       )
   )
   ent
)

broncos15 发表于 2022-7-5 18:15:06

李,非常感谢你的帮助!我现在遇到的问题是添加了另一个while循环,该循环将一直运行,直到空格键被击中或逃脱。例如,用户将选择源对象,然后选择目标对象,然后选择源对象,然后选择目标。。。直到他们做了他们想做的一切,然后他们就会击中空间或逃跑。

broncos15 发表于 2022-7-5 18:17:22

因此,我最终通过以下方式实现了这一点:
(while
   (and
(setq sent (selectif "\nSelect source object: "))
(setq dent (selectif "\nSelect destination object: "))
   )
;...Rest of code像这样使用and函数有什么问题吗?

Grrr 发表于 2022-7-5 18:22:46

通过阅读本文,我认为您必须使用其他方法-提示用户在循环中不断选择源和目标对象,并在这样做的同时构建一个assoc列表,如下所示:
(<source ent1> . <destination ent1>) (<source ent2> . <destination ent2>) ... (<source entN> . <destination entN>)
然后为列表中的每一对做你的秘密工作。
不幸的是,我不知道如何编写这个代码(但我对此很感兴趣,因为我脑海中也有类似的想法)。
页: [1] 2
查看完整版本: While循环中的While循环