How to make a tkinter rectangle rectangle with rounded corners?

I would like to create a rounded rectangle. I am using canvas from tkinter.

+3


source to share


2 answers


While suggesting an alternative approach to the Tobiz method, it would really be to do it with a single polygon.

This will have the advantage of being a single canvas object if you are concerned with optimization or shouldn't have to worry about the tagging system for accessing a single object.

The code is a little longer, but very simple, as it just uses the idea that when smoothing a polygon, you can give the same coordinate twice to "stop" the smooth situation.

This is an example of what can be done:

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()

      

Using this function, you can simply provide the normal coordinates that you would point to the rectangle and then specify a "radius" rounded at the corners. Usage **kwargs

means you can pass keyword arguments fill="blue"

like you normally would with the method create_

.



Although the coordinates look complicated, they just methodically walk to each point of the "rectangle", giving each non-angular point twice.

If you don't mind a rather long line of code, you can put all coordinates on one line, making the function just two lines (!). It looks like this:

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)

      

This results in the following (note that this is the ONE canvas object):

Rounded rectangle created by function

+7


source


There doesn't seem to be a built-in method for this. The closest thing will be a polyline with smooth=1

, but it still looks more like an old TV screen, and the sides are slightly curved as well.

Instead, you can define a helper function by concatenating a rounded rectangle from lines and arcs:

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)

      

Example:



import tkinter
root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()
rounded_rect(canvas, 20, 20, 60, 40, 10)
root.mainloop()

      

enter image description here

You can also specify another parameter **options

to set the line width, color, etc. for individual parts, but the problem with that is that, for example, lines and arcs use different parameters for the line color ( fill

and outline

accordingly). Also, if you want to have a filled rounded rectangle, you will need to specify this as a second method using multiple rectangles.

+4


source







All Articles