获取以已知宽度创建的 tkinter canvas 线的每个像素的 canvas 坐标

Get canvas coordinate of every pixel of a tkinter canvas line created with a known width

我想获取在 tkinter canvas 中以给定宽度绘制的线条的每个像素的 canvas 坐标。

之前有一个关于这个问题的 post,给出的答案是无法从 tkinter 获得信息。[1]Tkinter: save coordinates of a drawn line of a given width

但是,tkinter 为用户提供了在 canvas 上标记任何绘制的项目的能力,并且还能够删除标记的项目。这不应该意味着 tkinter 必须为标记项目创建一个数组变量来存储标记项目每个像素的 canvas 坐标,以便用户可以在需要时 remove/hide/show 标记项目吗?如果这个推理是正确的,从理论上讲,如果用户有权访问 tkinter 数组变量,则用户应该能够提取标记绘制项目的每个像素的 canvas 坐标。

我想请教以下问题:

  1. 我上面的推理是否正确?
  2. 有人知道如何使用 tkinter 命令或 不然呢?

无法在 tkinter 上获取项目的像素信息 canvas。要获取信息,您需要实现一个新的 canvas 项目方法(在 C 中),并重新编译 tk 和 tkinter 以供您自己使用。即使那样,我也不确定你能做你想做的事。最终,canvas 代码调用 X11 绘图原语——具体来说,在线条的情况下是 XDrawLines——我认为 returns 不是绘制的实际像素。

如果您想修改 canvas 源代码,这里是 tk 源代码树的主干 link:http://core.tcl.tk/tk/dir?ci=trunk&name=generic。您可能需要修改的文件 tkCanvLine.c,您应该在其中查找函数 DisplayLine

在不深入了解 X11 绘图基元的细节的情况下,我在我的 python & tkinter 代码中编写了一个方法来捕获 tkinter canvas 行的每个像素的 canvas 坐标以已知宽度创建。它缺乏正式的证据,但目视检查似乎表明它有效。我在下面分享我的研究和代码。希望它能帮助 tkinter 用户。欢迎提出改进建议或反馈意见。

假设:

  1. 线宽像素数为奇数。
  2. 三种像素表示方式用于绘制线宽 像素:(a) 垂直型 (|),(b) 水平型 (_) & (c) 对角线类型 (/) & ()。我观察了这些线宽 tk.canvas.create_line 处于活动状态时的表示。
  3. 判断线宽像素类型的标准 表示是基于相对位置的梯度 在一条直线的两点之间。

Line Width Pixel Representation Criteria:

Examples:

代码:

def linewidthpixels(self, width, Acol, Arow, Bcol, Brow):
    """
    This method attempts to replicate how tk.canvas.createline creates a
    line with a given width on tk.canvas. The line width's orientation is a
    function of the gradient of the line. Verification was done by visual 
    comparison; formal proof lacking.

    Input Mandatory Argument:
    -------------------------
    width - width of line including its center pixel (in pixel units).
    Acol  - line 1st point column coordinate (x-axis).
    Arow  - line 1st point row coordinate (y-axis).
    Bcol  - line 2nd point column coordinate (x-axis).
    Brow  - line 2nd point row coordinate (y-axis).

    Internal Variables:
    -------------------------
    swidth - half the width of line excluding its center pixel (in pixel units).

    Return Variable:
    ----------------
    linepixels - a numpy 1D array consisting the (col,row) position [] of every pixel
                 used to represent a line with a given width.

    Created: 20th Jan 2016
    Amended: 21st Jan 2016

    Acknowledgement: Kindly acknowledge author when using this code (with or without modifications).
    """
        print('def linewidthpixels(self, width, Acol, Arow, Bcol, Brow):')
        print ('width, Acol, Arow, Bcol, Brow =', width, Acol, Arow, Bcol, Brow)
        # 1. Initialise return variable
        linepixels = np.array([], dtype=np.uint16)
        # 2. Calculate the number of side pixels given to the line
        swidth = int(abs((width-1)/2))
        print('swidth =', swidth)
        # 3. Calculate gradient (m) of the line (B: endpoint, A: startpoint)
        if (Bcol - Acol) != 0: # When m is finite
            m = (Brow - Arow) / (Bcol - Acol)
        else: # when m is infinite
            m = float('Infinity')
        print ('m =', m)
        # 4. Store A: starpoint, it is the centre pixel of the line width
        linepixels = np.array([Acol, Arow])
        # 5. Determine and store the coordinates of the pixels of the line width
        if width != 1: # line width > 1 pixel wide
            if m > -0.5 and m < 0.5: # Linewidth type = |
                print('Linetype = |')
                for k in range(1,swidth+1,1):
                    linepixels = np.append(linepixels, [[Acol, Arow+k], [Acol, Arow-k]])
            elif m >= 0.5 and m < 2.0: # Linewidth type = /
                print('Linetype = /')
                for k in range(1,swidth+1,1):
                    linepixels = np.append(linepixels, [[Acol+k, Arow-k], [Acol-k, Arow+k]])
            elif m > -2.0 and m <= -0.5: # Linewidth type = \
                print('Linetype = \')
                for k in range(1,swidth+1,1):
                    linepixels = np.append(linepixels, [[Acol-k, Arow-k], [Acol+k, Arow+k]])
            else: # Linewidth type = --
                print('Linetype = --')
                for k in range(1,swidth+1,1):
                    linepixels = np.append(linepixels, [[Acol+k, Arow], [Acol-k, Arow]])
        print ('linepixels =', linepixels)
        print ('Size of linepixels =', linepixels.size)
        return linepixels