Skip to content

Instantly share code, notes, and snippets.

@limafresh
Created May 28, 2025 08:27
Show Gist options
  • Save limafresh/4e7193bb31d2aff3652d5c6f6cf35871 to your computer and use it in GitHub Desktop.
Save limafresh/4e7193bb31d2aff3652d5c6f6cf35871 to your computer and use it in GitHub Desktop.
Tkinter rounded button. An unofficial modern button for Tkinter that supports rounding.
"""
Author: limafresh <https://github.com/limafresh>
License: CC0 <https://creativecommons.org/publicdomain/zero/1.0/>
"""
from tkinter import Canvas
class RoundedButton(Canvas):
def __init__(
self,
parent,
width=150,
height=30,
text="RoundedButton",
font=None,
radius=13,
bg_color="green",
fg_color="white",
command=None,
cursor="hand2",
**kwargs,
):
Canvas.__init__(
self,
parent,
width=width,
height=height,
bg=parent["bg"],
highlightthickness=0,
**kwargs,
)
self.width = width
self.height = height
self.text = text
self.font = font
self.radius = radius
self.bg_color = bg_color
self.fg_color = fg_color
self.command = command
self.cursor = cursor
self.delete("all")
self._create_button()
self.bind("<ButtonRelease-1>", self._on_release)
def _create_button(self):
r, w, h = self.radius, self.width, self.height
self.create_arc(
(0, 0, r * 2, r * 2),
start=90,
extent=90,
fill=self.bg_color,
outline=self.bg_color,
tags="button",
)
self.create_arc(
(w - 2 * r, 0, w, r * 2),
start=0,
extent=90,
fill=self.bg_color,
outline=self.bg_color,
tags="button",
)
self.create_arc(
(0, h - 2 * r, r * 2, h),
start=180,
extent=90,
fill=self.bg_color,
outline=self.bg_color,
tags="button",
)
self.create_arc(
(w - 2 * r, h - 2 * r, w, h),
start=270,
extent=90,
fill=self.bg_color,
outline=self.bg_color,
tags="button",
)
self.create_rectangle(
(r, 0, w - r, h), fill=self.bg_color, outline=self.bg_color, tags="button"
)
self.create_rectangle(
(0, r, w, h - r), fill=self.bg_color, outline=self.bg_color, tags="button"
)
if self.font is None:
self.create_text(
w / 2, h / 2, text=self.text, fill=self.fg_color, tags="button"
)
elif isinstance(self.font, tuple):
self.create_text(
w / 2,
h / 2,
text=self.text,
font=self.font,
fill=self.fg_color,
tags="button",
)
else:
self.create_text(
w / 2,
h / 2,
text=self.text,
font=(None, self.font),
fill=self.fg_color,
tags="button",
)
self.configure(cursor=self.cursor)
def _on_release(self, event):
if self.command:
self.command()
def config(self, **kwargs):
self.delete("button")
if "width" in kwargs:
self.width = kwargs["width"]
self.configure(width=self.width)
if "height" in kwargs:
self.height = kwargs["height"]
self.configure(height=self.height)
if "text" in kwargs:
self.text = kwargs["text"]
if "font" in kwargs:
self.font = kwargs["font"]
if "radius" in kwargs:
self.radius = kwargs["radius"]
if "bg_color" in kwargs:
self.bg_color = kwargs["bg_color"]
if "fg_color" in kwargs:
self.fg_color = kwargs["fg_color"]
if "command" in kwargs:
self.command = kwargs["command"]
if "cursor" in kwargs:
self.cursor = kwargs["cursor"]
self._create_button()
def cget(self, key):
if key == "width":
return self.width
elif key == "height":
return self.height
elif key == "text":
return self.text
elif key == "font":
return self.font
elif key == "radius":
return self.radius
elif key == "bg_color":
return self.bg_color
elif key == "fg_color":
return self.fg_color
elif key == "command":
return self.command
elif key == "cursor":
return self.cursor
else:
raise KeyError(f"Unknown option: '{key}'")
@limafresh
Copy link
Author

screenshot

How to use?

It's very simple - download the RoundedButton.py file and place it in the folder where your script file is. Then import:

from RoundedButton import RoundedButton

And create button, for example:

button = RoundedButton(root, text="My button")
button.pack()

Arguments

Argument Description
width int value in px, for example, width=250
height int value in px, for example, height=50
text text for button
font int (for example, font=20) or tuple (for example, font=("Arial", 20))
radius radius of rounding, int value
bg_color button background color, for example bg_color="red" or bg_color="#f0f0f0"
fg_color button text color
command button command
cursor button cursor, by default cursor="hand2"

Methods

  • .config()
  • .cget()

Code example

Simple example

import tkinter
from RoundedButton import RoundedButton


def clickme():
    clickme_button.config(text="Thanks!", bg_color="yellow", fg_color="black")


root = tkinter.Tk()
root.geometry("200x200")
root.title("Simple example")

clickme_button = RoundedButton(root, text="Click me!", command=clickme)
clickme_button.pack(padx=10, pady=10)

quit_button = RoundedButton(root, text="Quit", bg_color="red", command=quit)
quit_button.pack(padx=10, pady=10)

root.mainloop()

Calculator

calculator

import tkinter as tk
from RoundedButton import RoundedButton


def press(key):
    current = entry.get()
    if key == "=":
        try:
            result = str(eval(current))
            entry.delete(0, tk.END)
            entry.insert(tk.END, result)
        except Exception:
            entry.delete(0, tk.END)
            entry.insert(tk.END, "Error")
    elif key == "C":
        entry.delete(0, tk.END)
    else:
        entry.insert(tk.END, key)


root = tk.Tk()
root.title("Calculator")
root["bg"] = "#2e2e2e"

entry = tk.Entry(root, font=(None, 15), relief=tk.FLAT, justify=tk.RIGHT)
entry.pack(fill=tk.X, padx=5, pady=20)

buttons_frame = tk.Frame(root, bg="#2e2e2e")
buttons_frame.pack()

row, column = 0, 0

buttons = [
    "7",
    "8",
    "9",
    "+",
    "4",
    "5",
    "6",
    "-",
    "1",
    "2",
    "3",
    "*",
    "C",
    "0",
    "=",
    "/",
]

for button_text in buttons:
    button = RoundedButton(
        buttons_frame,
        width=50,
        height=50,
        radius=20,
        text=button_text,
        font=20,
        command=lambda key=button_text: press(key),
    )
    button.grid(row=row, column=column, padx=5, pady=5)

    if button_text in ["+", "-", "*", "/"]:
        button.config(bg_color="orange")
    elif button_text == "=":
        button.config(bg_color="blue")
    else:
        button.config(bg_color="#6e6e6e")

    column += 1
    if column == 4:
        column = 0
        row += 1

root.mainloop()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment