Support Forum

[Frage] Interactor PythonPart modifizieren [Gelöst]

Schlagworte:
  • Allplan
  • 2022
  • PythonParts
  • PythonAPI
  • Modifizieren
  • Fehler
  • Interactor

Hallo. Ich habe ein recht seltsames Problem. Ich hab mich mal an einem Interactor probiert. Als Vorlage hab ich da den Polyline3DInteractor genommen. Da ich meinen PythonPart jedoch nicht als 3D Element sondern als Part absetzten will, hab ich den Part so erzeugt:

pythonpart = PythonPart('MyInteractor',
                        parameter_list=BuildingElementListService.get_params_list(
                            self.build_ele_list),
                        hash_value=BuildingElementListService.get_hash(
                            self.build_ele_list),
                        python_file=self.build_ele_list[0].pyp_file_name,
                        views=[View2D3D(self.model_ele_list)])

AllplanBaseElements.CreateElements(self.coord_input.GetInputViewDocument(),
                                    AllplanGeo.Matrix3D(),
                                    pythonpart.create(), [], None)

Auch beim Initialisieren meiner Interactor Klasse hab ich folgende Parameter ergänzt:

self.build_ele_list = build_ele_list
self.build_ele_composite = build_ele_composite
self.control_props_list = control_props_list
self.modify_uuid_list = modify_uuid_list

So weit so gut. Wenn ich den PythonPart aus der Bibliothek erzeuge funktioniert alles genau so wie ich will ohne Fehler. Sobald ich jedoch den abgesetzten PythonPart wieder modifizieren will (also mit Doppelklick) dann erscheint folgende Fehlermeldung im Trace.

Traceback (most recent call last):
File "C:\ProgramData\Nemetschek\Allplan\2022\Etc\PythonPartsFramework\GeneralScripts\BuildingElementInput.py", line 795, in create_element
preview_ele_list = self.build_ele_script.create_element(self.build_ele_list[0],
AttributeError: 'NoneType' object has no attribute 'create_element'

Ich verstehe aber nicht warum das nicht funktioniert. Die Polylinie die ich abgreife wird auch in einem Parameter aus der .pal-File gespeichert - die erzeugte Geometrie dürfte also nicht verloren gehen...

Lösung anzeigen Lösung verbergen

Hab den Fehler nun gefunden:
Der Name-Tag in der jeweiligen pal oder pypsub File muss ausgefüllt sein! Ich hatte das bisher immer auf <Name></Name> gestellt.
Das führt dazu, dass das Erzeugen des Parts ohne Probleme funktioniert, sobald man ihn aber modifizieren will nicht mehr klar ist auf welches Script der Part zugreifen soll...

Du brauchst 2 PythonParts: Den Interactor(1), der das eigentliche PythonPart(2 ohne Interactor) erzeugt.

Der Versuch, das in einem PythonPart zu machen, ist schwierig bis unmöglich.
Ein PythonPart mit aktiviertem Interactor ist nicht zur Modifikation vorgesehen. Das ist ein "Fire-And-Forget"-Tool!

Denn beim Doppelklick links auf das PythonPart zum Modifizieren wird der Interactor gestartet, und will "sich" erneut absetzen...

Hallo.

Es gibt einige Beispiele (Precast Trench, Tendon Placement, etc...) in denen das in einem Part abgebildet wird. Die Methode mit dem absetzten eines Parts ist mir bekannt jedoch würde ich gerne bei einem bereits abgesetzten Part auch mal die Austeilung der Linie neu eingeben. Bei einem Tool, welches ich mit Visual Scripting generiere ist das ja auch möglich.

Ich hab mich hier an die oben genannten Beispiele gehalten, jedoch verstehe ich nicht, warum die oben genannte Fehlermeldung kommt. Das Script wird nicht mal ausgeführt sondern sofort die Exception geworfen

Naja, die Fehlermeldung aufmerksam lesen: AttributeError: 'NoneType' object has no attribute 'create_element'

preview_ele_list = self.build_ele_script.create_element(self.build_ele_list[0]

self.build_ele_script hat keinen Typ, ist scheinbar nur ein object!
Dem Member self.build_ele_script müsste man was zuweisen, z.B. das Script wie in
BuilingElementService.py Line 112:
build_ele_script = BuildingElementUtil.import_building_element_script(build_ele, False, set())

Leider kann ich Dir beim Python-Framework nicht weiter helfen.
Vielleicht kann Herr Hohmann sich des Problems annehmen?

Hallo Nemo.
Danke, dass du mich darauf aufmerksam gemacht hast! In den Beispielen, bei denen das Modifizieren funktioniert, wurde build_ele_script nie definiert. Ich hab das jedoch beim Aufruf der Palette instanziiert:

result, self.build_ele_script, self.build_ele_list, self.control_props_list,    \
    self.build_ele_composite, part_name, self.file_name = \
    self.build_ele_service.read_data_from_pyp(self.pyp_path + "\\" + palette_name,
                                                self.str_table_service.str_table, False,
                                                self.str_table_service.material_str_table)

Wenn ich alle Parameter in der .pyp-Datei definiere und die Palette so aufrufe

self.palette_service = BuildingElementPaletteService(self.build_ele_list, self.build_ele_composite,
                                                     "",
                                                     self.control_props_list, "InteractorExample")

self.palette_service.show_palette("InteractorExample")

funktioniert das Modifizieren des Parts... Das heißt für mich mal: weniger mit .pal Dateien sondern pypsub's arbeiten.
Den genauen Fehler verstehe ich leider immer noch nicht - vielleicht hat hier ja jemand die Antwort...

Moin zusammen,

also man kann Interactor mit "normalem PythonPart" kreuzen (bzw den ein Interactor-Objekt auch ohne große Interacktionen verwenden), indem man einfach eine Weiche einbaut. Wenn Interactor_flag, dann als Interactor agieren (z.B. Koordinaten per Klicken abgreifen), ansonsten andere Funktionen durchführen.
Im Beispiel LinesFromFileInteractor.py ist eine Weiche eingebaut.
Somit kann man mit einem Objekt beide Fälle abdecken. Oder man setzt mit dem Interactor ein normales PythonPart ab. Dann braucht man halt 2 unterschiedliche Objekte.

Hi,

für meinen Workflow brauche ich zuerst immer die Interactor Funktionen und anschließend die Modifikationen. Da ich jedoch die Eingaben die ich mit meinem Interactor getätigt habe (z.B.: Koordinaten abfragen, Element auswählen, Polylinie generieren) manchmal auch neu eingeben muss (und dabei alle anderen Angaben behalten will), wollte ich das nicht mit 2 Parts lösen. Ich hab das so wie oben beschrieben gelöst und die Weiche nicht innerhalb der create_interactor Methode sondern innerhalb meiner Klasse gelöst. Hier gibt es einen Parameter, welcher auf den aktuellen "Bearbeitungsstatus" hinweist und je nach dem Status diesen Parameters ändern sich Eingabepaletten und Workflows.

Der Fehler tritt hier nur auf wenn ich mit .pal-Dateien arbeite. Warum das der Fall ist kann ich mir nicht ganz erklären. Ich bin jetzt auf das Verwenden von pypsub Files umgestiegen. Hier scheint der oben genannte Fehler nicht aufzutreten.

Ich hab mich wohl zu früh gefreut!
Der oben gezeigte Weg funktioniert nur wenn alle Pages und Parameter innerhalb der .pyp File definiert werden. Sobald die building_ele_list also mehr als einen Eintrag hat tritt mein Fehler auf.

Hab den Fehler nun gefunden:
Der Name-Tag in der jeweiligen pal oder pypsub File muss ausgefüllt sein! Ich hatte das bisher immer auf <Name></Name> gestellt.
Das führt dazu, dass das Erzeugen des Parts ohne Probleme funktioniert, sobald man ihn aber modifizieren will nicht mehr klar ist auf welches Script der Part zugreifen soll...