├── .gitignore ├── LICENSE ├── README.md ├── assets ├── example-1.png └── example-2.png ├── development ├── demo.py ├── demov6.py └── test.py ├── pyproject.toml └── tkfontawesome ├── __init__.py ├── svgs.py └── svgs └── consolidate.py /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | .idea 3 | build 4 | dist 5 | *.egg-info 6 | *.mp4 7 | *_build 8 | *_static 9 | .vscode 10 | __pycache__ 11 | experiment 12 | testing_notes.txt 13 | docsenv 14 | tkfontawesome/svgs/brands 15 | tkfontawesome/svgs/regulars 16 | tkfontawesome/svgs/solid 17 | tkfontawesome/svgs/icons.json 18 | publish.bat 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Israel Dryer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PyPI](https://img.shields.io/pypi/v/tkfontawesome.svg)](https://pypi.org/project/tkfontawesome/) 2 | [![Downloads](https://static.pepy.tech/badge/tkfontawesome/month)](https://pepy.tech/project/tkfontawesome) 3 | [![GitHub issues](https://img.shields.io/github/issues/israel-dryer/tkfontawesome.svg)](https://github.com/israel-dryer/tkfontawesome/issues) 4 | [![GitHub issues closed](https://img.shields.io/github/issues-closed/israel-dryer/tkfontawesome.svg)](https://github.com/israel-dryer/tkfontawesome/issues?q=is%3Aissue+is%3Aclosed) 5 | [![License](https://img.shields.io/github/license/israel-dryer/tkfontawesome.svg)](https://github.com/israel-dryer/tkfontawesome/blob/main/LICENSE) 6 | [![Stars](https://img.shields.io/github/stars/israel-dryer/tkfontawesome.svg)](https://github.com/israel-dryer/tkfontawesome/stargazers) 7 | [![Forks](https://img.shields.io/github/forks/israel-dryer/tkfontawesome.svg)](https://github.com/israel-dryer/tkfontawesome/network) 8 | [![Code Size](https://img.shields.io/github/languages/code-size/israel-dryer/tkfontawesome)](https://github.com/israel-dryer/tkfontawesome) 9 | 10 | # TkFontAwesome 11 | 12 | > Requires Python **3.8+** 13 | 14 | A library that enables you to use [FontAwesome icons](https://fontawesome.com/v6/icons?o=r&m=free) 15 | in your tkinter application. 16 | 17 | You may use any of the 2k+ *free* [FontAwesome 6.5 icons](https://fontawesome.com/v6/icons?o=r&m=free). 18 | The **fill color** and **size** are customized to your specifications and then converted 19 | to an object via [tksvg](https://pypi.org/project/tksvg/) that can be used anywhere you would use a `tkinter.PhotoImage` object. 20 | 21 | ![example-2](https://raw.githubusercontent.com/israel-dryer/TkFontAwesome/main/assets/example-2.png) 22 | 23 | ## Installation 24 | 25 | ```shell 26 | python -m pip install tkfontawesome 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```python 32 | import tkinter as tk 33 | from tkfontawesome import icon_to_image 34 | 35 | root = tk.Tk() 36 | fb = icon_to_image("facebook", fill="#4267B2", scale_to_width=64) 37 | send = icon_to_image("paper-plane", fill="#1D9F75", scale_to_width=64) 38 | 39 | tk.Label(root, image=fb).pack(padx=10, pady=10) 40 | tk.Button(root, image=send).pack(padx=10, pady=10) 41 | 42 | root.mainloop() 43 | ``` 44 | 45 | ![example-1](https://raw.githubusercontent.com/israel-dryer/TkFontAwesome/main/assets/example-1.png) 46 | 47 | ## API: `icon_to_image()` 48 | 49 | ```python 50 | ( 51 | name=None, 52 | fill=None, 53 | scale_to_width=None, 54 | scale_to_height=None, 55 | scale=1 56 | ) 57 | ``` 58 | 59 | ### Parameters 60 | 61 | | Name | Type | Description | Default | 62 | |-------------------|-------|-----------------------------------------------------------------------|-----------| 63 | | name | str | The name of the FontAwesome icon. | None | 64 | | fill | str | The fill color of the svg path. | None | 65 | | scale_to_width | int | Adjust image width to this size (in pixels); maintains aspect ratio. | None | 66 | | scale_to_height | int | Adjust image height to this size (in pixels); maintains aspect ratio. | None | 67 | | scale | float | Scale the image width and height by this factor. | 1 | 68 | 69 | ## License 70 | 71 | The [CC BY 4.0](https://fontawesome.com/license/free) license applies to all FontAwesome *free* icons used in the library. 72 | The MIT License applies to all other work. 73 | 74 | --- 75 | 76 | **Author**: [Israel Dryer](https://github.com/israel-dryer) 77 | 📦 Available on [PyPI](https://pypi.org/project/tkfontawesome/) | 🐙 [GitHub](https://github.com/israel-dryer/tkfontawesome) 78 | -------------------------------------------------------------------------------- /assets/example-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/israel-dryer/TkFontAwesome/c34952fca54d7a911e7b9aa03f8668c25877b7ac/assets/example-1.png -------------------------------------------------------------------------------- /assets/example-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/israel-dryer/TkFontAwesome/c34952fca54d7a911e7b9aa03f8668c25877b7ac/assets/example-2.png -------------------------------------------------------------------------------- /development/demo.py: -------------------------------------------------------------------------------- 1 | from tkfontawesome import icon_to_image 2 | import tkinter as tk 3 | from ctypes import windll 4 | 5 | windll.user32.SetProcessDPIAware() 6 | 7 | icons = [ 8 | ( 9 | "band-aid", 10 | "basketball-ball", 11 | "box", 12 | "child", 13 | "church", 14 | "feather-alt", 15 | "save", 16 | "drafting-compass", 17 | ), 18 | ( 19 | "vial", 20 | "fish", 21 | "user-ninja", 22 | "concierge-bell", 23 | "tooth", 24 | "sign", 25 | "caravan", 26 | "file-prescription", 27 | ), 28 | ( 29 | "wine-glass-alt", 30 | "mitten", 31 | "couch", 32 | "mortar-pestle", 33 | "dna", 34 | "bus-alt", 35 | "car", 36 | "stethoscope", 37 | ), 38 | ] 39 | 40 | root = tk.Tk() 41 | images = [] 42 | 43 | for i, row in enumerate(icons): 44 | root.rowconfigure(i, weight=1) 45 | for j, icon in enumerate(row): 46 | root.columnconfigure(j, weight=1) 47 | images.append(icon_to_image(icon, scale_to_width=64)) 48 | tk.Label(root, image=images[-1]).grid(row=i, column=j, padx=5, pady=5) 49 | 50 | root.mainloop() 51 | -------------------------------------------------------------------------------- /development/demov6.py: -------------------------------------------------------------------------------- 1 | from tkfontawesome import icon_to_image 2 | import tkinter as tk 3 | from ctypes import windll 4 | 5 | windll.user32.SetProcessDPIAware() 6 | 7 | icons = [ 8 | ( 9 | "x-twitter", 10 | "stapler", 11 | "fa-bridge-water", 12 | "envelope-circle-check", 13 | "hill-rockslide", 14 | "mobile-retro", 15 | "people-pulling", 16 | "person-cane", 17 | ), 18 | ( 19 | "person-drowning", 20 | "person-walking-luggage", 21 | "ranking-star", 22 | "shield-heart", 23 | "toilets-portable", 24 | "panorama", 25 | "shrimp", 26 | "timeline", 27 | ), 28 | ( 29 | "child-reaching", 30 | "mitten", 31 | "bowl-rice", 32 | "bucket", 33 | "cubes-stacked", 34 | "jug-detergent", 35 | "shield-dog", 36 | "bug-slash", 37 | ), 38 | ] 39 | 40 | root = tk.Tk() 41 | images = [] 42 | 43 | for i, row in enumerate(icons): 44 | root.rowconfigure(i, weight=1) 45 | for j, icon in enumerate(row): 46 | root.columnconfigure(j, weight=1) 47 | images.append(icon_to_image(icon, scale_to_width=64)) 48 | tk.Label(root, image=images[-1]).grid(row=i, column=j, padx=5, pady=5) 49 | 50 | root.mainloop() 51 | -------------------------------------------------------------------------------- /development/test.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkfontawesome import icon_to_image 3 | 4 | root = tk.Tk() 5 | img = icon_to_image("facebook", fill="#4267B2", scale_to_width=64) 6 | tk.Label(root, image=img).pack(padx=20, pady=20) 7 | root.mainloop() 8 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "tkfontawesome" 3 | version = "0.3.2" 4 | authors = [{name = "Israel Dryer", email = "israel.dryer@gmail.com"}] 5 | description = "Use any of the 2k+ free FontAwesome icons in your tkinter application." 6 | keywords = ["svg", "fontawesome", "icons", "tkinter", "ttk"] 7 | readme = "README.md" 8 | license = {file = "LICENSE"} 9 | classifiers = [ 10 | "Programming Language :: Python :: 3", 11 | "License :: OSI Approved :: MIT License", 12 | "Operating System :: OS Independent", 13 | ] 14 | requires-python = ">=3.8" 15 | dependencies = [ 16 | "lxml>=5.4.0,<6.0.0", 17 | "tksvg>=0.7.4,<0.8.0" 18 | ] 19 | 20 | [project.urls] 21 | Homepage = "https://github.com/israel-dryer/tkfontawesome" 22 | Repository = "https://github.com/israel-dryer/tkfontawesome" 23 | Issues = "https://github.com/israel-dryer/tkfontawesome/issues" 24 | 25 | [build-system] 26 | requires = ["setuptools", "scikit-build"] 27 | build-backend = "setuptools.build_meta" 28 | 29 | [tool.setuptools.packages.find] 30 | where = ["."] 31 | -------------------------------------------------------------------------------- /tkfontawesome/__init__.py: -------------------------------------------------------------------------------- 1 | import io 2 | import tksvg 3 | from lxml import etree 4 | from tkfontawesome.svgs import FA, FA_aliases 5 | 6 | 7 | def icon_to_image(name, fill=None, scale_to_width=None, scale_to_height=None, scale=1): 8 | """ 9 | Look up a FontAwesome icon by name and return it as an SvgImage object, 10 | which can be used anywhere a PhotoImage object is used in tkinter. 11 | 12 | Parameters: 13 | name (str): Name of the FontAwesome icon (e.g., 'facebook'). 14 | fill (str): Optional fill color for the icon (e.g., "#4267B2"). 15 | scale_to_width (int): Target width in pixels (maintains aspect ratio). 16 | scale_to_height (int): Target height in pixels (maintains aspect ratio). 17 | scale (float): Scaling factor (applied only if width/height are not set). 18 | 19 | Returns: 20 | SvgImage: The converted SVG image ready for tkinter use. 21 | 22 | Example: 23 | import tkinter as tk 24 | from tkfontawesome import icon_to_image 25 | 26 | root = tk.Tk() 27 | img = icon_to_image("facebook", fill="#4267B2", scale_to_width=64) 28 | tk.Label(root, image=img).pack(padx=10, pady=10) 29 | root.mainloop() 30 | """ 31 | name = FA_aliases.get(name, name) 32 | if name.startswith('fa-'): 33 | name = name[3:] 34 | xml_data = FA.get(name) 35 | if xml_data is None: 36 | raise ValueError( 37 | f"'{name}' is not a valid icon name. Check spelling or visit https://fontawesome.com/icons." 38 | ) 39 | return svg_to_image(xml_data, fill, scale_to_width, scale_to_height, scale) 40 | 41 | 42 | def svg_to_image(source, fill=None, scale_to_width=None, scale_to_height=None, scale=1): 43 | """ 44 | Convert an SVG string into an SvgImage object for use in tkinter. 45 | 46 | Parameters: 47 | source (str): Raw SVG XML string. 48 | fill (str): Optional fill color override. 49 | scale_to_width (int): Width in pixels (maintains aspect ratio). 50 | scale_to_height (int): Height in pixels (maintains aspect ratio). 51 | scale (float): Optional scaling factor. 52 | 53 | Returns: 54 | SvgImage: The processed image object. 55 | """ 56 | root = etree.fromstring(source) 57 | tree = etree.ElementTree(root) 58 | 59 | # Apply fill color override if provided 60 | if fill: 61 | for elem in root.iter(): 62 | tag = str(elem.tag) 63 | if 'fill' in elem.attrib: 64 | elem.attrib['fill'] = fill 65 | elif tag.endswith("path"): 66 | elem.attrib['fill'] = fill 67 | 68 | img_data = io.BytesIO() 69 | tree.write(img_data) 70 | params = {"data": img_data.getvalue()} 71 | if scale_to_width: 72 | params["scaletowidth"] = scale_to_width 73 | if scale_to_height: 74 | params["scaletoheight"] = scale_to_height 75 | if scale != 1: 76 | params["scale"] = scale 77 | 78 | return tksvg.SvgImage(**params) 79 | -------------------------------------------------------------------------------- /tkfontawesome/svgs/consolidate.py: -------------------------------------------------------------------------------- 1 | """Create svgs.py file from font-awesome icons directories. 2 | 3 | brands, regular, solid should be copied into this directory from svgs directory 4 | in font awesome download zip. 5 | icons.json should be copied into this directory from metadata directory in font 6 | awesome download zip. 7 | """ 8 | 9 | import json 10 | from pathlib import Path 11 | from pprint import pformat 12 | 13 | root = Path(__file__).parent 14 | 15 | dirs = [root/'brands', root/'regular', root/'solid'] 16 | 17 | svg_dict = {} 18 | 19 | for dir in dirs: 20 | print(dir) 21 | for file in dir.iterdir(): 22 | svg_dict[file.stem] = file.read_text() 23 | 24 | 25 | alias_dict = {} 26 | 27 | with (root/'icons.json').open('r', encoding='utf8') as f: 28 | icons = json.load(f) 29 | 30 | for icon, icon_data in icons.items(): 31 | if 'aliases' not in icon_data or 'names' not in icon_data['aliases']: 32 | continue 33 | for alias in icon_data['aliases']['names']: 34 | alias_dict[alias] = icon 35 | 36 | with (root/'..'/'svgs.py').open('w', encoding='utf-8') as f: 37 | f.write(f'FA = {pformat(svg_dict, width=9999, indent=4)}\nFA_aliases = {pformat(alias_dict, indent=4)}\n') 38 | --------------------------------------------------------------------------------