Python win32com和二维数组

标签 python multidimensional-array coordinates win32com

当使用 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 发出错误提示“Only arrays with dimension 1 are supported”。现在我知道数组的数组和二维数组之间是有区别的。所以问题是我如何强制 python 制作正确类型的数组?

我尝试制作自己的 VARIANT 类型但惨遭失败。为此,我也查看了 ctypes。任何人都遇到过同样的问题并且可以阐明一些问题吗?

附言:

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

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

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

最佳答案

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

from win32com.client import VARIANT
from pythoncom import VT_VARIANT

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

如果不需要总是在任何地方都输入 variant 会很方便,所以你可以只使用一个 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 的原因,例如能够生成常量。所以经过很长一段时间我终于找到了这个真正让我困惑的问题的答案。希望这对某人有所帮助。

关于Python win32com和二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10166064/

相关文章:

c# 一个集合来保存两个arraylist

ios - 计算与位置的角度

java - Android NDK - 如何从点击获取坐标并将它们显示在 TextView 上?

python - 开发Django项目时Docker是否可以替代 'virtualenv'?

python - 尝试在 Linux 服务器上运行 jupyter 笔记本

python - numpy ndarray 是均匀的和矩形的(子数组必须具有相同的长度)因为它在引擎盖下使用 C 数组吗?

android - 如何使用 mapPoints?我需要根据矩阵移动绘制点(坐标)

python - 使用 openpyxl 插入表格

c - 如何使用数组汇总数据列表

c - 为 n 维超立方体生成距离矩阵