{"id":21127008,"url":"https://github.com/pyrustic/tkstyle","last_synced_at":"2025-08-17T18:07:50.585Z","repository":{"id":57475907,"uuid":"386740643","full_name":"pyrustic/tkstyle","owner":"pyrustic","description":"Create styles and themes for your Python desktop applications","archived":false,"fork":false,"pushed_at":"2022-03-21T20:43:08.000Z","size":28,"stargazers_count":15,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-03T06:05:42.959Z","etag":null,"topics":["beautiful","gui","library","lightweight","pyrustic","python","style","styling","theme","theme-builder","theming","theming-paradigm","tkinter"],"latest_commit_sha":null,"homepage":"https://pyrustic.github.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pyrustic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-16T19:15:46.000Z","updated_at":"2024-09-18T16:53:23.000Z","dependencies_parsed_at":"2022-09-07T13:51:46.723Z","dependency_job_id":null,"html_url":"https://github.com/pyrustic/tkstyle","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/pyrustic/tkstyle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyrustic%2Ftkstyle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyrustic%2Ftkstyle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyrustic%2Ftkstyle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyrustic%2Ftkstyle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pyrustic","download_url":"https://codeload.github.com/pyrustic/tkstyle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pyrustic%2Ftkstyle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270885360,"owners_count":24662452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beautiful","gui","library","lightweight","pyrustic","python","style","styling","theme","theme-builder","theming","theming-paradigm","tkinter"],"created_at":"2024-11-20T04:46:14.996Z","updated_at":"2025-08-17T18:07:50.562Z","avatar_url":"https://github.com/pyrustic.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TkStyle\n`TkStyle` is a `Python` library to style your `GUI` with a modern and pragmatic paradigm. It's part of the [Pyrustic Open Ecosystem](https://pyrustic.github.io).\n\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/cyberpunk-cover.png\" alt=\"Figure\" width=\"970\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Cyberpunk theme made with TkStyle \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\n[Installation](#installation) | [Reference](https://github.com/pyrustic/tkstyle/tree/master/docs/reference#readme) | [Cyberpunk](https://github.com/pyrustic/cyberpunk-theme)\n\n## Overview\n`TkStyle` is a styling library for `Tkinter` that takes advantage of the autocomplete feature of IDEs so that you hardly need any prior Tkinter styling knowledge.\n\nEach Tkinter widget has a set of options that allow you to define its look. For example, the `tkinter.Button` widget has the `background` and `foreground` options to change the background color and the text color on the button respectively.\n\n`TkStyle` reproduces for each widget a class which bears the name of the widget and which has attributes representing the options to modify the appearance of the widget.\n\nHere is the definition of the `tkstyle.Button` class which is supposed to modify the look of the `tkinter.Button` widget:\n\n```python\nclass Button(_Style):\n    _CLASS_NAME = \"Button\"\n\n    def __init__(self):\n        super().__init__()\n        self.activeBackground = None  # \"#ececec\"\n        self.activeForeground = None  # \"#000000\"\n        self.anchor = None  # \"center\"\n        self.background = None  # \"#d9d9d9\"\n        self.borderWidth = None  # 1\n        self.compound = None  # \"none\"\n        self.default = None  # \"disabled\"\n        self.disabledForeground = None  # \"#a3a3a3\"\n        self.font = None  # TkDefaultFont\n        self.foreground = None  # \"#000000\"\n        self.height = None  # 0\n        self.highlightBackground = None  # \"#d9d9d9\"\n        self.highlightColor = None  # \"#000000\"\n        self.highlightThickness = None  # 1\n        self.justify = None  # \"center\"\n        self.padX = None  # 3\n        self.padY = None  # 1\n        self.relief = None  # \"raised\"\n        self.repeatDelay = None  # 0\n        self.repeatInterval = None  # 0\n        self.state = None  # \"normal\"\n        self.underline = None  # -1\n        self.width = None  # 0\n        self.wrapLength = None  # 0\n```\n\nSince a style is a `Python` object and thanks to the autocomplete feature of the IDEs, we no longer need to know by heart the options to change the look of widgets:\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-1.png\" alt=\"Figure\" width=\"470\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e \u003ca href=\"https://www.jetbrains.com/pycharm/\"\u003ePyCharm\u003c/a\u003e's autocomplete \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\nSince Tkinter is a mature GUI toolkit, it sometimes indicates the legal values of an option when you don't set the correct value. For example, if you don't know which values the `relief` option  of the `tkinter.Button` widget accepts, you can put an arbitrary string like `oops` and at runtime Tkinter will raise an informative exception:\n\n```bash\n_tkinter.TclError: bad relief \"oops\": must be flat, groove, raised, ridge, solid, or sunken\n```\n\nThese details combined make `TkStyle` a great modern paradigm for GUI styling that will save you a lot of time.\n\n\n## Style an instance of a widget\n\nThis code snippet shows how to style the instance of a widget:\n\n```python\nimport tkinter as tk\nimport tkstyle\n\n\nroot = tk.Tk()\n\n# create and pack button_1\nbutton_1 = tk.Button(root, text=\"Button 1\")\nbutton_1.pack(side=tk.LEFT, padx=5, pady=5)\n# create and pack button_2\nbutton_2 = tk.Button(root, text=\"Button 2\")\nbutton_2.pack(side=tk.LEFT, padx=5, pady=5)\n\n# create the button_style\nbutton_style = tkstyle.Button()\nbutton_style.background = \"tomato\"\nbutton_style.foreground = \"white\"\n# apply the button_style to button_2\nbutton_style.target(button_2)\n\n# mainloop\nroot.mainloop()\n\n```\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-2.png\" alt=\"Figure\" width=\"196\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Custom style applied to a button \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\n\n## Style a megawidget\nA megawidget is a custom widget built with other native widgets.\n\nFor example, `megawidget.Table` is built with `tkinter.Listbox`, `tkinter.Label`, and `tkinter.Scrollbar`.\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-3.png\" alt=\"Figure\" width=\"357\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Table \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n\n\nSince a megawidget is not a native widget, it does not have a class that represents it in `TkStyle`.\n\nSo how do you style a megawidget ?\n\nWell, megawidgets subclass `tkinter.Frame` or `tkinter.Toplevel` and `TkStyle` allows styles to be nested like [Matryoshka dolls](https://en.wikipedia.org/wiki/Matryoshka_doll).\n\nHere's how we can style the Listboxes that make up a Table:\n\n```python\nimport tkinter as tk\nimport tkstyle\nfrom megawidget.table import Table\n\n\nroot = tk.Tk()\n\n# table titles\ntitles = (\"Username\", \"Password\")\n# table data\ndata = [(\"Jackieman\", \"Ydfj87mAfw\"),\n        (\"Salvador\", \"Dqmpa644dga\")]\n# create and pack table\ntable = Table(root, titles=titles, data=data)\ntable.pack()\n\n# create the listbox_style\nlistbox_style = tkstyle.Listbox()\nlistbox_style.background = \"tomato\"\nlistbox_style.foreground = \"white\"\n\n# create the table_style\ntable_style = tkstyle.Frame()  # megawidgets subclass tk.Frame\n# add the listbox_style to the table_style by specifying\n# a XResources-like pattern that matches Listboxes: \"*Listbox\"\ntable_style.add(listbox_style, pattern=\"*Listbox\")\n# apply the table_style to table\ntable_style.target(table)\n\n# mainloop\nroot.mainloop()\n\n```\n\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-4.png\" alt=\"Figure\" width=\"357\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Table with a custom style \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\n## Create a theme\nA theme is a collection of styles. While a style allows you to change the look of a particular (mega)widget instance, a theme allows you to apply a style to multiple (mega)widgets or also to a particular widget.\n\nIn this example, we'll create a theme that changes the look of all the buttons:\n\n```python\nimport tkinter as tk\nimport tkstyle\n\n\ndef get_button_style():\n    # create the button_style\n    button_style = tkstyle.Button()\n    button_style.background = \"tomato\"\n    button_style.foreground = \"white\"\n    return button_style\n\n\ndef get_theme():\n    # create the theme\n    theme = tkstyle.Theme()\n    # add the button_style to the theme\n    button_style = get_button_style()\n    theme.add(button_style, pattern=\"*Button\")\n    # the previous line could be this:\n    # theme.add(button_style)\n    # When you don't set a pattern, by default, the added style\n    # class name prefixed with \"*\" is used as pattern\n    return theme\n\n\nroot = tk.Tk()\ntheme = get_theme()\ntheme.target(root)\n\n# create and pack button_1\nbutton_1 = tk.Button(root, text=\"Button 1\")\nbutton_1.pack(side=tk.LEFT, padx=5, pady=5)\n# create and pack button_2\nbutton_2 = tk.Button(root, text=\"Button 2\")\nbutton_2.pack(side=tk.LEFT, padx=5, pady=5)\n\n# mainloop\nroot.mainloop()\n\n```\n\n\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-5.png\" alt=\"Figure\" width=\"196\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Custom theme for buttons \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\nIn this other example, the theme contains a style that targets a particular instance of `tkinter.Button`:\n\n```python\nimport tkinter as tk\nimport tkstyle\n\n\ndef get_button_style():\n    # create the button_style\n    button_style = tkstyle.Button()\n    button_style.background = \"tomato\"\n    button_style.foreground = \"white\"\n    return button_style\n\n\ndef get_theme():\n    # create the theme\n    theme = tkstyle.Theme()\n    # add the button_style to the theme\n    button_style = get_button_style()\n    theme.add(button_style, pattern=\"*mybutton\")\n    return theme\n\n\nroot = tk.Tk()\ntheme = get_theme()\ntheme.target(root)\n\n# create and pack button_1\nbutton_1 = tk.Button(root, text=\"Button 1\")\nbutton_1.pack(side=tk.LEFT, padx=5, pady=5)\n# create and pack button_2\nbutton_2 = tk.Button(root, name=\"mybutton\", text=\"Button 2\")\nbutton_2.pack(side=tk.LEFT, padx=5, pady=5)\n\n# mainloop\nroot.mainloop()\n\n```\n\n\n\u003c!-- Image --\u003e\n\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/pyrustic/misc/master/media/tkstyle-figure-6.png\" alt=\"Figure\" width=\"196\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003ci\u003e Custom theme but constrained to fit to button_2 \u003c/i\u003e\n    \u003c/p\u003e\n\u003c/div\u003e\n\nSo in short:\n- You don't need to know the options by heart to customize the look of a widget.\n- You don't need to learn yet another DSL.\n- `TkStyle` uses object oriented programming and takes advantage of your IDE.\n- There is a flag that allows TkStyle to forgive your mistakes (by default ignore_error = True), so your app doesn't crash just because you misspelled a color name.\n- You can determine which widgets used a given style since a style is just a Python object and therefore your IDE can locate usages.\n- You can use code organization best practices to manage the styling aspect of your project since `TkStyle` lets you use object oriented programming.\n\nI invite you to check out the [Cyberpunk dark theme](https://github.com/pyrustic/cyberpunk-theme) which uses the `TkStyle` library.\n\n```bash\n$ pip install cyberpunk-theme\n```\n\n```python\nimport tkinter as tk\nfrom cyberpunk_theme import Cyberpunk\nfrom cyberpunk_theme.widget.button import get_button_style_4\n\n\nroot = tk.Tk()\n# apply the Cyberpunk theme to the GUI\ncyberpunk_theme = Cyberpunk()\ncyberpunk_theme.target(root)\n\n# write your awesome code here\n# ...\n# ...\n\nbutton = tk.Button(root, text=\"Button\")\nbutton.pack()\n\n# do you need to set dynamically a specific style to a button ?\n# there are 10 styles for buttons ! from the black to the red style !\nbutton_style_4 = get_button_style_4()\nbutton_style_4.target(button)\n\n# mainloop\nroot.mainloop()\n```\n\n## Installation\n### First time\nInstall for the first time:\n\n```bash\n$ pip install tkstyle\n```\n\n### Upgrade\nTo upgrade `TkStyle`:\n\n```bash\n$ pip install tkstyle --upgrade --upgrade-strategy eager\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyrustic%2Ftkstyle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpyrustic%2Ftkstyle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpyrustic%2Ftkstyle/lists"}