-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
149 changed files
with
1,442 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,81 @@ | ||
# Forest-ttk-theme | ||
The Forest theme is a beautiful and modern ttk theme inspired by Excel. | ||
# Forest theme for ttk | ||
|
||
|
||
## How to use | ||
### Python / tkinter | ||
To use the theme just import the **forest-light.tcl**, or the **forest-dark.tcl** file, and call the `theme_use` method to set the theme: | ||
```python | ||
# Import the tcl file | ||
root.tk.call('source', 'forest-light.tcl / forest-dark.tcl') | ||
|
||
# Set the theme with the theme_use method | ||
ttk.Style().theme_use('forest-light / forest-dark') | ||
``` | ||
|
||
### Tcl / tk | ||
To use the theme just import the **forest-light.tcl**, or the **forest-dark.tcl** file, and call the `theme use` method to set the theme: | ||
```tcl | ||
# Import the tcl file | ||
source "forest-light.tcl / forest-dark.tcl" | ||
# Set theme using the theme use method | ||
ttk::style theme use forest-light / forest-dark | ||
``` | ||
|
||
## New style elements | ||
The Forest theme similar to my [Azure theme](https://github.com/rdbende/Azure-ttk-theme) has some **new** widget styles, such as an accent button, toggle switch, toggle button and card. You can apply these with the style option. | ||
|
||
If you need a highlighted button, use `Accent.TButton`: | ||
```python | ||
button = ttk.Button(root, text='Accent button', style='Accent.TButton', command=callback) | ||
``` | ||
|
||
To create a toggle button you need a checkbutton, to which you can apply the `ToggleButton` style: | ||
```python | ||
togglebutton = ttk.Checkbutton(root, text='Toggle button', style='ToggleButton', variable=var) | ||
``` | ||
|
||
The use of switches is becoming more common these days, so this theme has a `Switch` style, that can be applied to checkbuttons: | ||
```python | ||
switch = ttk.Checkbutton(root, text='Switch', style='Switch', variable=var) | ||
``` | ||
|
||
If you only want a border around your widgets, not an entire LabelFrame then apply the `Card` style to a Frame: | ||
```python | ||
card = ttk.Frame(root, style='Card', padding=(5, 6, 7, 8)) | ||
``` | ||
|
||
## A short example | ||
for Python... | ||
```python | ||
import tkinter as tk | ||
from tkinter import ttk | ||
|
||
root = tk.Tk() | ||
|
||
# Import the tcl file | ||
root.tk.call('source', 'forest-dark.tcl') | ||
|
||
# Set the theme with the theme_use method | ||
ttk.Style().theme_use('forest-dark') | ||
|
||
# A themed (ttk) button | ||
button = ttk.Button(root, text="I'm a themed button") | ||
button.pack(pady=20) | ||
|
||
root.mainloop() | ||
``` | ||
...and for Tcl | ||
```tcl | ||
package require Tk 8.6 | ||
# Import the tcl file | ||
source "forest-dark.tcl" | ||
# Set theme using the theme use method | ||
ttk::style theme use forest-dark | ||
# A themed (ttk) button | ||
ttk::button .button -text "I'm a themed button" | ||
pack .button -pady 20 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
""" | ||
Example script for testing the Forest theme | ||
Author: rdbende | ||
License: MIT license | ||
Source: https://github.com/rdbende/ttk-widget-factory | ||
""" | ||
|
||
|
||
import tkinter as tk | ||
from tkinter import ttk | ||
|
||
root = tk.Tk() | ||
root.title("Forest") | ||
root.option_add("*tearOff", False) # This is always a good idea | ||
|
||
# Make the app responsive | ||
root.columnconfigure(index=0, weight=1) | ||
root.columnconfigure(index=1, weight=1) | ||
root.columnconfigure(index=2, weight=1) | ||
root.rowconfigure(index=0, weight=1) | ||
root.rowconfigure(index=1, weight=1) | ||
root.rowconfigure(index=2, weight=1) | ||
|
||
# Create a style | ||
style = ttk.Style(root) | ||
|
||
# Import the tcl file | ||
root.tk.call("source", "forest-dark.tcl") | ||
|
||
# Set the theme with the theme_use method | ||
style.theme_use("forest-dark") | ||
|
||
# Create lists for the Comboboxes | ||
option_menu_list = ["", "OptionMenu", "Option 1", "Option 2"] | ||
combo_list = ["Combobox", "Editable item 1", "Editable item 2"] | ||
readonly_combo_list = ["Readonly combobox", "Item 1", "Item 2"] | ||
|
||
# Create control variables | ||
a = tk.BooleanVar() | ||
b = tk.BooleanVar(value=True) | ||
c = tk.BooleanVar() | ||
d = tk.IntVar(value=2) | ||
e = tk.StringVar(value=option_menu_list[1]) | ||
f = tk.BooleanVar() | ||
g = tk.DoubleVar(value=75.0) | ||
h = tk.BooleanVar() | ||
|
||
# Create a Frame for the Checkbuttons | ||
check_frame = ttk.LabelFrame(root, text="Checkbuttons", padding=(20, 10)) | ||
check_frame.grid(row=0, column=0, padx=(20, 10), pady=(20, 10), sticky="nsew") | ||
|
||
# Checkbuttons | ||
check_1 = ttk.Checkbutton(check_frame, text="Unchecked", variable=a) | ||
check_1.grid(row=0, column=0, padx=5, pady=10, sticky="nsew") | ||
check_2 = ttk.Checkbutton(check_frame, text="Checked", variable=b) | ||
check_2.grid(row=1, column=0, padx=5, pady=10, sticky="nsew") | ||
check_3 = ttk.Checkbutton(check_frame, text="Third state", variable=c) | ||
check_3.state(["alternate"]) | ||
check_3.grid(row=2, column=0, padx=5, pady=10, sticky="nsew") | ||
check_4 = ttk.Checkbutton(check_frame, text="Disabled", state="disabled") | ||
check_4.state(["disabled !alternate"]) | ||
check_4.grid(row=3, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Separator | ||
separator = ttk.Separator(root) | ||
separator.grid(row=1, column=0, padx=(20, 10), pady=10, sticky="ew") | ||
|
||
# Create a Frame for the Radiobuttons | ||
radio_frame = ttk.LabelFrame(root, text="Radiobuttons", padding=(20, 10)) | ||
radio_frame.grid(row=2, column=0, padx=(20, 10), pady=10, sticky="nsew") | ||
|
||
# Radiobuttons | ||
radio_1 = ttk.Radiobutton(radio_frame, text="Deselected", variable=d, value=1) | ||
radio_1.grid(row=0, column=0, padx=5, pady=10, sticky="nsew") | ||
radio_2 = ttk.Radiobutton(radio_frame, text="Selected", variable=d, value=2) | ||
radio_2.grid(row=1, column=0, padx=5, pady=10, sticky="nsew") | ||
radio_3 = ttk.Radiobutton(radio_frame, text="Mixed") | ||
radio_3.state(["alternate"]) | ||
radio_3.grid(row=2, column=0, padx=5, pady=10, sticky="nsew") | ||
radio_4 = ttk.Radiobutton(radio_frame, text="Disabled", state="disabled") | ||
radio_4.grid(row=3, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Create a Frame for input widgets | ||
widgets_frame = ttk.Frame(root, padding=(0, 0, 0, 10)) | ||
widgets_frame.grid(row=0, column=1, padx=10, pady=(30, 10), sticky="nsew", rowspan=3) | ||
widgets_frame.columnconfigure(index=0, weight=1) | ||
|
||
# Entry | ||
entry = ttk.Entry(widgets_frame) | ||
entry.insert(0, "Entry") | ||
entry.grid(row=0, column=0, padx=5, pady=(0, 10), sticky="ew") | ||
|
||
# Spinbox | ||
spinbox = ttk.Spinbox(widgets_frame, from_=0, to=100, increment=0.1) | ||
spinbox.insert(0, "Spinbox") | ||
spinbox.grid(row=1, column=0, padx=5, pady=10, sticky="ew") | ||
|
||
# Combobox | ||
combobox = ttk.Combobox(widgets_frame, values=combo_list) | ||
combobox.current(0) | ||
combobox.grid(row=2, column=0, padx=5, pady=10, sticky="ew") | ||
|
||
# Read-only combobox | ||
readonly_combo = ttk.Combobox(widgets_frame, state="readonly", values=readonly_combo_list) | ||
readonly_combo.current(0) | ||
readonly_combo.grid(row=3, column=0, padx=5, pady=10, sticky="ew") | ||
|
||
# Menu for the Menubutton | ||
menu = tk.Menu(widgets_frame) | ||
menu.add_command(label="Menu item 1") | ||
menu.add_command(label="Menu item 2") | ||
menu.add_separator() | ||
menu.add_command(label="Menu item 3") | ||
menu.add_command(label="Menu item 4") | ||
|
||
# Menubutton | ||
menubutton = ttk.Menubutton(widgets_frame, text="Menubutton", menu=menu, direction="below") | ||
menubutton.grid(row=4, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# OptionMenu | ||
optionmenu = ttk.OptionMenu(widgets_frame, e, *option_menu_list) | ||
optionmenu.grid(row=5, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Button | ||
button = ttk.Button(widgets_frame, text="Button") | ||
button.grid(row=6, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Accentbutton | ||
accentbutton = ttk.Button(widgets_frame, text="Accentbutton", style="Accent.TButton") | ||
accentbutton.grid(row=7, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Togglebutton | ||
button = ttk.Checkbutton(widgets_frame, text="Togglebutton", style="ToggleButton") | ||
button.grid(row=8, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Switch | ||
switch = ttk.Checkbutton(widgets_frame, text="Switch", style="Switch") | ||
switch.grid(row=9, column=0, padx=5, pady=10, sticky="nsew") | ||
|
||
# Panedwindow | ||
paned = ttk.PanedWindow(root) | ||
paned.grid(row=0, column=2, pady=(25, 5), sticky="nsew", rowspan=3) | ||
|
||
# Pane #1 | ||
pane_1 = ttk.Frame(paned) | ||
paned.add(pane_1, weight=1) | ||
|
||
# Create a Frame for the Treeview | ||
treeFrame = ttk.Frame(pane_1) | ||
treeFrame.pack(expand=True, fill="both", padx=5, pady=5) | ||
|
||
# Scrollbar | ||
treeScroll = ttk.Scrollbar(treeFrame) | ||
treeScroll.pack(side="right", fill="y") | ||
|
||
# Treeview | ||
treeview = ttk.Treeview(treeFrame, selectmode="extended", yscrollcommand=treeScroll.set, columns=(1, 2), height=12) | ||
treeview.pack(expand=True, fill="both") | ||
treeScroll.config(command=treeview.yview) | ||
|
||
# Treeview columns | ||
treeview.column("#0", width=120) | ||
treeview.column(1, anchor="w", width=120) | ||
treeview.column(2, anchor="w", width=120) | ||
|
||
# Treeview headings | ||
treeview.heading("#0", text="Column 1", anchor="center") | ||
treeview.heading(1, text="Column 2", anchor="center") | ||
treeview.heading(2, text="Column 3", anchor="center") | ||
|
||
# Define treeview data | ||
treeview_data = [ | ||
("", "end", 1, "Parent", ("Item 1", "Value 1")), | ||
(1, "end", 2, "Child", ("Subitem 1.1", "Value 1.1")), | ||
(1, "end", 3, "Child", ("Subitem 1.2", "Value 1.2")), | ||
(1, "end", 4, "Child", ("Subitem 1.3", "Value 1.3")), | ||
(1, "end", 5, "Child", ("Subitem 1.4", "Value 1.4")), | ||
("", "end", 6, "Parent", ("Item 2", "Value 2")), | ||
(6, "end", 7, "Child", ("Subitem 2.1", "Value 2.1")), | ||
(6, "end", 8, "Sub-parent", ("Subitem 2.2", "Value 2.2")), | ||
(8, "end", 9, "Child", ("Subitem 2.2.1", "Value 2.2.1")), | ||
(8, "end", 10, "Child", ("Subitem 2.2.2", "Value 2.2.2")), | ||
(8, "end", 11, "Child", ("Subitem 2.2.3", "Value 2.2.3")), | ||
(6, "end", 12, "Child", ("Subitem 2.3", "Value 2.3")), | ||
(6, "end", 13, "Child", ("Subitem 2.4", "Value 2.4")), | ||
("", "end", 14, "Parent", ("Item 3", "Value 3")), | ||
(14, "end", 15, "Child", ("Subitem 3.1", "Value 3.1")), | ||
(14, "end", 16, "Child", ("Subitem 3.2", "Value 3.2")), | ||
(14, "end", 17, "Child", ("Subitem 3.3", "Value 3.3")), | ||
(14, "end", 18, "Child", ("Subitem 3.4", "Value 3.4")), | ||
("", "end", 19, "Parent", ("Item 4", "Value 4")), | ||
(19, "end", 20, "Child", ("Subitem 4.1", "Value 4.1")), | ||
(19, "end", 21, "Sub-parent", ("Subitem 4.2", "Value 4.2")), | ||
(21, "end", 22, "Child", ("Subitem 4.2.1", "Value 4.2.1")), | ||
(21, "end", 23, "Child", ("Subitem 4.2.2", "Value 4.2.2")), | ||
(21, "end", 24, "Child", ("Subitem 4.2.3", "Value 4.2.3")), | ||
(19, "end", 25, "Child", ("Subitem 4.3", "Value 4.3")) | ||
] | ||
|
||
# Insert treeview data | ||
for item in treeview_data: | ||
treeview.insert(parent=item[0], index=item[1], iid=item[2], text=item[3], values=item[4]) | ||
if item[0] == "" or item[2] == 8 or item[2] == 21: | ||
treeview.item(item[2], open=True) # Open parents | ||
|
||
# Select and scroll | ||
treeview.selection_set(9) | ||
treeview.see(7) | ||
|
||
# Pane #2 | ||
pane_2 = ttk.Frame(paned) | ||
paned.add(pane_2, weight=3) | ||
|
||
# Notebook | ||
notebook = ttk.Notebook(pane_2) | ||
|
||
# Tab #1 | ||
tab_1 = ttk.Frame(notebook) | ||
tab_1.columnconfigure(index=0, weight=1) | ||
tab_1.columnconfigure(index=1, weight=1) | ||
tab_1.rowconfigure(index=0, weight=1) | ||
tab_1.rowconfigure(index=1, weight=1) | ||
notebook.add(tab_1, text="Tab 1") | ||
|
||
# Scale | ||
scale = ttk.Scale(tab_1, from_=100, to=0, variable=g, command=lambda event: g.set(scale.get())) | ||
scale.grid(row=0, column=0, padx=(20, 10), pady=(20, 0), sticky="ew") | ||
|
||
# Progressbar | ||
progress = ttk.Progressbar(tab_1, value=0, variable=g, mode="determinate") | ||
progress.grid(row=0, column=1, padx=(10, 20), pady=(20, 0), sticky="ew") | ||
|
||
# Label | ||
label = ttk.Label(tab_1, text="Forest ttk theme", justify="center") | ||
label.grid(row=1, column=0, pady=10, columnspan=2) | ||
|
||
# Tab #2 | ||
tab_2 = ttk.Frame(notebook) | ||
notebook.add(tab_2, text="Tab 2") | ||
|
||
# Tab #3 | ||
tab_3 = ttk.Frame(notebook) | ||
notebook.add(tab_3, text="Tab 3") | ||
|
||
notebook.pack(expand=True, fill="both", padx=5, pady=5) | ||
|
||
# Sizegrip | ||
sizegrip = ttk.Sizegrip(root) | ||
sizegrip.grid(row=100, column=100, padx=(0, 5), pady=(0, 5)) | ||
|
||
# Center the window, and set minsize | ||
root.update() | ||
root.minsize(root.winfo_width(), root.winfo_height()) | ||
x_cordinate = int((root.winfo_screenwidth()/2) - (root.winfo_width()/2)) | ||
y_cordinate = int((root.winfo_screenheight()/2) - (root.winfo_height()/2)) | ||
root.geometry("+{}+{}".format(x_cordinate, y_cordinate)) | ||
|
||
# Start the main loop | ||
root.mainloop() |
Oops, something went wrong.