首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何制作一个圆角的tkinter画布矩形?

如何制作一个圆角的tkinter画布矩形?
EN

Stack Overflow用户
提问于 2017-05-22 01:08:21
回答 3查看 19.1K关注 0票数 14

我想创建一个圆角矩形。我使用的是tkinter的canvas。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-05-22 01:57:49

为tobias的方法提供了另一种方法,实际上是用一个多边形来做。

这样做的好处是,如果您担心优化,则可以成为一个画布对象,或者不必担心引用单个对象的标记系统。

代码有点长,但非常基础,因为它只是利用了这样的想法,即在平滑多边形时,可以给出相同的坐标两次来“阻止”平滑的发生。

这是一个可以做到的例子:

代码语言:javascript
复制
from tkinter import *
root = Tk()
canvas = Canvas(root)
canvas.pack()

def round_rectangle(x1, y1, x2, y2, radius=25, **kwargs):
        
    points = [x1+radius, y1,
              x1+radius, y1,
              x2-radius, y1,
              x2-radius, y1,
              x2, y1,
              x2, y1+radius,
              x2, y1+radius,
              x2, y2-radius,
              x2, y2-radius,
              x2, y2,
              x2-radius, y2,
              x2-radius, y2,
              x1+radius, y2,
              x1+radius, y2,
              x1, y2,
              x1, y2-radius,
              x1, y2-radius,
              x1, y1+radius,
              x1, y1+radius,
              x1, y1]

    return canvas.create_polygon(points, **kwargs, smooth=True)

my_rectangle = round_rectangle(50, 50, 150, 100, radius=20, fill="blue")

root.mainloop()

使用此函数,您可以只提供矩形的法线坐标,然后指定在角落中舍入的“半径”。使用**kwargs意味着您可以传递fill="blue"等关键字参数,就像通常使用create_方法一样。

虽然坐标看起来很复杂,但它只是有条不紊地绕到“矩形”中的每个点,给每个非角点两次。

如果你不介意很长的一行代码,你可以把所有的坐标放在一行上,使函数只有2行(!)。这看起来像这样:

代码语言:javascript
复制
def round_rectangle(x1, y1, x2, y2, r=25, **kwargs):    
    points = (x1+r, y1, x1+r, y1, x2-r, y1, x2-r, y1, x2, y1, x2, y1+r, x2, y1+r, x2, y2-r, x2, y2-r, x2, y2, x2-r, y2, x2-r, y2, x1+r, y2, x1+r, y2, x1, y2, x1, y2-r, x1, y2-r, x1, y1+r, x1, y1+r, x1, y1)
    return canvas.create_polygon(points, **kwargs, smooth=True)

这将产生以下内容(请注意,这是一个画布对象):

如果要在创建矩形后更新其位置,可以使用如下函数(如果在与原始canvas对象相同的范围内):

代码语言:javascript
复制
def update_rectangle_coords(round_rect, x1, y1, x2, y2, r=25):
    points = (x1+r, y1, x1+r, y1, x2-r, y1, x2-r, y1, x2, y1, x2, y1+r, x2, y1+r, x2, y2-r, x2, y2-r, x2, y2, x2-r, y2, x2-r, y2, x1+r, y2, x1+r, y2, x1, y2, x1, y2-r, x1, y2-r, x1, y1+r, x1, y1+r, x1, y1)
    canvas.coords(round_rect, *points)

因此,要更新my_rectangle的位置(来自第一个代码示例),我们可以这样说:

代码语言:javascript
复制
update_rectangle_coords(my_rectangle, 20, 20, 100, 100)
票数 30
EN

Stack Overflow用户

发布于 2017-05-22 01:42:05

对于这一点,似乎没有内置的方法。最接近的是带有smooth=1的polyline,但它看起来仍然更像一个旧电视屏幕,两边也略有弯曲。

相反,您可以定义一个辅助函数,将直线和圆弧中的圆角矩形组合在一起:

代码语言:javascript
复制
def rounded_rect(canvas, x, y, w, h, c):
    canvas.create_arc(x,   y,   x+2*c,   y+2*c,   start= 90, extent=90, style="arc")
    canvas.create_arc(x+w-2*c, y+h-2*c, x+w, y+h, start=270, extent=90, style="arc")
    canvas.create_arc(x+w-2*c, y,   x+w, y+2*c,   start=  0, extent=90, style="arc")
    canvas.create_arc(x,   y+h-2*c, x+2*c,   y+h, start=180, extent=90, style="arc")
    canvas.create_line(x+c, y,   x+w-c, y    )
    canvas.create_line(x+c, y+h, x+w-c, y+h  )
    canvas.create_line(x,   y+c, x,     y+h-c)
    canvas.create_line(x+w, y+c, x+w,   y+h-c)

示例:

代码语言:javascript
复制
import tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()
rounded_rect(canvas, 20, 20, 60, 40, 10)
root.mainloop()

您也可以提供另一个**options参数来设置各个部分的线宽、颜色等,但这样做的问题是,直线和圆弧使用不同的线条颜色参数(分别为filloutline )。此外,如果想要填充圆角矩形,则必须使用多个矩形将其指定为第二种方法。

票数 7
EN

Stack Overflow用户

发布于 2020-04-12 03:57:21

我知道这篇文章已经有了一个公认的矩形答案。但对于那些寻找圆角多边形(显然包括矩形)的人来说,我基于@SneakyTutle的答案编写了这段代码。

代码语言:javascript
复制
roundPolygon(x_array, y_array, sharpness, **kwargs)

结果

其背后的逻辑是启用平滑并将子点放置在顶点旁边。这样,只有角将是圆角,而多边形的其余部分保持平坦。

代码语言:javascript
复制
from tkinter import *
root = Tk()
canvas = Canvas(root, width = 1000, height = 1000)
canvas.pack()

def roundPolygon(x, y, sharpness, **kwargs):

    # The sharpness here is just how close the sub-points
    # are going to be to the vertex. The more the sharpness,
    # the more the sub-points will be closer to the vertex.
    # (This is not normalized)
    if sharpness < 2:
        sharpness = 2

    ratioMultiplier = sharpness - 1
    ratioDividend = sharpness

    # Array to store the points
    points = []

    # Iterate over the x points
    for i in range(len(x)):
        # Set vertex
        points.append(x[i])
        points.append(y[i])

        # If it's not the last point
        if i != (len(x) - 1):
            # Insert submultiples points. The more the sharpness, the more these points will be
            # closer to the vertex. 
            points.append((ratioMultiplier*x[i] + x[i + 1])/ratioDividend)
            points.append((ratioMultiplier*y[i] + y[i + 1])/ratioDividend)
            points.append((ratioMultiplier*x[i + 1] + x[i])/ratioDividend)
            points.append((ratioMultiplier*y[i + 1] + y[i])/ratioDividend)
        else:
            # Insert submultiples points.
            points.append((ratioMultiplier*x[i] + x[0])/ratioDividend)
            points.append((ratioMultiplier*y[i] + y[0])/ratioDividend)
            points.append((ratioMultiplier*x[0] + x[i])/ratioDividend)
            points.append((ratioMultiplier*y[0] + y[i])/ratioDividend)
            # Close the polygon
            points.append(x[0])
            points.append(y[0])

    return canvas.create_polygon(points, **kwargs, smooth=TRUE)

my_rectangle = roundPolygon([50, 350, 350, 50], [50, 50, 350, 350], 10 , width=5, outline="#82B366", fill="#D5E8D4")
my_triangle = roundPolygon([50, 650, 50], [400, 700, 1000], 8 , width=5, outline="#82B366", fill="#D5E8D4")

root.mainloop()

我想不出一个好的方法来使锐度正常化。无论如何,2到10之间的值在任何情况下都是合适的。您可以随意更改代码。

为了直观起见,对于带有sharpness=8的三角形,for循环的结果代码如下所示。正如您可能注意到的,如果清晰度为2,则子点将放置在顶点的中间。

代码语言:javascript
复制
points = [
      # Begin vertex
      x[0], y[0],
      # Between vertices
      (7*x[0] + x[1])/8, (7*y[0] + y[1])/8,
      (7*x[1] + x[0])/8, (7*y[1] + y[0])/8,
      # Vertex
      x[1], y[1],
      # Between vertices
      (7*x[1] + x[2])/8, (7*y[1] + y[2])/8,
      (7*x[2] + x[1])/8, (7*y[2] + y[1])/8,
      # Vertex
      x[2], y[2],
      # Between vertices
      (7*x[2] + x[0])/8, (7*y[2] + y[0])/8,
      (7*x[0] + x[2])/8, (7*y[0] + y[2])/8,
      # End/Begin vertex
      x[0], y[0]
    ]
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44099594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档