Автообновление в ArcGIS с использованием Python

Я пытаюсь создать инструмент «автоматического обновления» для ArcMap, чтобы обновить DataFrame. Я считаю, что в версии 10 было дополнение, которое вы могли загрузить для этой цели ... однако мы работаем с 10.1, и такого инструмента нет.

ИЗМЕНИТЬ таймер wxPython должен работать, однако использовать wx в arc сложно. Вот как сейчас выглядит код:

import arcpy
import pythonaddins
import os
import sys
sMyPath = os.path.dirname(__file__)
sys.path.insert(0, sMyPath)

WATCHER = None

class WxExtensionClass(object):
    """Implementation for Refresher_addin.extension (Extension)"""
    _wxApp = None
    def __init__(self):
        # For performance considerations, please remove all unused methods in this class.
        self.enabled = True
    def startup(self):
        from wx import PySimpleApp
        self._wxApp = PySimpleApp()
        self._wxApp.MainLoop()
        global WATCHER
        WATCHER = watcherDialog()


class RefreshButton(object):
    """Implementation for Refresher_addin.button (Button)"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        if not WATCHER.timer.IsRunning():
            WATCHER.timer.Start(5000)
        else:
            WATCHER.timer.Stop()

class watcherDialog(wx.Frame):
    '''Frame subclass, just used as a timer event.'''
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "timer_event")
        #set up timer
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)

    def onTimer(self, event):
        localtime = time.asctime( time.localtime(time.time()) )
        print "Refresh at :", localtime
        arcpy.RefreshActiveView()

    app = wx.App(False)

Вы заметите там материал PySimpleApp. Я понял это из презентации Седерхольма. Мне интересно, если я что-то не понимаю. Должен ли я создать полностью отдельный надстройку для расширения? ЗАТЕМ создать мою панель инструментов / надстройку с нужным мне кодом? Я спрашиваю об этом, потому что я не вижу ссылки на PySimpleApp в приведенном ниже коде или какого-либо импорта из wx в методе переопределения запуска ... который, как я думал, был необходим / суть всего этого. Я очень ценю вашу помощь. Пожалуйста, дайте мне знать, что вы видите в моем коде.


person default_noob_network    schedule 11.05.2013    source источник
comment
Здесь вам понадобится какой-то параллелизм, time.sleep заблокирует и заблокирует Arcmap.   -  person MikeHunter    schedule 12.05.2013


Ответы (2)


Вы не можете сделать это так, как пытаетесь, потому что time.sleep заблокирует и заблокирует все приложение. Надстройки Python в ArcGIS - довольно новый материал, и многие функции еще не реализованы. Одно из них - это какое-то обновление или событие таймера, как в .NET и ArcObjects. Вы можете подумать об использовании threading.Thread и threading.Event в подобном случае, но ничего общего с потоками не будет работать в среде надстройки Python. По крайней мере, я не могу заставить его работать. В подобных ситуациях я использовал wxPython и класс Timer. Приведенный ниже код будет работать, если надстройка настроена правильно.

import time
import os, sys
import wx
import arcpy

mp = os.path.dirname(__file__)
sys.path.append(mp)

WATCHER = None

class LibLoader1(object):
    """Extension Implementation"""
    def __init__(self):
        self.enabled = True

    def startup(self):
        global WATCHER
        WATCHER = watcherDialog()

class ButtonClass5(object):
    """Button Implementation"""
    def __init__(self):
        self.enabled = True
        self.checked = False
    def onClick(self):
        if not WATCHER.timer.IsRunning():
            WATCHER.timer.Start(5000)
        else:
            WATCHER.timer.Stop()

class watcherDialog(wx.Frame):
    '''Frame subclass, just used as a timer event.'''
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "timer_event")
        #set up timer
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)

    def onTimer(self, event):
        localtime = time.asctime( time.localtime(time.time()) )
        print "Refresh at :", localtime
        arcpy.RefreshActiveView()

    app = wx.App(False)

Сделайте надстройку расширения с панелью инструментов и классом кнопок. Переопределите метод startup расширения, как показано выше. Это создаст экземпляр подкласса Frame с таймером. Затем всякий раз, когда вы нажимаете кнопку на панели инструментов, таймер включается или выключается. Аргумент таймера указывается в миллисекундах, поэтому показанный код будет обновляться каждые 5 секунд.

Подробнее об использовании wxPython в надстройках можно узнать здесь. Обратите особое внимание на сообщения MCederholm, например, о том, что оператор печати не работает.

РЕДАКТИРОВАТЬ

В коде используется startup переопределение метода класса расширения надстройки. Этот метод должен запускаться при запуске Arcmap, но из ваших комментариев видно, что этот метод запуска не запускается при запуске. Это возможно, если вы не создадите свою надстройку правильно, но в моих тестах она отлично работает. Если вы продолжаете получать «AttributeError: объект 'NoneType' не имеет атрибута 'timer'», измените метод onClick вашего класса кнопки следующим образом:

def onClick(self):

    if WATCHER is None:
        global WATCHER
        WATCHER = watcherDialog()

    if not WATCHER.timer.IsRunning():
        WATCHER.timer.Start(5000)
    else:
        WATCHER.timer.Stop()

Первые 3 строки проверяют, чтобы переменная WATCHER была установлена ​​на экземпляр watcherDialog, а не на None. Не знаю, почему ваш метод запуска не работает, но, надеюсь, это все исправит.

person MikeHunter    schedule 11.05.2013
comment
Потрясающий! Код, который вы предоставили, выглядит великолепно ... спасибо! Я боролся с тем, чтобы импортировать wx в окно Python в ArcMap. Не уверен, связано ли это с моей установкой wxPython. Я установил его специально в ArcGIS10.1 \ lib, однако я всегда получаю сообщение об ошибке при попытке импортировать wx. Я собираюсь посмотреть презентацию саммита разработчиков Марка Седерхольма в 2012 году, которую я получил по ссылке, на которую вы ссылались. (см. другой мой вопрос: stackoverflow.com/questions/16184829/) - person default_noob_network; 12.05.2013
comment
Также я получаю следующее сообщение об ошибке: Runtime error Traceback (последний вызов последний): File ‹string›, строка 1, в ‹module› Файл C: \ Python27 \ ArcGIS10.1 \ lib \ site-packages \ wx-2.8- msw-unicode \ wx_ init_ .py, строка 45, в ‹module› из импорта wx._core * Файл C: \ Python27 \ ArcGIS10.1 \ lib \ site-packages \ wx-2.8-msw -unicode \ wx_core.py, строка 4, в ‹module› import core ImportError: Ошибка загрузки DLL:% 1 не является допустимым приложением Win32. - person default_noob_network; 12.05.2013
comment
Получаете ли вы эту ошибку при попытке импортировать wx в окно Python или импортировать его в расширение надстройки с помощью метода запуска? Вы должны точно следовать инструкциям Седерхольма, иначе вы получите всевозможные подобные ошибки. Импортируйте wx в расширение с методом запуска, и вы уже в пути. - person MikeHunter; 12.05.2013
comment
Хорошо - наконец-то появилось расширение для отображения в Arc, и кнопка, похоже, хочет нормально работать. Я получаю трассировку: строка 29 в onClick, если не WATCHER.timer.IsRunning (): AttributeError: объект 'NoneType' не имеет атрибута 'timer' - person default_noob_network; 12.05.2013
comment
Вам нужно будет перейти в диспетчер надстроек и загрузить надстройку. Затем перезапустите Arcmap. Сделайте это один раз, и он должен автоматически загрузиться на эту машину. - person MikeHunter; 12.05.2013
comment
И проверьте файл config.xml в надстройке. В разделе "Расширения" для свойства автозагрузки должно быть установлено значение "истина". - person MikeHunter; 12.05.2013
comment
Я проверил файл congig.xml, все нормально. Расширение нормально загружается в Arc, и надстройка также загружается в Arc OK. Сейчас мои варианты ООП все еще находятся в зачаточном состоянии, но, судя по тому AttributeError, который я получаю, похоже, проблема с 'WATCHER.timer'. Могу я спросить вас, что именно делает WATCHER? И почему я могу получить сообщение об отсутствии атрибута «таймер»? - person default_noob_network; 12.05.2013
comment
пожалуйста, ознакомьтесь с моими изменениями, которые включают мой скрипт в его текущем состоянии. При необходимости я могу включить config.xml. Я попробовал ваше последнее предложение, я тоже не смог заставить его работать. - person default_noob_network; 13.05.2013

Вы можете использовать RefreshTOC или Метод RefreshActiveView. Просто добавьте таймер

person Rachel Gallen    schedule 11.05.2013