Package: tkstyle
TkStyleTkStyleis aPythonlibrary to style yourGUIwith a modern and pragmatic paradigm. It's part of thePyrustic Open Ecosystem.Cyberpunk theme made with TkStyleInstallation|Reference|CyberpunkOverviewTkStyleis a styling library forTkinterthat takes advantage of the autocomplete feature of IDEs so that you hardly need any prior Tkinter styling knowledge.Each Tkinter widget has a set of options that allow you to define its look. For example, thetkinter.Buttonwidget has thebackgroundandforegroundoptions to change the background color and the text color on the button respectively.TkStylereproduces 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.Here is the definition of thetkstyle.Buttonclass which is supposed to modify the look of thetkinter.Buttonwidget:classButton(_Style):_CLASS_NAME="Button"def__init__(self):super().__init__()self.activeBackground=None# "#ececec"self.activeForeground=None# "#000000"self.anchor=None# "center"self.background=None# "#d9d9d9"self.borderWidth=None# 1self.compound=None# "none"self.default=None# "disabled"self.disabledForeground=None# "#a3a3a3"self.font=None# TkDefaultFontself.foreground=None# "#000000"self.height=None# 0self.highlightBackground=None# "#d9d9d9"self.highlightColor=None# "#000000"self.highlightThickness=None# 1self.justify=None# "center"self.padX=None# 3self.padY=None# 1self.relief=None# "raised"self.repeatDelay=None# 0self.repeatInterval=None# 0self.state=None# "normal"self.underline=None# -1self.width=None# 0self.wrapLength=None# 0Since a style is aPythonobject 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:PyCharm's autocompleteSince 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 thereliefoption  of thetkinter.Buttonwidget accepts, you can put an arbitrary string likeoopsand at runtime Tkinter will raise an informative exception:_tkinter.TclError:badrelief"oops":mustbeflat,groove,raised,ridge,solid,orsunkenThese details combined makeTkStylea great modern paradigm for GUI styling that will save you a lot of time.Style an instance of a widgetThis code snippet shows how to style the instance of a widget:importtkinterastkimporttkstyleroot=tk.Tk()# create and pack button_1button_1=tk.Button(root,text="Button 1")button_1.pack(side=tk.LEFT,padx=5,pady=5)# create and pack button_2button_2=tk.Button(root,text="Button 2")button_2.pack(side=tk.LEFT,padx=5,pady=5)# create the button_stylebutton_style=tkstyle.Button()button_style.background="tomato"button_style.foreground="white"# apply the button_style to button_2button_style.target(button_2)# mainlooproot.mainloop()Custom style applied to a buttonStyle a megawidgetA megawidget is a custom widget built with other native widgets.For example,megawidget.Tableis built withtkinter.Listbox,tkinter.Label, andtkinter.Scrollbar.TableSince a megawidget is not a native widget, it does not have a class that represents it inTkStyle.So how do you style a megawidget ?Well, megawidgets subclasstkinter.Frameortkinter.ToplevelandTkStyleallows styles to be nested likeMatryoshka dolls.Here's how we can style the Listboxes that make up a Table:importtkinterastkimporttkstylefrommegawidget.tableimportTableroot=tk.Tk()# table titlestitles=("Username","Password")# table datadata=[("Jackieman","Ydfj87mAfw"),("Salvador","Dqmpa644dga")]# create and pack tabletable=Table(root,titles=titles,data=data)table.pack()# create the listbox_stylelistbox_style=tkstyle.Listbox()listbox_style.background="tomato"listbox_style.foreground="white"# create the table_styletable_style=tkstyle.Frame()# megawidgets subclass tk.Frame# add the listbox_style to the table_style by specifying# a XResources-like pattern that matches Listboxes: "*Listbox"table_style.add(listbox_style,pattern="*Listbox")# apply the table_style to tabletable_style.target(table)# mainlooproot.mainloop()Table with a custom styleCreate a themeA 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.In this example, we'll create a theme that changes the look of all the buttons:importtkinterastkimporttkstyledefget_button_style():# create the button_stylebutton_style=tkstyle.Button()button_style.background="tomato"button_style.foreground="white"returnbutton_styledefget_theme():# create the themetheme=tkstyle.Theme()# add the button_style to the themebutton_style=get_button_style()theme.add(button_style,pattern="*Button")# the previous line could be this:# theme.add(button_style)# When you don't set a pattern, by default, the added style# class name prefixed with "*" is used as patternreturnthemeroot=tk.Tk()theme=get_theme()theme.target(root)# create and pack button_1button_1=tk.Button(root,text="Button 1")button_1.pack(side=tk.LEFT,padx=5,pady=5)# create and pack button_2button_2=tk.Button(root,text="Button 2")button_2.pack(side=tk.LEFT,padx=5,pady=5)# mainlooproot.mainloop()Custom theme for buttonsIn this other example, the theme contains a style that targets a particular instance oftkinter.Button:importtkinterastkimporttkstyledefget_button_style():# create the button_stylebutton_style=tkstyle.Button()button_style.background="tomato"button_style.foreground="white"returnbutton_styledefget_theme():# create the themetheme=tkstyle.Theme()# add the button_style to the themebutton_style=get_button_style()theme.add(button_style,pattern="*mybutton")returnthemeroot=tk.Tk()theme=get_theme()theme.target(root)# create and pack button_1button_1=tk.Button(root,text="Button 1")button_1.pack(side=tk.LEFT,padx=5,pady=5)# create and pack button_2button_2=tk.Button(root,name="mybutton",text="Button 2")button_2.pack(side=tk.LEFT,padx=5,pady=5)# mainlooproot.mainloop()Custom theme but constrained to fit to button_2So in short:You don't need to know the options by heart to customize the look of a widget.You don't need to learn yet another DSL.TkStyleuses object oriented programming and takes advantage of your IDE.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.You can determine which widgets used a given style since a style is just a Python object and therefore your IDE can locate usages.You can use code organization best practices to manage the styling aspect of your project sinceTkStylelets you use object oriented programming.I invite you to check out theCyberpunk dark themewhich uses theTkStylelibrary.$pipinstallcyberpunk-themeimporttkinterastkfromcyberpunk_themeimportCyberpunkfromcyberpunk_theme.widget.buttonimportget_button_style_4root=tk.Tk()# apply the Cyberpunk theme to the GUIcyberpunk_theme=Cyberpunk()cyberpunk_theme.target(root)# write your awesome code here# ...# ...button=tk.Button(root,text="Button")button.pack()# do you need to set dynamically a specific style to a button ?# there are 10 styles for buttons ! from the black to the red style !button_style_4=get_button_style_4()button_style_4.target(button)# mainlooproot.mainloop()InstallationFirst timeInstall for the first time:$pipinstalltkstyleUpgradeTo upgradeTkStyle:$pipinstalltkstyle--upgrade--upgrade-strategyeager