【问题标题】:IronPython and Revit API - How to display item attributes in listbox (attribute name)?IronPython 和 Revit API - 如何在列表框中显示项目属性(属性名称)?
【发布时间】:2019-12-17 14:52:37
【问题描述】:

我是一名建筑师,通过 Revit 逐渐爱上了编码。但不幸的是,由于仍然是一个终极菜鸟,我需要任何愿意加入的人的帮助。我也是 Stackoverflow 菜鸟,所以我不知道是否可以,并且在社区中发布这样的问题更多辅导的,然后解决问题。但无论如何,它是这样的: 我正在尝试创建一个能够同时从 Revit 族编辑器中删除多个参数的应用程序。我在 C# 方面取得了成功,但是由于我想转移到 Python,因为作为初学者更容易进入,所以我做了很多浏览,但由于 OOP 知识有限而没有任何帮助。 如何在列表框中显示 Family 参数名称,或者如果列表框中已经有字符串名称,如何将所选项目与 FamilyParameterSet 中的实际参数进行比较?

我有一个启动代码,可以从家庭管理员那里收集所有参数。我将它投射到列表中。然后一个选项是使用要在列表框中列出的参数的名称属性,但我不知道返回并检查列表或循环列表以将参数集中的名称与从列表框中选择的名称进行比较。所以我选择了将 Family 参数直接放入列表框中的另一个选项,但我无法显示实际的 Name 属性。 这段 C# 代码可能对我有帮助,但我不知道如何在 Python 中重新创建它,因为我的 OOP 经验真的很差。 Items on ListBox show up as a class name

doc = __revit__.ActiveUIDocument.Document               
mgr = doc.FamilyManager;                                
fps = mgr.Parameters;                                  

paramsList=list(fps)                                   
senderlist =[]                                          

class IForm(Form):

    def __init__(self):
        self.Text = "Remove multiple parameters"

        lb = ListBox()                                  
        lb.SelectionMode = SelectionMode.MultiSimple   

        for n in fps:                                   
        lb.Items.Add(n.Definition.Name)


        lb.Dock = DockStyle.Fill
        lb.SelectedIndexChanged += self.OnChanged       


        self.Size = Size(400, 400)                      
        self.CenterToScreen()                           

        button = Button()                               
        button.Text = "Delete Parameters"              
        button.Dock = DockStyle.Bottom                  
        button.Click += self.RemoveParameter                  
        self.Controls.Add(button)  

    def OnChanged(self, sender, event):
        senderlist.append(sender.SelectedItem)                        

    def RemoveParameter(self,sender,event):       
        for i in paramsList:
            if i.Definition.Name in senderlist:
            t = Transaction(doc, 'This is my new transaction')
            t.Start()  
            mgr.RemoveParameter(i.Id)
            t.Commit()
Application.Run(IForm())

我需要函数 RemoveParameter 具有 Family 参数的所有 .Id 比例,以便将它们从 Family 参数集中删除。在代码的开头(对于不知道 Revit API 的人)“fps”表示 FamilyParameterSet,它被转换为 Python 列表“paramsList”。所以我需要从列表框中选择的项目中删除 FPS 的成员。

【问题讨论】:

    标签: c# python listbox revit-api revitpythonshell


    【解决方案1】:

    您从 Revit 到编写代码的旅程很熟悉!

    首先,您的 C# 代码中似乎存在一些遗留问题。您需要牢记从 C# 到 Python 的几个关键转变 - 在您的情况下,根据运行代码时的错误,有两行需要缩进:

    Syntax Error: expected an indented block (line 17)
    Syntax Error: expected an indented block (line 39)
    

    经验法则是在冒号: 之后需要缩进,这也使代码更具可读性。前几行还有一些分号; - 不需要它们!

    否则代码就在那里,我在下面的代码中添加了 cmets:

    # the Winforms library first needs to be referenced with clr
    import clr
    clr.AddReference("System.Windows.Forms")
    
    # Then all the Winforms components youre using need to be imported
    from System.Windows.Forms import Application, Form, ListBox, Label, Button, SelectionMode, DockStyle
    
    doc = __revit__.ActiveUIDocument.Document               
    mgr = doc.FamilyManager                         
    fps = mgr.Parameters                          
    
    paramsList=list(fps)                                   
    # senderlist = [] moved this into the Form object - welcome to OOP!                                        
    
    class IForm(Form):
    
        def __init__(self):
            self.Text = "Remove multiple parameters"
    
            self.senderList = []
    
            lb = ListBox()                                  
            lb.SelectionMode = SelectionMode.MultiSimple   
    
            lb.Parent = self # this essentially 'docks' the ListBox to the Form
    
            for n in fps:                                   
                lb.Items.Add(n.Definition.Name)
    
            lb.Dock = DockStyle.Fill
            lb.SelectedIndexChanged += self.OnChanged       
    
            self.Size = Size(400, 400)                      
            self.CenterToScreen()                           
    
            button = Button()                               
            button.Text = "Delete Parameters"              
            button.Dock = DockStyle.Bottom                  
            button.Click += self.RemoveParameter                  
            self.Controls.Add(button)  
    
        def OnChanged(self, sender, event):
            self.senderList.append(sender.SelectedItem)                        
    
        def RemoveParameter(self,sender,event):       
            for i in paramsList:
                if i.Definition.Name in self.senderList:
                    t = Transaction(doc, 'This is my new transaction')
                    t.Start()
    
                    # wrap everything inside Transactions in 'try-except' blocks
                    # to avoid code breaking without closing the transaction
                    # and feedback any errors
                    try:
                        name = str(i.Definition.Name) 
                        mgr.RemoveParameter(i) # only need to supply the Parameter (not the Id)
                        print 'Parameter deleted:',name # feedback to the user
                    except Exception as e:
                        print '!Failed to delete Parameter:',e
    
                    t.Commit()
                    self.senderList = [] # clear the list, so you can re-populate 
    
    Application.Run(IForm())
    

    从这里开始,附加功能只是为用户完善它:

    • 添加一个弹出对话框,让他们知道成功/失败
    • 一旦用户删除了参数,刷新ListBox
    • 过滤掉BuiltIn不能删除的参数(删除一个试试看报错)

    让我知道这是如何工作的!

    【讨论】:

    • 非常感谢@Callum。本质上,脚本本身仍然只删除单个参数,而我想删除多个参数,但它帮助我掌握了需要做的事情。它也帮助我更多地理解 OOP。所以总的来说,它确实有助于语气。与此同时,我将我的解决方案迁移到了带有复选框的 Listview 中,它工作起来更加整洁。但是,我遇到了另一个我试图解决的问题。我想捕捉异常(InvalidOperationException),但没有这样做......
    • 当我在项目中(不是在家庭编辑器模式下)尝试使用我的功能区应用程序时会发生这种情况。通过 RevitPythonShell 部署 XML 后,我创建了一个 .addin。所以本质上它在家庭编辑器中就像一个魅力,但如果应用程序正在项目中使用,我想提示用户去家庭管理员。 Itried 是这样的:如果 doc.IsFamilyDocument==False: TaskDialog.Show("不在家庭编辑器中", "请进入家庭编辑器模式")。我尝试了 try/else 但没有太多成功。在 C# 中,我使用了上层设置并返回了 Result.Cancelled 但在这里我不知道如何解决这个问题...
    • 我会在接下来的一两天内尝试解决这个问题,然后可能会以全新的脚本为例创建新问题。你的指导方针真的很有帮助。再次感谢@Callum
    • 听起来你在正确的道路上 - 请注意,您可以使用 exit() 转义 python 脚本,因此在 TaskDialog 之后您可以在运行脚本的其余部分之前 exit()
    • 谢谢@Callum。由于我缺乏经验,这正是我一直在寻找的。 exit() 没有工作,但是(经过一些谷歌搜索后)它似乎 quit() 就像一个魅力。非常感谢。
    猜你喜欢
    • 2011-07-11
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2017-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多