TableOfContents

Include(CPUGnav)

将Flash应用于Python项目

基于本地的Python应用程序

写在之前

这篇所说的是关于建立python调用Flash的本地应用,不同于Adobe的Apollo。

没有用到浏览器嵌入flash网页的方法,直接在pythonwin或者wxpython建立的窗口中插入Flash ocx。

因为是操作Activex控件的方式因此大概只适用于windows平台。抱歉我并未在其它平台上试过这种方法,不过linux中应该也有类似的技术。

Flash ocx介绍

Flash ocx实际上是一种COM组件开发模型(Microsoft Component Object Model),它原先是从Windows 3.x中的OLE发展过来的。现在又被改名叫做Activex。Activex是COM的一种,一般是指带有UI界面的COM。

Flash ocx的本名是叫Shockwave Flash Object,是一个Activex控件。Activex控件文件名的后缀是ocx。

原先的Shockwave包括了很多东西。被Adobe收购的MicroMedia公司的另一个产品Director的web应用就叫shockwave,它集合了视频流、Flash、shockwave 3D于一身。

对于Director我还是挺有感情的,只不过Director到了8.5以后的版本就基本不再发展了,我也渐渐不用它了。(听说Adobe收购MicroMedia以后,还会推出Director 11)

Flash ocx与外界通迅的方法

调用ocx标准COM接口IDispatch

这种方法最简单,也比较通用。

它又叫COM对象的自动化接口。使用自动化,对象就可以提供一个简单的自动化接口,这样脚本语言作者只需掌握IDispatch和几个COM应用程序接口就可以了。

pythonwin的作者 Mark Hammond 的一本书(Python Programming on Win32)就讲到了怎样用python直接操作COM对象(操作的函义包括使用和发布)。如果想深入细节的话,可以参考这本书。

Python 程序使用 win32com.client.Dispatch() 方法来创建 COM objects。 如创建一个 Flash COM object.

   1 >>> import win32com.client
   2 >>> fl = win32com.client.Dispatch("ShockwaveFlash.ShockwaveFlash.9") #Flash 9 的ProgID是ShockwaveFlash.ShockwaveFlash.9,有很多工具可以查到机器内部注册的COM组件信息

这样就得到了Flash COM object,你可以让它LoadMovie,让它Play,但是你暂时还看不到它,你得传给它一个窗口,这样它才能显示在窗口。 所幸wxpython帮我们封装了这一切,你只需要调用wx.lib.flashwin.FlashWindow类就行了。

例:

   1 import wx
   2 from wx.lib.flashwin import FlashWindow
   3 
   4 class CGui(wx.Frame):
   5     def __init__(self):
   6         wx.Frame.__init__(self, None, 101, "map", size = (800, 600), style = wx.FRAME_SHAPED)        
   7         self.flash = FlashWindow(self, style=wx.SUNKEN_BORDER, size = (800, 600))                   #用wx.lib.flashwin.FlashWindow创建窗口
   8         self.flash.LoadMovie(0, 'C:\\drop_shadow_dog.swf')                                          #播放"C:\\drop_shadow_dog.swf"的Flash影片
   9         self.flash.SetSize((800, 600));
  10     
  11     def getText(self):
  12         returnValue = self.flash.GetVariable('FlashValue')                                          #从Flash端
  13         return returnValue
  14             
  15     def setText(self, text):
  16         self.flash.SetVariable("PythonValue", text)                                                 #传给Flash变量

这些传递变量在Flash AS端都处于_root层级下。

这儿有个例子:

http://www.sephiroth.it/weblog/archives/2004/05/wxpython_and_flash_first_test.php

   1 #!/usr/bin/env python
   2 # -*- coding: utf-8 -*-
   3 import wx, sys, os
   4 import string, codecsfrom wx.lib.flashwin 
   5 import FlashWindow
   6 from wx.lib.flashwin import EVT_FSCommand
   7 #----------------------------------------
   8 class TestPanel(wx.Panel):
   9     def __init__(self, parent, base, swf):
  10         wx.Panel.__init__(self, parent, -1)
  11         self.base = base
  12         sizer = wx.BoxSizer(wx.VERTICAL)
  13         self.flash = FlashWindow(self, style=wx.SUNKEN_BORDER)
  14         dlg = wx.MessageDialog(self, "This will work only under Windows!","Warning!",wx.OK | wx.ICON_INFORMATION)
  15         dlg.Center()
  16         dlg.ShowModal()
  17         wx.BeginBusyCursor()
  18         try:
  19             self.flash.LoadMovie(0, swf)
  20         except:
  21             wx.MessageDialog(self, "could not load the swf file","Error",wx.OK | wx.ICON_ERROR).ShowModal()
  22             sys.exit(2)
  23         wx.EndBusyCursor()
  24         self.flash.Stop()
  25         self.flash.SetSize((self.flash.GetSize()[0],self.flash.GetSize()[1]))
  26         # sizer
  27         sizer.Add(self.flash, 1, wx.EXPAND)
  28         self.SetSizer(sizer)
  29         self.SetAutoLayout(True)
  30         sizer.Fit(self)
  31         sizer.SetSizeHints(self)
  32         self.SetFlashOptions()
  33         self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
  34         self.Bind(EVT_FSCommand, self.CallMethod)  ##将Flash ocx的消息事件绑定到CallMethod函数上。
  35 
  36     def SetFlashOptions(self):
  37         self.flash.menu = False
  38         self.flash._set_FlashVars("data=Server started on " + sys.platform)
  39         self.flash.Play()
  40 
  41     def OnDestroy(self, evt):
  42         if self.flash:
  43             self.flash.Cleanup()
  44             self.flash = None
  45 
  46     # Called from Flash FSCommand
  47     def CallMethod(self, evt):
  48         try:
  49             arguments = string.split(evt.args,"###")
  50             filename = arguments[0]
  51             body = arguments[1]
  52             if filename == "" or body == "":
  53                 wx.MessageDialog(self, "Please check data inserted", "An Error occurred", wx.OK | wx.ICON_INFORMATION).ShowModal()
  54             else:
  55                 dlg = wx.FileDialog(self, "Save as..." , os.getcwd(), filename, "*.*", wx.SAVE | wx.OVERWRITE_PROMPT )
  56                 if dlg.ShowModal() == wx.ID_OK:
  57                     try:
  58                         f = codecs.open(os.path.normpath(dlg.GetPath()), "w", "utf-8", "ignore")
  59                         f.write(codecs.utf_8_decode(codecs.BOM_UTF8)[0])
  60                         f.write(body)
  61                         f.close()
  62                         self.flash._set_FlashVars("data=Succesfully saved text file")
  63                     except:
  64                         wx.MessageDialog(self, "%s %s %s" % sys.exc_info(), "An Error occurred", wx.OK | wx.ICON_ERROR).ShowModal()
  65                         self.flash._set_FlashVars("data=%s %s %s" % sys.exc_info())
  66         except:
  67             wx.MessageDialog(self, "Please check data inserted","An Error occurred",wx.OK | wx.ICON_INFORMATION).ShowModal()
  68             self.flash._set_FlashVars("data=%s %s %s" % sys.exc_info())
  69 
  70 #-------------------------------------------
  71 if __name__ == '__main__':
  72     class TestFrame(wx.Frame):
  73         def __init__(self):
  74             wx.Frame.__init__(self, None, -1, "ActiveX -- Flash", size=(640, 480), style=wx.DEFAULT_FRAME_STYLE )
  75             base = os.path.normpath(os.path.abspath(os.path.dirname(sys.argv[0])))
  76             swf = os.path.normpath(os.path.join(base, "movie.swf"))
  77             self.tp = TestPanel(self, base, swf)
  78     app = wx.PySimpleApp()
  79     frame = TestFrame()
  80     frame.Center()
  81     frame.Show(True)
  82     app.MainLoop()

Flash端很简单,两句话就搞定了。

on (click) {
        fscommand("saveFile", this._parent.fnome.text + "###" + this._parent.ftesto.text)

}

这里用到了Flash的fscommand。

在Flash端点击了以后,它就会发送一个fscommand消息事件。

python端接收到了以后,由CallMethod处理。

使用Flash ExternalInterface

ExternalInterface 类是一个子系统,通过它可以轻松地实现从 ActionScript 和 Flash Player 到 HTML 页中的 JavaScript 或任何包含 Flash Player 实例的台式机应用程序的通信。 ExternalInterface 可以提供以下功能:

■  可以调用注册过的 python 函数。 从python端也可以调用注册过的Flash ActionScript函数。
■  可以传递任意数量的、具有任意名称的参数;而不是仅限于传递一个命令和一个字符串参数。
■  可以传递各种数据类型(例如 Boolean 、Number 和 String);不再仅限于 String 参数。 
■  可以接收调用值,该值将立即返回到 ActionScript(作为进行的调用的返回值)。


未完待续


反馈

PageComment2

Azureon Email: MailTo([email protected])

["技术文档分类"]