Закрытие видов

Автор Тема: Закрытие видов  (Прочитано 3823 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Закрытие видов
« : 21-11-2017, 14:21:41 »
Добрый день.

Пытаюсь открыть несколько видов, произвести в них некоторые действия, затем закрыть. При закрытии видов Revit падает с предложением отправить отчёт об ошибке. Пробовал в версиях 2015 и 2017.

Пишу в RevitPythonShell, поэтому код на Python.

Код - Python [Выбрать]
  1. user_active_view = uidoc.ActiveView
  2. user_opened_views = uidoc.GetOpenUIViews()
  3.  
  4. views = [view for view in FilteredElementCollector(doc).WherePasses(ElementClassFilter(ViewPlan)) if view.IsValidObject and not view.IsTemplate and view.ViewType != ViewType.CeilingPlan]
  5.  
  6. for view in views:
  7.     uidoc.ActiveView = view
  8.  
  9. uidoc.ActiveView = user_active_view
  10.  
  11. user_opened_views_ids_set = set(ui_view.ViewId for ui_view in user_opened_views)
  12. for ui_view in uidoc.GetOpenUIViews():
  13.     if ui_view.ViewId not in user_opened_views_ids_set:
  14.         ui_view.Close()

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #1 : 21-11-2017, 14:59:11 »
А в питоне нет блока try{} catch{}? Отлов ошибок. Нужно сначала обернуть в него.
И другой вопрос - в RevitPythonShell есть отладка пошаговая?

И если на первые два вопроса ответ "нет", то третий вопрос - зачем питон???

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Re: Закрытие видов
« Ответ #2 : 21-11-2017, 15:10:26 »
Завернул в try-except, ошибка не печатается, Revit падает.

Код - Python [Выбрать]
  1. try:
  2.     user_active_view = uidoc.ActiveView
  3.     user_opened_views = uidoc.GetOpenUIViews()
  4.  
  5.     views = [view for view in FilteredElementCollector(doc).WherePasses(ElementClassFilter(ViewPlan)) if view.IsValidObject and not view.IsTemplate and view.ViewType != ViewType.CeilingPlan]
  6.  
  7.     for view in views:
  8.         uidoc.ActiveView = view
  9.  
  10.     uidoc.ActiveView = user_active_view
  11.  
  12.     user_opened_views_ids_set = set(ui_view.ViewId for ui_view in user_opened_views)
  13.     for ui_view in uidoc.GetOpenUIViews():
  14.         if ui_view.ViewId not in user_opened_views_ids_set:
  15.             ui_view.Close()
  16.            
  17. except Exception as exception:
  18.     print exception.message

Выполнял пошагово команды, закрывал виды по одному. В таком режиме всё проходит успешно. Но при запуске этого кода не работает.

Есть предположение, что при открытии и изменении видов происходят какие-то действия, которые не успевают завершиться к моменту закрытия, что и приводит к ошибке. Но если даже так, то как отслеживать, что виды готовы к закрытию?

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #3 : 21-11-2017, 15:18:53 »
Попробуйте сначала вызвать ui_view.Dispose()

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #4 : 21-11-2017, 15:21:53 »
И еще можно попробовать перед закрытием вида сделать его активным

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Re: Закрытие видов
« Ответ #5 : 21-11-2017, 16:46:57 »
Сделать вид активным перед закрытием не помогает. Если же вызвать ui_view.Dispose() перед закрытием, то вылетает ошибка: "The managed object is not valid.".

Видимо, проблема действительно в том, что виды не готовы к закрытию. Если открыть вручную несколько видов и запустить следующий код, всё работает как надо.

Код - Python [Выбрать]
  1. try:  
  2.     for ui_view in uidoc.GetOpenUIViews():
  3.         if ui_view.ViewId != uidoc.ActiveView.Id:
  4.             ui_view.Close()
  5.            
  6. except Exception as exception:
  7.     print exception.message

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #6 : 21-11-2017, 16:52:20 »
Еще вариант для эксперимента - куда-то добавить транзакцию. Может в открытие вида, может и весь код обернуть
В Ревите бывают случаи, когда для методов, которым якобы не нужна транзакция, нужно использовать транзакцию
Еще вопрос - какое значение атрибута Транзакция для класса команды? Тоже может повлиять

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Re: Закрытие видов
« Ответ #7 : 21-11-2017, 17:09:52 »
При запущенной транзакции виды не открываются, ошибка: "Cannot change the active view of a modifiable document (with a transaction curently open)."
Если обернуть в транзакцию закрытие видов, Revit точно так же падает.

Еще вопрос - какое значение атрибута Транзакция для класса команды? Тоже может повлиять

Этот вопрос не понял. Объясните, пожалуйста.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #8 : 21-11-2017, 17:20:22 »
Когда пишется плагин на .Net, то для класса, реализующего интерфейс IExternalCommand ОБЯЗАТЕЛЬНО должен задаваться атрибут Transaction. Выглядит примерно так:
Код - C# [Выбрать]
  1. [Transaction(TransactionMode.Manual)]
  2. [Regeneration(RegenerationOption.Manual)]
  3. public class Revit_LintelsCommand : IExternalCommand
  4. {
  5.    //.....
  6. }
Атрибут имеет три варианта:
Automatic
        The API framework will create a transaction on the active document before the external command is executed and the transaction will be committed or rolled back after the command is completed (based upon the return value of the ExternalCommand callback).
Manual
   The API framework will not create a transaction (but will create an outer group to roll back all changes if the external command returns a failure status). Instead, you may use combinations of transactions, sub-transactions, and groups. You will have to follow all rules regarding use of transactions and related classes. You will have to give your transactions names, which will then appear in the undo menu. Revit will check that all transactions (also groups and sub-transaction) are properly closed upon return from an external command. If not, it will discard all changes to the model.
ReadOnly
   No transaction (nor group) will be created, and no transaction may be created for the lifetime of the command. The External command may use methods that only read from the model, but not methods that write anything to it. Exceptions will be thrown if the command either tries to start a transaction (or group) or attempts to write to the model.

По идее у вас тоже должно быть что-то подобное. Я просто не знаком с питоном.

Вот еще тема на что-то похожее вашему вопросу, где тоже говорится о транзакциях

Все-таки, мне кажется, что проблема где-то вокруг транзакций вертится.

Правда я не сталкивался еще с закрытием видов, поэтому могу только выдвигать предположения

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Re: Закрытие видов
« Ответ #9 : 21-11-2017, 17:20:44 »
damirsib, а на простой тестовой модели тоже падает? Бывают такое, что какой-то метод API не выполняется в конкретной модели.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Закрытие видов
« Ответ #10 : 21-11-2017, 17:23:32 »
К моему предыдущему ответу - могу предположить, что плагин автоматически запускается с атрибутом TransactionMode.Automatic, что согласно справке "запускает транзакцию до выполнения команды и завершает её после выполнения". А при работе с видами возможно нужно зафиксировать изменения в документе перед закрытием, но плагин этого не может сделать.
Значит нужно атрибут делать TransactionMode.Manual и самому в коде управлять транзакциями

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Re: Закрытие видов
« Ответ #11 : 21-11-2017, 17:33:44 »
Александр, спасибо за объяснение. Не нашёл способа проверить текущее состояние TransactionMode, но насколько смог разобраться в исходном коде RevitPythonShell, там используется TransactionMode.Manual, не нашёл в коде ни одного упоминания TransactionMode.Automatic.

Виктор, пробовал на разных моделях, даже на пустой, падает всегда.

Отмечено как Решение Александр Ривилис 22-11-2017, 01:32:03

Оффлайн Виктор Чекалин

  • Administrator
  • *****
  • Сообщений: 694
  • Карма: 111
  • Skype: chekalin-v
Re: Закрытие видов
« Ответ #12 : 21-11-2017, 17:35:15 »
Осталось попробовать выполнить данный код не на Питоне  и проверить ) Как вариант, контекст для выполнения данной команды не верный. Хотя PythonShell вроде в виде модального окна выступает.

Оффлайн damirsibАвтор темы

  • ADN OPEN
  • Сообщений: 6
  • Карма: 0
Re: Закрытие видов
« Ответ #13 : 21-11-2017, 18:54:08 »
Проблема действительно оказалась в RevitPythonShell. Переписал на C# - всё сработало.

Виктор, Александр, спасибо за помощь.