【Tkinter】角丸長方形の作り方を解説!角の丸みも変更可能!

Tkinterで角丸長方形を作る方法のアイキャッチ

   この記事の内容

  • 【結論】Tkinterで角丸長方形は作れる
  • Tkinterでの角丸長方形の作り方
  • Tkinterで長方形の一部分だけ角丸に

 

こんにちは、Youta(@youta_blog)です。

 

今回は、TkinterのCanvas上に角丸長方形を描きます。

 

すずか

Tkinterで四角形の角を丸めたいんだけど、どうすればいいの?
すこ〜しだけ座標計算をすれば、簡単にできます!

先生

 

この記事を読めば、Tkinterで角丸長方形を作れます。

もちろん、角の丸め具合は自由自在です。

角丸長方形の角の丸みを多様に変えた画像

 

本記事では、解説・確認用コード・実行結果の3点をご用意しております。

また必要に応じてコードの解説をしていますので、初心者でも安心です。

 

記事の信頼性は、確認用コードと実行結果が保証します。

少しでも疑問に感じたら、是非ともコードをコピペしてPCで確かめてみてください。

 

それでは、Tkinterで角を丸くした長方形を描く手法を見ていきましょう。

角丸長方形を作るプログラム

この章では、本記事で作るプログラム・結果を先にお見せします。

詳細は後で解説するのでご安心ください。

実装例

結論、次の9つの関数(自作)を使います。

  • flatten
  • get_arc_coords
  • get_upper_left_rounded_corner_coords
  • get_upper_right_rounded_corner_coords
  • get_lower_right_rounded_corner_coords
  • get_lower_left_rounded_corner_coords
  • get_adjustment_range
  • get_max_adjustment_range
  • get_rounded_rectangle_coords

import numpy as np


def flatten(sequence):
    result = []

    for item in sequence:
        if isinstance(item, (list, tuple, range, dict, set, frozenset)):
            result.extend(flatten(item))
        else:
            result.append(item)

    return result


def get_arc_coords(center, size, angle_range, is_radian=False, num_coords=None):
    center_x, center_y = center
    radius_x, radius_y = np.array(size) / 2
    start_angle, end_angle = angle_range

    if not is_radian:
        start_angle = np.radians(start_angle)
        end_angle = np.radians(end_angle)

    if num_coords is None:
        angle_diff_radians = end_angle - start_angle
        angle_diff_degrees = np.degrees(angle_diff_radians)
        signed_num_coords = int(angle_diff_degrees)
        num_coords = abs(signed_num_coords)

    angle = np.linspace(start_angle, end_angle, num_coords)

    xs = radius_x * np.cos(angle) + center_x
    ys = radius_y * np.sin(angle) + center_y

    points = []
    for x, y in zip(xs, ys):
        points.extend((x, y))

    return points


def get_upper_left_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[0] + radius, bbox_coords[1] + radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (-180, -90)

    return get_arc_coords(center, size, angle_range)


def get_upper_right_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[2] - radius, bbox_coords[1] + radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (-90, 0)

    return get_arc_coords(center, size, angle_range)


def get_lower_right_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[2] - radius, bbox_coords[3] - radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (0, 90)

    return get_arc_coords(center, size, angle_range)


def get_lower_left_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[0] + radius, bbox_coords[3] - radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (90, 180)

    return get_arc_coords(center, size, angle_range)


def get_max_adjustment_range(bbox_coords):
    width = abs(bbox_coords[0] - bbox_coords[2])
    height = abs(bbox_coords[1] - bbox_coords[3])

    return min(width, height) / 2


def get_adjustment_range(bbox_coords, ratio):
    return get_max_adjustment_range(bbox_coords) * ratio


def get_rounded_rectangle_coords(bbox_coords, ratio=1/3):
    radius = get_adjustment_range(bbox_coords, ratio)

    return flatten(
        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius),
            get_upper_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_left_rounded_corner_coords(bbox_coords, radius),
        ]
    )

 

現段階ではわからなくても問題ないです。

実行例

先ほどのプログラムの下に次のコードを追記し、実行してみます。

if __name__ == '__main__':
    import tkinter as tk

    # 画面作成
    root = tk.Tk()

    # キャンバス作成・配置
    canvas = tk.Canvas(root, width=500, height=500)
    canvas.pack()

    # 角丸長方形作成
    shape_coords = get_rounded_rectangle_coords((50, 100, 450, 400))
    canvas.create_polygon(shape_coords)

    # 画面表示
    root.mainloop()

 

実行結果です。

 

すずか

これこれ!こういうの欲しかった〜!
次の章からは、どうやって角丸長方形を作っているかを解説しますね。

先生

角丸長方形の作り方

Tkinterで角丸長方形を描くにはどうすれば良いでしょう?

結論、create_polygonメソッドを利用します。

 

create_polygonメソッドは、Canvasクラスに用意された、多角形を描画するメソッドです。

引数に渡した座標同士を繋ぎ、多角形を描きます。

 

例えば、座標を4つ渡して四角形を描きましょう。

canvas.create_polygon((x1, y1), (x2, y2), (x3, y3), (x4, y4))

 

必然的に、手順は次の\(2\)ステップとなります。

  1. 図形の頂点の座標を計算する。
  2. create_polygonメソッドに座標を渡す。

 

先ほどのコードだとこの部分。

    # 角丸長方形作成
    shape_coords = get_rounded_rectangle_coords((50, 100, 450, 400))
    canvas.create_polygon(shape_coords)

上から順に、ステップ\(1\)・\(2\)です。

 

create_polygonメソッドは元々Tkinterにあるので「そういうものだ」としか言えません。

ということは「そもそもメソッドに渡す座標をどう求めるか?」が問題です。

したがって、本記事ではステップ\(1\)にフォーカスして話を進めます。

 

では、角丸長方形の頂点の座標を求めるにはどうすれば良いでしょう。

結論、次の\(2\)つを考えます。

 

文言だけでは意味が分かりませんよね。

そこで、今からこの\(2\)つについて丁寧に解説していきます。

4隅のカーブの座標を求める

まずは、角丸長方形の丸い角の座標を求めます。

角丸長方形をcreate_polygonメソッドで描画するにあたり、座標を計算する部分の画像

すずか

え?座標って図形の外周全部のじゃなくて?

そこまでする必要はありませんよ。

先生

 

なぜなら、create_polygonメソッドは指定された座標同士を順に繋いで図形を描くからです。

create_polygonメソッドが、座標間を結んで多角形を描く画像

 

したがって、図形の外周すべてではなく、角の部分の座標を計算するだけで良いのです。

水色の部分は勝手に埋められます。

すずか

理屈はわかったけど、でも丸い部分の座標なんて計算できないよ!
円の媒介変数表示を利用すれば楽勝ですよ。

先生

 

そもそも、角丸長方形の角は円の一部です。

角丸長方形の左上の角の拡大画像

 

したがって、円の媒介変数表示を使えば、簡単に座標を取得できます。

円の媒介変数表示を解説する画像

例えば、\(\theta\)を\(0^\circ{}\)〜\(90^\circ{}\)の範囲で動かせば、円の右上の座標が取れます。

先生

すずか

媒介変数表示?なんか難しそう。

 

ご安心ください。

別記事にて、円周上の座標を求めるプログラムを既に作ってあります。

>>【Python】円周・楕円周上の座標を求める方法を徹底解説!プログラム付き!

 

コードはこちらです。


import numpy as np


def get_arc_coords(center, size, angle_range, is_radian=False, num_coords=None):
    center_x, center_y = center
    radius_x, radius_y = np.array(size) / 2
    start_angle, end_angle = angle_range

    if not is_radian:
        start_angle = np.radians(start_angle)
        end_angle = np.radians(end_angle)

    if num_coords is None:
        angle_diff_radians = end_angle - start_angle
        angle_diff_degrees = np.degrees(angle_diff_radians)
        signed_num_coords = int(angle_diff_degrees)
        num_coords = abs(signed_num_coords)

    angle = np.linspace(start_angle, end_angle, num_coords)

    xs = radius_x * np.cos(angle) + center_x
    ys = radius_y * np.sin(angle) + center_y

    points = []
    for x, y in zip(xs, ys):
        points.extend((x, y))

    return points

 

次の3つを関数に渡せば、円弧の座標など簡単に求まります。

  • center: 円の中心座標のタプル
  • size: 円のサイズ(横\(×\)縦)のタプル
  • angle_range: 弧の範囲の角度のタプル

 

例えば、引数を次のように指定します。

center = (p, q)
size = (2a, 2b)
angle_range = (0, 90)

arc_coords = get_arc_coords(center, size, angle_range)

 

arc_coordsには矢印の部分の座標が入ります。

図は楕円ですが、引数sizeを調整すれば円にできます。

先生

 

get_arc_coords関数はnumpyの関数を利用しています。

numpyをインストールしていない方は、コマンドラインから下記コマンドを入力し、インストールをお願いします。

$ pip install numpy

 

この文言が出たら完了です。

Successfully installed numpy-〇.〇〇.〇

 

それでは左上→右上→右下→左下の順に座標を計算していきましょう。

 左上カーブ

角丸長方形の左上カーブの座標を求める関数を、次のように実装しました。

def get_upper_left_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[0] + radius, bbox_coords[1] + radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (-180, -90)

    return get_arc_coords(center, size, angle_range)

 

引数は\(2\)つです。

  • bbox_coords: 境界ボックスの座標のリスト
  • radius: 左上の丸みの半径

bbox_coordsは境界ボックスの左上と右下の座標が入っています。

print(bbox_coords)
# [x1, y1, x2, y2]

print(
    bbox_coords[0],
    bbox_coords[1],
    bbox_coords[2],
    bbox_coords[3],
)
# x1, y1, x2, y2

 

関数内で行なっている処理は次の\(4\)つです。

順に解説します。

 

まずは円の中心座標を求めます。

角丸長方形の左上カーブを構成する円の中心座標を求める画像

    center = (bbox_coords[0] + radius, bbox_coords[1] + radius)

 

次に円のサイズを求めます。

角丸長方形の左上カーブを構成する円の縦横のサイズを求める画像

    diameter = radius * 2
    size = (diameter, diameter)

 

そして円弧の範囲の角度を指定します。

Tkinterの座標系は上下が反転していることにご注意ください。

角丸長方形の左上カーブを構成する円弧の角度を求める画像

    angle_range = (-180, -90)

 

最後にget_arc_coords関数に引数を渡して終了です。

    return get_arc_coords(center, size, angle_range)

 右上カーブ

角丸長方形の右上カーブの座標を求める関数を、次のように実装しました。

def get_upper_right_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[2] - radius, bbox_coords[1] + radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (-90, 0)

    return get_arc_coords(center, size, angle_range)

 

引数は\(2\)つです。

  • bbox_coords: 境界ボックスの座標のリスト
  • radius: 右上の丸みの半径

bbox_coordsは境界ボックスの左上と右下の座標が入っています。

print(bbox_coords)
# [x1, y1, x2, y2]

print(
    bbox_coords[0],
    bbox_coords[1],
    bbox_coords[2],
    bbox_coords[3],
)
# x1, y1, x2, y2

 

関数内で行なっている処理は次の\(4\)つです。

順に解説します。

 

まずは円の中心座標を求めます。

角丸長方形の右上カーブを構成する円の中心座標を求める画像

    center = (bbox_coords[2] - radius, bbox_coords[1] + radius)

 

次に円のサイズを求めます。

角丸長方形の右上カーブを構成する円の縦横のサイズを求める画像

    diameter = radius * 2
    size = (diameter, diameter)

 

そして円弧の範囲の角度を指定します。

Tkinterの座標系は上下が反転していることにご注意ください。

角丸長方形の右上カーブを構成する円弧の角度を求める画像

    angle_range = (-90, 0)

 

最後にget_arc_coords関数に引数を渡して終了です。

    return get_arc_coords(center, size, angle_range)

 右下カーブ

角丸長方形の右下カーブの座標を求める関数を、次のように実装しました。

def get_lower_right_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[2] - radius, bbox_coords[3] - radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (0, 90)

    return get_arc_coords(center, size, angle_range)

 

引数は\(2\)つです。

  • bbox_coords: 境界ボックスの座標のリスト
  • radius: 右下の丸みの半径

bbox_coordsは境界ボックスの左上と右下の座標が入っています。

print(bbox_coords)
# [x1, y1, x2, y2]

print(
    bbox_coords[0],
    bbox_coords[1],
    bbox_coords[2],
    bbox_coords[3],
)
# x1, y1, x2, y2

 

関数内で行なっている処理は次の\(4\)つです。

順に解説します。

 

まずは円の中心座標を求めます。

角丸長方形の右下カーブを構成する円の中心座標を求める画像

    center = (bbox_coords[2] - radius, bbox_coords[3] - radius)

 

次に円のサイズを求めます。

角丸長方形の右下カーブを構成する円の縦横のサイズを求める画像

    diameter = radius * 2
    size = (diameter, diameter)

 

そして円弧の範囲の角度を指定します。

Tkinterの座標系は上下が反転していることにご注意ください。

角丸長方形の右下カーブを構成する円弧の角度を求める画像

    angle_range = (0, 90)

 

最後にget_arc_coords関数に引数を渡して終了です。

    return get_arc_coords(center, size, angle_range)

 左下カーブ

角丸長方形の左下カーブの座標を求める関数を、次のように実装しました。

def get_lower_left_rounded_corner_coords(bbox_coords, radius):
    center = (bbox_coords[0] + radius, bbox_coords[3] - radius)

    diameter = radius * 2
    size = (diameter, diameter)

    angle_range = (90, 180)

    return get_arc_coords(center, size, angle_range)

 

引数は\(2\)つです。

  • bbox_coords: 境界ボックスの座標のリスト
  • radius: 左下の丸みの半径

bbox_coordsは境界ボックスの左上と右下の座標が入っています。

print(bbox_coords)
# [x1, y1, x2, y2]

print(
    bbox_coords[0],
    bbox_coords[1],
    bbox_coords[2],
    bbox_coords[3],
)
# x1, y1, x2, y2

 

関数内で行なっている処理は次の\(4\)つです。

順に解説します。

 

まずは円の中心座標を求めます。

角丸長方形の左下カーブを構成する円の中心座標を求める画像

    center = (bbox_coords[0] + radius, bbox_coords[3] - radius)

 

次に円のサイズを求めます。

角丸長方形の左下カーブを構成する円の縦横のサイズを求める画像

    diameter = radius * 2
    size = (diameter, diameter)

 

そして円弧の範囲の角度を指定します。

Tkinterの座標系は上下が反転していることにご注意ください。

角丸長方形の左下カーブを構成する円弧の角度を求める画像

    angle_range = (90, 180)

 

最後にget_arc_coords関数に引数を渡して終了です。

    return get_arc_coords(center, size, angle_range)

角の丸みをなす円の半径

角の丸みを数値で調整できるようにします。

比率は\(0\)〜\(1\)の範囲で、\(1\)に近づくほど角が丸くなります。

 

角の円の半径は、半径の最大値\(×\)比率です。

 

すずか

半径の最大値ってどこ?
境界ボックスの短い辺の半分です。

先生

 

例えば、縦\(<\)横の場合。

縦が短いので、縦の半分が半径の最大値です。

半径は\(0\)〜\(\frac{height}{2}\)の範囲で調整できます。

 

次は縦\(>\)横の場合。

横が短いので、横の半分が半径の最大値です。

半径は\(0\)〜\(\frac{width}{2}\)の範囲で調整できます。

 

最後は縦\(=\)横の場合。

縦横の長さが同じなので、一辺の長さの半分が半径の最大値です。

半径は\(0\)〜\(\frac{width}{2}\)(\(=\frac{height}{2}\))の範囲で調整できます。

 

以上を踏まえて、今から\(2\)つのプログラムを作ります。

 半径の最大値

角の円の半径の最大値を計算するプログラムです。

def get_max_adjustment_range(bbox_coords):
    width = abs(bbox_coords[0] - bbox_coords[2])
    height = abs(bbox_coords[1] - bbox_coords[3])

    return min(width, height) / 2

 

引数は境界ボックスの座標(左上・右下)です。

境界ボックスの左上と右下の座標

print(bbox_coords)
# [x1, y1, x2, y2]

print(
    bbox_coords[0],
    bbox_coords[1],
    bbox_coords[2],
    bbox_coords[3],
)
# x1, y1, x2, y2

 

戻り値は角の半径の最大値です。

 

内部では\(2\)つの処理を行っています。

順に解説します。

 

まずは境界ボックスの縦横の長さを求めます。

角丸長方形の境界ボックスの縦横の長さを求める

    width = abs(bbox_coords[0] - bbox_coords[2])
    height = abs(bbox_coords[1] - bbox_coords[3])

絶対値を取るのは、差が負になっては困るからです。

 

次に、短い方の辺の半分の長さを求めます。

 

min関数で縦横のどちらが短いかを特定し、

           min(width, height)

その辺の半分を求めて、

           min(width, height) / 2

計算結果を返して終了です。

    return min(width, height) / 2

 丸みの変更

比率に応じた角の丸みを算出するプログラムです。

def get_adjustment_range(bbox_coords, ratio):
    return get_max_adjustment_range(bbox_coords) * ratio

 

引数は次の\(2\)つです。

  • bbox_coords:  境界ボックスの座標(左上・右下)
  • radtio: 角の丸みの比率(\(0\)〜\(1\))

 

戻り値は比率を適用した角の半径です。

 

内部の処理はとても簡単。

角の半径の最大値に、比率(引数)を掛けて外に返すだけです。

    return get_max_adjustment_range(bbox_coords) * ratio

半径の最大値取得には、先ほどのget_max_adjustment_range関数を用いました。

完成

これまで作ったプログラムを統合しましょう。

角丸長方形の頂点の座標を求めるプログラムです。

def get_rounded_rectangle_coords(bbox_coords, ratio=1/3):
    radius = get_adjustment_range(bbox_coords, ratio)

    return flatten(
        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius),
            get_upper_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_left_rounded_corner_coords(bbox_coords, radius),
        ]
    )

 

引数は次の\(2\)つです。

  • bbox_coords:  境界ボックスの座標(左上・右下)
  • radtio: 角の丸みの比率(\(0\)〜\(1\))

 

戻り値は、角丸長方形の頂点の座標が入った一次元のリストです。

 

この関数内部では、順に次の\(3\)つの処理を行っています。

 比率に合う角の半径を求める

比率を元に角の半径を求めます。

get_adjustment_range関数に、角丸長方形の境界ボックスの座標と比率を渡します。

    radius = get_adjustment_range(bbox_coords, ratio)

 角のカーブの座標を求める

左上→右上→右下→左下の順に、角丸長方形の角丸部分の座標を取得します。

        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius),
            get_upper_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_left_rounded_corner_coords(bbox_coords, radius),
        ]

 

すずか

え?関数がリストに入ってるの?
見かけ上はそうですが、実は関数の戻り値が入っていますよ。

先生

 

get_〇〇_rounded_corner_coords関数は、カーブの座標(一次元リスト)を返します。

イメージはこうです。

        [
            [x1, y1, x2, y2, ..., xn, yn],  # 左上カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 右上カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 右下カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 左下カーブの座標
        ]

 座標を平坦化する

取得した座標を平坦化します。

           flatten(
        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius),
            get_upper_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_left_rounded_corner_coords(bbox_coords, radius),
        ]
    )

 

平坦化とは、多次元のリストやタプル等を一次元にすることです。

a = [[1, 2], [3, 4], [5, 6]]
print(a)
# [[1, 2], [3, 4], [5, 6]]

b = flatten(a)  # 平坦化する関数
print(b)
# [1, 2, 3, 4, 5, 6]

 

リストやタプルを平坦化する関数は、別記事にて既に作ってあります。

>>【Python】リストの平坦化(flatten)処理を徹底解説!

 

コードはこちらです。

def flatten(sequence):
    result = []

    for item in sequence:
        if isinstance(item, (list, tuple, range, dict, set, frozenset)):
            result.extend(flatten(item))
        else:
            result.append(item)

    return result

 

平坦化した座標のリストを外に返して終了です。

    return flatten(
        [
            [x1, y1, x2, y2, ..., xn, yn],  # 左上カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 右上カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 右下カーブの座標
            [x1, y1, x2, y2, ..., xn, yn],  # 左下カーブの座標
        ]
    )

お疲れ様でした。

以上までが、冒頭のプログラムの解説です。

次章は少し遊ぶので、肩の力を抜いてくださいね。

長方形の一部を角丸にするプログラム

多様なニーズに応えるべく、色々なレパートリーの角丸長方形をご用意しました。

先ほどのプログラムを少し改造すれば、お好きな角を丸められます。

1つの角を丸める

長方形の右上の角だけ丸める

長方形の右上の角だけ丸めましょう。

 

get_rounded_rectangle_coords関数を少し改造しました。

def get_rounded_1_rectangle_coords(bbox_coords, ratio=1/3):
    radius = get_adjustment_range(bbox_coords, ratio)

    return flatten(
        [
            get_upper_left_corner_coords(bbox_coords),
            get_upper_right_rounded_corner_coords(bbox_coords, radius),
            get_lower_right_corner_coords(bbox_coords),
            get_lower_left_corner_coords(bbox_coords),
        ]
    )

 

右上の関数以外を別の関数で差し替えています。

処理はとても簡単です。

# 丸めない角の座標を返す
def get_upper_left_corner_coords(bbox_coords):
    return [bbox_coords[0], bbox_coords[1]]

def get_lower_right_corner_coords(bbox_coords):
    return [bbox_coords[2], bbox_coords[3]]

def get_lower_left_corner_coords(bbox_coords):
    return [bbox_coords[0], bbox_coords[3]]

# 一応作りましたが、今回は使いません。
def get_upper_right_corner_coords(bbox_coords):
    return [bbox_coords[2], bbox_coords[1]]

境界ボックスの対角の座標から、各角の座標を返すだけですね。

 

以下を実行すると、先程の画像の角丸長方形が描けます。

if __name__ == '__main__':
    import tkinter as tk

    # 画面作成
    root = tk.Tk()

    # キャンバス作成・配置
    canvas = tk.Canvas(root, width=500, height=500)
    canvas.pack()

    # 角丸長方形作成
    shape_coords = get_rounded_1_rectangle_coords((50, 100, 450, 400), ratio=0.5)
    canvas.create_polygon(shape_coords)

    # 画面表示
    root.mainloop()

上下の角で丸みを変える

長方形の上下の角をそれぞれ同じ比率で丸める

長方形の上下の角をそれぞれ同じ比率で丸めましょう。

 

get_rounded_rectangle_coords関数を少し改造しました。

def get_rounded_2_same_rectangle_coords(bbox_coords, ratio1=1/3, ratio2=0):
    radius1 = get_adjustment_range(bbox_coords, ratio1)
    radius2 = get_adjustment_range(bbox_coords, ratio2)

    return flatten(
        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius1),
            get_upper_right_rounded_corner_coords(bbox_coords, radius1),
            get_lower_right_rounded_corner_coords(bbox_coords, radius2),
            get_lower_left_rounded_corner_coords(bbox_coords, radius2),
        ]
    )

 

すずか

ratio(比率)が増えてる!
上の角をratio1で、下の角をratio2で調整します。

先生

 

以下を実行すると、先程の画像の角丸長方形が描けます。

if __name__ == '__main__':
    import tkinter as tk

    # 画面作成
    root = tk.Tk()

    # キャンバス作成・配置
    canvas = tk.Canvas(root, width=500, height=500)
    canvas.pack()

    # 角丸長方形作成
    shape_coords = get_rounded_2_same_rectangle_coords((50, 100, 450, 400), ratio1=1, ratio2=0.5)
    canvas.create_polygon(shape_coords)

    # 画面表示
    root.mainloop()

対角を丸める

長方形の対角同士をそれぞれ同じ比率で丸める

長方形の対角同士をそれぞれ同じ比率で丸めましょう。

 

get_rounded_2_same_rectangle_coords関数を少し改造しました。

def get_rounded_2_diag_rectangle_coords(bbox_coords, ratio1=1/3, ratio2=0):
    radius1 = get_adjustment_range(bbox_coords, ratio1)
    radius2 = get_adjustment_range(bbox_coords, ratio2)

    return flatten(
        [
            get_upper_left_rounded_corner_coords(bbox_coords, radius1),
            get_upper_right_rounded_corner_coords(bbox_coords, radius2),
            get_lower_right_rounded_corner_coords(bbox_coords, radius1),
            get_lower_left_rounded_corner_coords(bbox_coords, radius2),
        ]
    )

 

左上・右下の角をratio1で、右上・左下の角をratio2で調整します。

先生

 

以下を実行すると、先程の画像の角丸長方形が描けます。

if __name__ == '__main__':
    import tkinter as tk

    # 画面作成
    root = tk.Tk()

    # キャンバス作成・配置
    canvas = tk.Canvas(root, width=500, height=500)
    canvas.pack()

    # 角丸長方形作成
    shape_coords = get_rounded_2_diag_rectangle_coords((50, 100, 450, 400), ratio1=1, ratio2=0.5)
    canvas.create_polygon(shape_coords)

    # 画面表示
    root.mainloop()

いかがでしたでしょうか?

好みに合わせてカスタマイズしてくださいね。

角丸長方形の応用例

1つの角を切り取り1つの角を丸める

長方形の左上の角を丸めて右上の角を切り取る

角を丸めて切り取りを行いました。

角丸と角の切り取りを合わせると、作れる図形の幅はグッと広がります。

 

長方形の角の切り取りに関しては、後日記事を出します。

調整ハンドルで角の丸みを変更する


角の丸みをマウスのドラッグで動的に調整できます。

ExcelやPowerPointではなく、Tkinterでの実装です。

 

わざわざコードを書き換えなくとも、ハンドルを動かせば調整できるのです。

本記事の内容を踏まえれば、意外と簡単に作れますよ。

 

この動きの実装方法に関しては、後日記事を出します。

まとめ

今回はTkinterで角丸長方形を作る方法についてお伝えしました。

 

実装方法は、大きく\(2\)つの段階に分けられましたね。

  1. 図形の頂点の座標を計算する。
  2. create_polygonメソッドに座標を渡す。

 

また、その中でもステップ\(1\)が特に重要で、次の\(2\)つを考える必要がありました。

 

四角形の角を丸くすると柔らかい印象を与えられますが、Tkinterでは直接的に角丸長方形を作れません。

しかし本記事の内容を踏まえれば、Tkinterでのデザインの引き出しが大幅にUPします。

本記事が皆様のお役に立てば幸いです。

 

最後までお付き合いいただき、ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA