Pour utiliser/créer une interface utilisateur depuis Dynamo il y a quelques solutions :
if this article is not in your language, use the Google Translate widget (bottom of page for Mobile version) ⬈
- le Dynamo Player
- permet de lancer des scripts
- permet de modifier des données d'entrée
- permet de visualiser les données de sortie
- le package MultipleInputForm++ (Data-Shape) pour créer facilement des UI Winform
- le package Mandrill pour visualiser des données sous forme de graphiques
- l'addin DynoBrowser (un launcher de script personnalisable)
Mais si vous avez quelques connaissances sur le framework .Net
(Winform ou Wpf) il est aussi possible de réaliser son propre UI.
Note:
Juste pour une question de débogage, bien que cela soit possible
d'utiliser Wpf en IronPython il est préférable d'utiliser Winform.
Pour faciliter la création et soulager un peu vos neurones, le formulaire
(Winform) sera créé dans un IDE comme SharpDevellop ou VisualStudio en Python, puis le code sera complété dans un nœud Dynamo
(Python).
Version conseillée à ce jour
Prérequis: du fait que SharpDevellop est un peu dépassé, il est conseillé
d'activer le Net Framework 3.5 dans les options de Windows pour éviter des
erreurs de compilation IronPython (ipy)
Choisir Python puis Application Windows pour créer un "Windows Form IronPython" |
Note:
Dans le cas d'une simple réalisation d'une interface UI il n'est pas
nécessaire d'importer les références telles que l'API Revit ou l'API
DynamoDS.
Placement des Objets dans la fenêtre Design |
Un double clique sur les objets pour créer les évènements puis copie du code vers Dynamo pour finalisation |
Note :
Dans le nœud Python dans Dynamo on pensera à rajouter les "assembly" nécessaire
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
Aller, un Exemple ?
Contexte de l'exemple ci-après :
Au fil d'un projet, il n'est pas rare de devoir aller fouiller dans les Paramètres de Projet afin de retrouver les propriétés d'un paramètres (catégories associées ?, groupe?, type de paramètre ?, etc...), et la liste peut être très longue....
Voici un script qui permet de visualiser les paramètres de Projet dans une fenêtre sous forme d'un TreeNode (WinForm) dynamique.
L'extraction des Paramètres de Projet se fait avec la propriété ParameterBindings ainsi que la
méthode ForwardIterator afin de retrouver le dictionnaire associé (IEnumerable).
# coding : utf-8
# Copyright POUPIN.C
import clr
import re
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
import System
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
import System.Drawing
import System.Windows.Forms
from System.Drawing import *
from System.Windows.Forms import *
from System.Collections.Generic import List
class ParaProj():
def __init__(self, definition, binding):
self.defName = definition.Name
self.binding = binding
self.thesecats = []
self.group = LabelUtils.GetLabelFor(definition.ParameterGroup)
for cat in binding.Categories:
try:
self.thesecats.append(cat.Name)
except SystemError:
pass
class MainForm(Form):
def __init__(self, lstObj_bind):
self.lstObj_bind = lstObj_bind #lst object
collSharP = FilteredElementCollector(doc).OfClass(SharedParameterElement)
self._paraSharPara = [x.GetDefinition().Name for x in collSharP]
self.InitializeComponent()
def InitializeComponent(self):
self._treeView1 = System.Windows.Forms.TreeView()
self._buttonEdit = System.Windows.Forms.Button()
self._buttonCancel = System.Windows.Forms.Button()
self.SuspendLayout()
#
# buttonEdit
self._buttonEdit.DialogResult = System.Windows.Forms.DialogResult.OK
self._buttonEdit.Location = System.Drawing.Point(350, 500)
self._buttonEdit.Name = "buttonEdit"
self._buttonEdit.Size = System.Drawing.Size(150, 45)
self._buttonEdit.TabIndex = 0
self._buttonEdit.Text = "Editer Paramètres de Projet"
self._buttonEdit.UseVisualStyleBackColor = True
self._buttonEdit.Click += self.ButtonEditClick
#
# buttonCancel
self._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel
self._buttonCancel.Location = System.Drawing.Point(50, 500)
self._buttonCancel.Name = "buttonCancel"
self._buttonCancel.Size = System.Drawing.Size(142, 45)
self._buttonCancel.TabIndex = 0
self._buttonCancel.Text = "Quitter"
self._buttonCancel.UseVisualStyleBackColor = True
self._buttonCancel.Click += self.ButtonCancelClick
#
# textBox1
self._textBox1 = System.Windows.Forms.TextBox()
self._textBox1.Location = System.Drawing.Point(50, 46)
self._textBox1.Name = "SearchBox"
self._textBox1.Size = System.Drawing.Size(213, 22)
self._textBox1.TabIndex = 0
self._textBox1.TextChanged += self.TextBox1TextChanged
#
# Label
self._label1 = System.Windows.Forms.Label()
self._label1.Location = System.Drawing.Point(50, 20)
self._label1.Name = "Search"
self._label1.Size = System.Drawing.Size(150, 23)
self._label1.TabIndex = 1
self._label1.Text = "Recherche (Regex)"
#
# treeView1
self._treeView1.Location = System.Drawing.Point(50, 75)
self._treeView1.Name = "treeView1"
dataBind = self.lstObj_bind
#call function to Populate TreeNode
self.setDataTreeNode(dataBind)
self._treeView1.Size = System.Drawing.Size(450, 400)
self._treeView1.TabIndex = 0
#
# Form1
self.ClientSize = System.Drawing.Size(540, 580)
self.Controls.Add(self._treeView1)
self.Controls.Add(self._label1)
self.Controls.Add(self._textBox1)
self.Controls.Add(self._buttonCancel)
self.Controls.Add(self._buttonEdit)
self.Name = "Projet Parameters"
self.Text = "Liste des Parametres de Projet"
self.ResumeLayout(False)
def setDataTreeNode(self, dataBind):
self.lsttreenode = List[System.Object]()
for objbind in dataBind:
paraproj = objbind.defName
isShared = "Partagé" if paraproj in self._paraSharPara else "Non Partagé"
#check binding and apply Color
if isinstance(objbind.binding, InstanceBinding):
bindtype = "Occurrence"
colorNod = System.Drawing.Color.Blue
else:
bindtype = "Type"
colorNod = System.Drawing.Color.Red
filtercats = objbind.thesecats
sublist = List[System.Object]()
#create data TreeNode
for cat in filtercats:
treeNodeChildCat = System.Windows.Forms.TreeNode(cat)
treeNodeChildCat.Name = cat
treeNodeChildCat.Text = cat
sublist.Add(treeNodeChildCat)
treeNodeParentCat = System.Windows.Forms.TreeNode("Catégories", System.Array[System.Windows.Forms.TreeNode](sublist))
treeNodeParentCat.Name = "Catégories"
treeNodeParentCat.Text = "Catégories"
treeNodeTypePara = System.Windows.Forms.TreeNode("Propriété")
treeNodeTypePara.Name = "Propriété"
treeNodeTypePara.Text = "Propriété du Paramètre : " + bindtype
treeNodeShared = System.Windows.Forms.TreeNode("Type")
treeNodeShared.Name = "Type"
treeNodeShared.Text = "Type de Paramètre : " + isShared
treeNodeGroup = System.Windows.Forms.TreeNode("Groupe")
treeNodeGroup.Name = "Groupe"
treeNodeGroup.Text = "Groupe : " + objbind.group
treeNodeParentPara = System.Windows.Forms.TreeNode(paraproj, System.Array[System.Windows.Forms.TreeNode](
[treeNodeTypePara,
treeNodeShared,
treeNodeGroup,
treeNodeParentCat]))
#treeNodeParent
treeNodeParentPara.Name = paraproj
treeNodeParentPara.Text = paraproj
treeNodeParentPara.ForeColor = colorNod
self.lsttreenode.Add(treeNodeParentPara)
self._treeView1.Nodes.AddRange(System.Array[System.Windows.Forms.TreeNode](self.lsttreenode))
def TextBox1TextChanged(self, sender, e):
try:
dataBindFilter = [x for x in self.lstObj_bind if re.search(sender.Text, x.defName) is not None]
self._treeView1.BeginUpdate()
self._treeView1.Nodes.Clear()
self.setDataTreeNode(dataBindFilter)
self._treeView1.EndUpdate()
except:pass #if regex failed (typing not finish )
def ButtonCancelClick(self, sender, e):
self.Close()
def ButtonEditClick(self, sender, e):
id_addin = RevitCommandId.LookupPostableCommandId(PostableCommand.ProjectParameters)
uiapp.PostCommand(id_addin)
self.Close()
full_bind = []
iterator = doc.ParameterBindings.ForwardIterator()
while iterator.MoveNext():
objBind = ParaProj(iterator.Key, iterator.Current)
full_bind.append(objBind)
full_bind.sort(key = lambda x : x.defName)
objform = MainForm(full_bind)
result = objform.ShowDialog()
OUT = full_bind, result
lien Github
Aperçu en Vidéo
# coding : utf-8
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument
class ParaProj():
def __init__(self, definition, binding):
self.defName = definition.Name
self.binding = binding
self.thesecats = []
self.group = LabelUtils.GetLabelFor(definition.ParameterGroup)
self.type = "Instance" if isinstance(binding, InstanceBinding) else "Type"
@property
def categories(self):
thesecats = []
for cat in self.binding.Categories:
try:
thesecats.append(cat.Name)
except SystemError:
pass
return thesecats
@property
def isShared(self):
collSharP = FilteredElementCollector(doc).OfClass(SharedParameterElement)
paraSharPara = [x.GetDefinition().Name for x in collSharP]
return True if self.defName in paraSharPara else False
paraName = []
paraGroup = []
paraCategories = []
paraType = []
paraIsShared = []
iterator = doc.ParameterBindings.ForwardIterator()
while iterator.MoveNext():
objBind = ParaProj(iterator.Key, iterator.Current)
paraName.append(objBind.defName)
paraGroup.append(objBind.group)
paraType.append(objBind.type)
paraIsShared.append(objBind.isShared)
paraCategories.append(objBind.categories)
OUT = paraName, paraGroup, paraType, paraIsShared, paraCategories
Une astuce pour trouver si un paramètre partagé est présent dans le projet
import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
lstDef = []
gpNames = []
spf = app.OpenSharedParameterFile()
if spf is not None:
spfGroups = spf.Groups
for group in spfGroups:
for def_ in group.Definitions:
guid = def_.GUID
spInproj = SharedParameterElement.Lookup(doc, guid)
if spInproj is not None:
defInproj = spInproj.GetDefinition()
pGroup = defInproj.ParameterGroup
lstDef.append(defInproj)
gpNames.append(LabelUtils.GetLabelFor(pGroup))
OUT = lstDef, gpNames
Thanks for this article. It help me a lot for my work.
RépondreSupprimerYou're welcome
SupprimerBonjour et merci pour les explications
RépondreSupprimerJ'ai installé SharpDevelop
dans la catégorie je ne vois pas le répertoire Python
à l'occasion, merci
Salut, essaie la version suivante
SupprimerSharpDevelop_4.4.1.9729_Setup.msi
j'ai rajouté le lien dans l'article
Bonjour, impeccable
SupprimerMerci @ vous
cordialement