【IDL】IDL 8.4 文件监视系统体验

注:此函数为 IDL 8.4 新增功能,请在 IDL 8.4及更高版本运行此代码。

IDL 8.4新增的 FOLDERWATCH 函数可以实现监视文件夹的功能。当文件夹发生变化时,会自动调用用户自定义的回调函数。

这里就和大家一起来体验一下 FOLDERWATCH的功能。从帮助中,我们可以获知此函数其实是一个类,具备如下几种方法:

  • FolderWatch::Init —— 对象初始化
  • FolderWatch::Check —— 检查是否正在监视某文件夹
  • FolderWatch::Start —— 开始监视指定文件夹
  • FolderWatch::Stop —— 停止监视

具体用法可参考帮助内容。

下面以一个具体实例演示FOLDERWATCH函数的功能。在此代码中,具备人机交互界面,可以实现如下功能:

  • 输入监视路径:单击此按钮,在弹出面板中选择要监视的文件夹路径,会显示在后方的文本控件中。
  • 开始监视:单击此按钮,开始监视指定文件夹。
  • 停止监视:单击此按钮,停止监视指定文件夹。
  • 日志列表:在日志列表中,可以看到对指定文件夹内文件的操作情况(修改、删除和添加)。右键菜单“清除日志”可以清除日志列表。
  • 状态栏:显示目前监视状态,如正在监视中、已停止监视。

通过此代码可以学习如下IDL开发知识:

1. 用户界面搭建方法、居中显示界面等;

2. 事件处理方法,如按钮事件与状态设置、右键菜单实现方法、程序关闭事件等;

3. Folderwatch 函数使用方法;

4. LIST 链表使用方法;

5. IDL中时间和日期相关处理函数,以及字符串处理技巧。


如下图所示,为程序运行效果图。 

图:测试效果图

源代码下载地址:http://pan.baidu.com/s/1kTmRKj1

 

附源代码如下:

;+
; :Description:
;   测试 IDL 8.4 新增的文件监视系统.
;
; :Author: duhj@esrichina.com.cn
;-
 
PRO example_folderwatch_event, ev
 ;
 COMPILE_OPT idl2
 ; 获取信息
 WIDGET_CONTROL, ev.TOP, GET_UVALUE=pState
 ; 判断事件类型
  tag_name = TAG_NAMES(ev, /STRUCTURE_NAME)
 ; 在关闭窗体时的事件处理
 CASE tag_name OF
 
   'WIDGET_KILL_REQUEST': BEGIN
     ; 关闭程序事件
     result = DIALOG_MESSAGE('是否停止监视,并退出?',/QUESTION)
     CASE result OF
       'Yes': BEGIN
         ; 如果 Folderwatch 对象有效,则停止监测,并销毁对象
         IF OBJ_VALID(((*pState).FW)) THEN BEGIN
           ((*pState).FW).STOP
           OBJ_DESTROY, (*pState).FW
         ENDIF
         ; 退出系统
         WIDGET_CONTROL, ev.TOP, /DESTROY
       END
       'No':
       ELSE:
     ENDCASE
     RETURN
   END
   ; 右键菜单
   'WIDGET_CONTEXT': BEGIN
     contextBase = WIDGET_INFO(ev.TOP, find_by_uname = 'contextMenu')
     WIDGET_DISPLAYCONTEXTMENU, ev.ID, ev.X, ev.Y, contextBase
   END
   ELSE:
 ENDCASE
 ; 通过 uname 进行事件处理
  uname = WIDGET_INFO(ev.ID, /UNAME)
 ;
 CASE uname OF
   ; "开始监视"按钮响应事件
   'Start': BEGIN
     ; 获取监测文件夹路径
     WIDGET_CONTROL, (*pState).WTEXTPATH, GET_VALUE=inPath
     IF inPath EQ '' THEN RETURN
     ; 初始化监测对象,开始监测
     FW = FOLDERWATCH(inPath, 'MyCallback', /RECURSIVE, $
       USER_DATA=ev.TOP)
     (*pState).FW = FW
     ; 设置对应按钮状态(可用或不可用),以及当前监视状态
     WIDGET_CONTROL, (*pState).WSTART, SENSITIVE=0
     WIDGET_CONTROL, (*pState).WSTOP, SENSITIVE=1
     WIDGET_CONTROL, (*pState).WSTATUS, set_value='状态:正在监视中...'
 
   END
   ; "停止监视"按钮响应事件
   'Stop': BEGIN
     ; 设置对应按钮状态(可用或不可用),以及当前监视状态
     WIDGET_CONTROL, (*pState).WSTOP, SENSITIVE=0
     WIDGET_CONTROL, (*pState).WSTART, SENSITIVE=1
     WIDGET_CONTROL, (*pState).WSTATUS, set_value='状态:已停止监视'
     ; 停止监测
     ((*pState).FW).STOP
   END
   ; "输入监视路径"按钮响应事件
   'Input': BEGIN
     ; 通过对话框选择需要监视的文件夹路径
     inPath = DIALOG_PICKFILE(TITLE='选择需要监视的文件夹', $
       /DIRECTORY)
     IF inPath EQ '' THEN RETURN
     ; 将路径显示在 文本框 中
     WIDGET_CONTROL, (*pState).WTEXTPATH, SET_VALUE=inPath
   END
   ; 日志列表右键菜单"清除日志"按钮响应事件
   'Clear': BEGIN
     ;
     ((*pState).LOGS).REMOVE, /all
     ; 将日志信息显示在 WIDGET_LIST 中
     WIDGET_CONTROL, (*pState).WLOGLIST, SET_VALUE=''
   END
   ELSE:
 ENDCASE
END
 
;文件监视回调函数
PRO MyCallback, obj, data
 
 COMPILE_OPT IDL2
 ; 计算当前日期,并格式化为 字符串 类型,用于日志输出
 caldat,SYSTIME(/julian),month,day,year,hour,minute,second
  date = [year,month,day]
  time = [hour,minute,second]
  datestr = STRJOIN(STRTRIM(date, 2), '-')
  timestr = STRJOIN(STRING(FIX(time), FORMAT='(I02)'), ':')
 ; 对字符串进行处理
  ret = datestr + " " + timestr + ""
 ; 判断文件的3中操作类型
 IF data.ADDED THEN ret += ' 添加操作 '
 IF data.MODIFIED THEN ret += ' 修改操作 '
 IF data.REMOVED THEN ret += ' 移除操作 '
  ret += '"'+data.FILE+'"'
 
 ; 在 Folderwatch 的 User_data 中存储了 ev.top,获取信息
 WIDGET_CONTROL, obj.USER_DATA, GET_UVALUE=pState
 ; 将当前状态字符串添加到 历史记录 中
 ((*pState).LOGS).ADD, ret
 ; 日志信息由 List 转换为 字符串数组
  Logs = ((*pState).LOGS).toarray()
 ; 将日志信息显示在 WIDGET_LIST 中
 WIDGET_CONTROL, (*pState).WLOGLIST, SET_VALUE= Logs, $
   SET_LIST_TOP=(((*pState).LOGS).Count()-15)
 
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MAIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PRO example_folderwatch
 
 COMPILE_OPT IDL2
 ; 构建主界面
  FONT = 'Microsoft Yahei*18'
  tlb = WIDGET_BASE(title='IDL中的文件监视系统', /COLUMN, $
   XOFFSET=500, YOFFSET=300, TLB_FRAME_ATTR=1, $
   /TLB_KILL_REQUEST_EVENTS, map=0)
  wBase = WIDGET_BASE(tlb, /ROW)
  wPath = WIDGET_BUTTON(wBase, VALUE='输入监视路径', $
   UNAME='Input', FONT=FONT)
  wTextPath = WIDGET_TEXT(wBase, VALUE='', XSIZE=65, $
   FONT=FONT)
  wStart = WIDGET_BUTTON(wBase, VALUE='开始监视', $
   UNAME='Start', FONT=FONT)
  wStop = WIDGET_BUTTON(wBase, VALUE='停止监视', $
   UNAME='Stop', SENSITIVE=0, FONT=FONT)
  wLogList = WIDGET_LIST(tlb, YSIZE=15, XSIZE=110, $
   FONT=FONT, /CONTEXT_EVENTS)
 ; 右键菜单,用于清除日志
 contextBase = WIDGET_BASE(wLogList, /CONTEXT_MENU, $
   UNAME='contextMenu')
  wClear = WIDGET_BUTTON(contextBase, VALUE=' 清除日志', $
   UNAME='Clear', FONT=FONT)
 
  wStatus = WIDGET_LABEL(tlb, VALUE='状态:已停止监视', $
   /ALIGN_LEFT, FONT=FONT)
 
 WIDGET_CONTROL, tlb, /REALIZE
 ; 居中显示界面
 DEVICE, get_screen_size=ss
  info = WIDGET_INFO(tlb, /GEOMETRY)
  tlb_XY = [info.SCR_XSIZE, info.SCR_YSIZE]
  offset = [ss-tlb_XY]/2
 WIDGET_CONTROL, tlb, XOFFSET=offset[0],$
   YOFFSET=offset[1]
 WIDGET_CONTROL, tlb, /map
 ; 将需要的信息保存在tlb的uvalue中
  pState = {WPATH:wPath,  $
   WTEXTPATH:wTextPath,  $
   WSTART:wStart,       $
   WSTOP:wStop,         $
   WLOGLIST:wLogList,   $
   WSTATUS:wStatus,     $
   FW:OBJ_NEW(),        $
   LOGS:LIST()}
 WIDGET_CONTROL, tlb, SET_UVALUE=PTR_NEW(pState)
 ; 事件管理
 XMANAGER, 'example_folderwatch', tlb, /NO_BLOCK
END

 

posted @   ENVI-IDL技术殿堂  阅读(368)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示