【问题标题】:Draw, Resize and Move a triangle on Canvas with Tkinter (Python)使用 Tkinter (Python) 在 Canvas 上绘制、调整大小和移动三角形
【发布时间】:2021-08-23 11:59:34
【问题描述】:

我正在尝试开发一个像 MS Paint 这样的应用程序,但我在制作必须在画布上插入不同形状的代码部分时遇到了麻烦。与此链接中的代码类似:Tkinter resize a rectange on Canvas using mouse,我尝试实现我的代码,但这次我想创建一个三角形,而不是矩形。但它不会在画布上的图像上显示三角形。 (self.b 是一张图片) 我该如何解决这个问题?以及如何将我制作的每个三角形在画布上移动到任何我想要的位置?

#Create triangle:
    
    def on_click3(self, event):
        """fires when user clicks on the background ... creates a new rectangle"""
        self.x1 = event.x
        self.y1 = event.y

        self.x2 = event.x
        self.y2 = event.y

        self.current =self.create_polygon(self.x1, self.y1, self.x2, self.y1,(self.x1+self.x2)/2,self.y2,self.x1,self.y1, width=self.thickness_entry.get(), outline=self.culoare, tags="Triangle")
        self.tag_bind(self.current, '<Button-1>', partial(self.on_click_triangle, self.current))
        self.tag_bind(self.current, '<Button1-Motion>', self.on_motion3)
        

    def on_click_triangle(self, tag, event):
        """fires when the user clicks on a rectangle ... edits the clicked on rectange"""
        self.current = tag
        x1, y1, x2, y2 = self.coords(tag)
        if abs(event.x-x1) < abs(event.x-x2):
            # opposing side was grabbed; swap the anchor and mobile side
            x1, x2 = x2, x1
        if abs(event.y-y1) < abs(event.y-y2):
             y2 = y1
                  
        event.x, event.y = x1, y1
        


    def on_motion3(self, event):
        """fires when the user drags the mouse ... resizes currently active rectangle"""
        self.coords(self.current, self.x1 ,self.y1, event.x, event.y)

    


    def instruction_triangle(self):
        self.config(cursor="crosshair")
        #self.bind("<ButtonPress-1>",self.left_but_down)
        #self.bind("<ButtonRelease-1>",self.left_but_up)
        self.tag_bind(self.b, '<Button-1>', self.on_click3)
        self.tag_bind(self.b, '<Button1-Motion>', self.on_motion3)

【问题讨论】:

  • 您要制作规则多边形还是手绘(不规则)多边形?
  • @Derek 通过该命令 create_polygon 是您可以在 tkinter 中创建三角形的唯一方法。结果,我想生成正多边形
  • 做了一个小改动(从类中传输代码时发现了一个错误)并添加了一个旋转对象。 an and si 变量选择角度和边值。

标签: python tkinter tkinter-canvas


【解决方案1】:

这是一个我已经缩减到最小状态的代码示例。

函数polygonal 允许创建从直线到圆的规则多边形。

它需要 4 个坐标并包括用于旋转的控件 angle 和从 2 到 360 的 sides

我已经包含了函数 polyside,它将接受 rectangleoval 对象并将其转换为多边形。

三个例子包括八边形、矩形和三角形。

我已经包含了一个简单的对象旋转方法。

import math
import tkinter as tk

master = tk.Tk()
master.rowconfigure(0, weight = 1)
master.columnconfigure(0, weight = 1)
canvas = tk.Canvas(
    master, cursor = "crosshair", width = 600, height = 400)
canvas.grid(row = 0, column = 0, sticky = tk.NSEW)
canvas.focus_set()
master.update()

def intdata( box, cision= 2 ):
    """intdata( box, cision=2)"""
    return [ round( x, cision ) for x in box ]

def polygonal(c, angle, sides = 6):
    """polygonal( c(x1, y1, x2, y2), angle(0-360), sides=(2-360) )"""
    stp = max(1, int( 360 / max( 2, sides ) ))
    x1, y1, r1, r2 = c[0], c[1], (c[ 2 ] - c[ 0 ]) / 2, (c[ 3 ] - c[ 1 ]) / 2
    box = []
    for ang in range(stp, 360 + stp, stp):
        za = math.radians( ang+angle)
        box.append(x1 + math.cos( za ) * r1)
        box.append(y1 + math.sin( za ) * r2)
    return intdata(box)

def polyside(item):
    if item in canvas.find_all():
        box = canvas.coords(item)
        if canvas.type(item) == "rectangle":
            return polygonal(box, 45, sides = 4)
        elif canvas.type(item) == "oval":
            return polygonal(box, 0, sides = 72)


box = polygonal( ( 102, 102, 202, 202 ), angle = 0, sides = 8)
canvas.create_polygon( box, fill = "", outline = "black" )

box = polygonal( ( 204, 102, 304, 202 ), angle = 45, sides = 4)
canvas.create_polygon( box, fill = "red", outline = "black" )

# rotating polygons
box = ( 400, 300, 500, 400 )
an, si = 45, 4

item = canvas.create_polygon(
    polygonal( box, angle = an, sides = si),
    fill = "cyan", outline = "red",
    width = 4, stipple = "gray50" )

def rotate():
    global an, si
    an = (an + 2) % 360
    canvas.coords( item, *polygonal( box, angle = an, sides = si))
    master.after( 50, rotate)

master.after( 50, rotate)
master.mainloop()

【讨论】:

  • 非常感谢您的帮助!!
  • 好一个@Ioana Braslasu。编码愉快。
最近更新 更多