3

当使用 python 和 win32com 自动化 Adob​​e 软件时,会遇到传递二维坐标数组的问题。如果看一下 Adob​​e 为 Visual Basic (VB) 提供的代码,它很简单。在 Illustrator 中绘制线条的简化示例如下所示:

Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add

Set pathItem = docObj.PathItems.Add
    pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))

现在天真的假设是 VB 代码可以通过将其转换为 python 如下:

from win32com.client import Dispatch

appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )

显然,这并不容易,python 发出一个错误说“仅支持维度为 1 的数组”。现在我知道数组数组和二维数组之间是有区别的。所以问题是我如何强制 python 制作一个正确类型的数组?

我尝试制作自己的 VARIANT 类型,但惨遭失败。我也为此查看了ctypes。有没有人遇到过同样的问题,可以解释一下吗?

PS:

我知道这个问题可以通过使用来规避:

pathItem = docObj.PathItems.Add()
for point in (  [0.0,0.0], [20.0,20.0] ):
    pp = pathItem.PathPoints.Add() 
    pp.Anchor = point

但也有类似的情况,实际上这不起作用。无论如何,重点是为学生编写移植指南,以便尽可能接近初衷会更好。

4

2 回答 2

8

这是实际使用win32com模块的替代解决方案。碰巧IllustratorPhotoshop的数组类型是变体类型的单个数组。其中变体类型也是一个数组。还有其他应用程序(例如solidworks)使用相同的策略。您可以强制 win32com 使用以下代码制作变体类型:

from win32com.client import VARIANT
from pythoncom import VT_VARIANT

def variant(data):
    return VARIANT(VT_VARIANT, data)

不需要总是在任何地方都输入变体会很方便,因此您可以只使用一个 python 数组并使用以下内容制作每个子元素变体:

import collections

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

所以最后我的完整代码如下所示:

from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections


appObj = Dispatch("Illustrator.Application")  
docObj = appObj.Documents.Add()

def variant(data):
    return VARIANT(VT_VARIANT, data)

def vararr(*data):
    if (  len(data) == 1 and 
          isinstance(data, collections.Iterable) ):
        data = data[0]
    return map(variant, data)

pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] )  )

#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] )  )

是的,这可以通过comtypes完成,但这回答了我如何在win32com中执行此操作的真正问题。此外,使用 win32com 也是有原因的,例如能够生成常量。所以在很长一段时间后,我终于找到了真正让我困惑的问题的答案。希望这可以帮助某人。

于 2013-07-26T21:56:11.453 回答
2

我在尝试使用 win32com 确定选择区域时遇到了同样的问题。我发现使用 comtypes 而不是 win32com 访问 Photoshop 彻底解决了多维数组问题。

我认为一维数组问题是win32com的一个限制,但我可能错了。

你可以在这里获得 comtypes:http: //sourceforge.net/projects/comtypes/

Tech Artists Org上有一篇关于这个问题的帖子,值得一看。

这是使用上面链接的技术艺术家论坛帖子中的 comtypes 传递数组的示例。路径点的实现应该类似。

import comtypes.client
ps_app = comtypes.client.CreateObject('Photoshop.Application') 
# makes a new 128x128 image
ps_app.Documents.Add(128, 128, 72)

# select 10x10 pixels in the upper left corner
sel_area = ((0, 0), (10, 0), (10, 10), (0, 10), (0, 0))
ps_app.ActiveDocument.Selection.Select(sel_area)
于 2012-04-16T01:54:02.687 回答