获取使用已知宽度创建的tkinter画布线的每个像素的画布坐标

时间:2015-12-28 07:30:51

标签: python tkinter tkinter-canvas

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

此问题上有一篇帖子,给出的答案是无法从tkinter获取通知。[1] Tkinter: save coordinates of a drawn line of a given width

但是,tkinter为用户提供了在画布上标记任何绘制项目的能力,以及删除标记项目的能力。这是否意味着tkinter必须为标记项创建一个数组变量来存储标记项的每个像素的画布坐标,以便用户可以在需要时删除/隐藏/显示标记项?如果这种推理是正确的,理论上讲,如果用户有权访问tkinter数组变量,用户应该能够提取标记绘制项的每个像素的画布坐标。

我想问下列问题:

  1. 我上面提到的推理是否正确?
  2. 有人知道如何使用tkinter命令或提取与标记画布线关联的每个像素的画布坐标 否则?

2 个答案:

答案 0 :(得分:1)

无法在tkinter画布上获取项目的像素信息。要获取实现新的canvas项方法(在C中)所需的信息,并重新编译tk和tkinter以供自己使用。即便如此,我也不确定你能做你想做的事。最终,画布代码调用X11绘图基元 - 特别是线条的XDrawLines - 我不认为它会返回绘制的实际像素。

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

答案 1 :(得分:0)

没有深入研究X11绘图基元的细节,我在python&中编写了一个方法。 tkinter代码,用于捕获使用已知宽度创建的tkinter画布线的每个像素的画布坐标。它缺乏正式的证据,但目视检查似乎表明它有效。我在下面分享我的研究和代码。希望它能帮助tkinter用户。我们赞赏有关改进或反馈的建议。

假设:

  1. 线宽具有奇数个像素。
  2. 使用三种类型的像素表示来绘制线宽 像素:(a)垂直类型(|),(b)水平类型(_)& (C) 对角线类型(/)& ()。我观察到这些线宽 tk.canvas.create_line处于活动状态时的表示。
  3. 确定线宽像素类型的标准 表示基于相对位置的梯度 在一条线的两点之间。
  4. 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