Skip to content
9 changes: 6 additions & 3 deletions TkEasyGUI/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def str_to_float(value: str, default_value: float = 0) -> float:
_tkeasygui_info: dict[str, Any] = {}


def get_tnemes() -> tuple[str, ...]:
def get_themes() -> tuple[str, ...]:
"""
Get theme list

Expand All @@ -236,6 +236,11 @@ def get_tnemes() -> tuple[str, ...]:
return ttk.Style().theme_names()


def get_tnemes() -> tuple[str, ...]:
"""Alias of get_themes (kept for backward compatibility)."""
return get_themes()


def theme(name: str) -> None:
"""Set theme (alias of set_theme)"""
set_theme(name)
Expand All @@ -259,8 +264,6 @@ def set_default_theme() -> None:
set_theme("aqua")
elif is_win():
# ('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
# set_theme("winnative")
# set_theme("default")
set_theme("vista")
else:
set_theme("clam")
Expand Down
25 changes: 23 additions & 2 deletions TkEasyGUI/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2337,6 +2337,7 @@ class Button(Element):

**Example**
The program below changes the button's label to "Pushed" when the button is pressed.

```python
import TkEasyGUI as eg
button:eg.Button = eg.Button("Push me")
Expand All @@ -2346,6 +2347,12 @@ class Button(Element):
button.set_text("Pushed")
break
```

`use_ttk_buttons` parameter is set to `True` by default, which makes buttons look more modern.
However, on macOS, the default `ttk.Button` has a gray background and does not support changing the background color.
If you want to change the button color on macOS, set `use_ttk_buttons=False` to use `tk.Button` instead.
Also, when `use_ttk_buttons=True`, explicit button height settings are ignored due to a `ttk` limitation.
If you need to control button height, set `use_ttk_buttons=False`.
"""

# pylint: disable=too-many-arguments, too-many-locals
Expand All @@ -2371,14 +2378,17 @@ def __init__(
expand_y: bool = False,
pad: Optional[PadType] = None,
# other
use_ttk_buttons: bool = False,
use_ttk_buttons: Optional[bool] = None,
metadata: Optional[dict[str, Any]] = None,
**kw,
) -> None:
"""Create a Button element."""
key = button_text if (key is None) or (key == "") else key
super().__init__("Button", "TButton", key, False, metadata, **kw)
self.use_ttk = use_ttk_buttons # can select ttk or tk button
# ttk buttons look more modern by default.
if use_ttk_buttons is None:
use_ttk_buttons = True
self.use_ttk = use_ttk_buttons
self.disabled = False
if disabled is not None:
self.props["disabled"] = self.disabled = disabled
Expand All @@ -2390,6 +2400,16 @@ def __init__(
self.tooltip: Union[str, None] = tooltip
if button_color is not None:
self.set_button_color(button_color, update=False)
# check size
self.tk_button_height = 1
size = self.props.get("size", None)
if size is not None:
if isinstance(size, tuple) and len(size) == 2:
h = self.props["height"] = size[1]
if h >= 2:
self.use_ttk = False
self.tk_button_height = h

self._set_text_props(
font=font,
text_align=text_align,
Expand All @@ -2416,6 +2436,7 @@ def create(self, win: Window, parent: tk.Widget) -> tk.Widget:
**self.props,
)
else:
self.props["height"] = self.tk_button_height
self.widget = tk.Button(
parent,
command=lambda: self.disptach_event({"event_type": "command"}),
Expand Down
2 changes: 2 additions & 0 deletions TkEasyGUI/widgets_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def _create_root(self) -> tk.Tk:
self._root.eval("tk::PlaceWindow . center")
self._root.withdraw()
if self._theme_name == "":
# windows: winnative, clam, alt, default, classic, vista, xpnative
# macOS: aqua, clam, alt, default, classic
if _is_mac():
self.set_theme("aqua")
elif _is_win():
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Here is a list of elements:
### TkEasyGUI Original features

- [Custom Events](https://github.com/kujirahand/tkeasygui-python/blob/main/docs/custom_events.md)
- [Theme Guide](https://github.com/kujirahand/tkeasygui-python/blob/main/docs/theme.md)

### Package developper

Expand Down
115 changes: 115 additions & 0 deletions docs/theme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# TkEasyGUI Theme Guide

This document explains how to use themes and how to change theme-related defaults in TkEasyGUI.

## Overview

TkEasyGUI uses `ttk` themes for modern widget rendering.
You can switch themes at runtime using `set_theme()` or `theme()`.

Default theme by platform:

- macOS: `aqua`
- Windows: `vista`
- Linux/others: `clam`

## Basic theme usage

### Change theme with `set_theme`

```python
import TkEasyGUI as eg

eg.set_theme("clam")
window = eg.Window("Theme sample", [[eg.Button("OK", use_ttk_buttons=True)]])
window.read()
window.close()
```

### Alias: `theme`

`theme()` is an alias of `set_theme()`.

```python
import TkEasyGUI as eg

eg.theme("default")
```

## List available themes

Use `get_themes()` to inspect themes available in your current Tk runtime.

```python
import TkEasyGUI as eg

print(eg.get_themes())
```

Note:
- `get_themes()` is the preferred API name.
- `get_tnemes()` is still available as a backward-compatible alias.

## Change button style behavior

`Button` can render with `ttk.Button` (modern) or `tk.Button` (classic).

- `use_ttk_buttons=True` (default): use `ttk.Button`
- `use_ttk_buttons=False`: use `tk.Button`

```python
import TkEasyGUI as eg

layout = [
[eg.Button("Modern", use_ttk_buttons=True)],
[eg.Button("Classic", use_ttk_buttons=False)],
]
window = eg.Window("Buttons", layout)
window.read()
window.close()
```

Note:
- If you set `use_ttk_buttons=True`, explicit button height settings are ignored.
- This is a limitation of `ttk`.
- If you need to control button height, use `use_ttk_buttons=False`.




## How to customize defaults

### Global theme default

If you want to change the default theme for your app, call `set_theme()` before creating windows.

```python
import TkEasyGUI as eg

eg.set_theme("winnative")
```

### Revert to old Windows look

If you want behavior close to older Windows appearance:

```python
import TkEasyGUI as eg

eg.set_theme("vista")
layout = [[eg.Button("OK", use_ttk_buttons=False)]]
window = eg.Window("Legacy look", layout)
window.read()
window.close()
```

## Recommended test scripts

After changing theme defaults, validate with:

```bash
python tests/file_viewer.py
python tests/theme/ttk_button.py
python tests/ui_test.py
python tests/many_buttons.py
```
74 changes: 74 additions & 0 deletions tests/calc2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
### Calculator Sample

This sample demonstrates how to create a simple calculator using TkEasyGUI.
It also shows how to create multiple buttons and handle button events effectively.
"""

import TkEasyGUI as eg

eg.set_theme("alt")

# define the calculator buttons
calc_buttons = [
["C", "←", "//", "/"],
["7", "8", "9", "*"],
["4", "5", "6", "-"],
["1", "2", "3", "+"],
["0", ".", "%", "="],
]
font = ("Helvetica", 20)
# create window
layout = [
[
eg.Input(
"0",
key="-output-",
background_color="white",
color="black",
readonly_background_color="white",
readonly=True,
expand_x=True,
)
],
]
# create many buttons
for row in calc_buttons:
buttons = []
for ch in row:
btn = eg.Button(
ch, # label
key=f"-btn{ch}",
size=(5, 3),
)
buttons.append(btn)
layout.append(buttons)
window = eg.Window("Calc", layout, font=font)

# event loop
output = "0"
for event, values in window.event_iter():
if event == eg.WINDOW_CLOSED:
break
# when a button is pressed
if event.startswith("-btn"):
# get label
ch = window[event].get()
# clear if text is empty (0 or error)
if output == "0" or output.startswith("E:"):
output = ""
# check label
if ch == "C": # clear key
output = "0"
elif ch == "←": # bs key
output = output[:-1]
elif ch == "=": # calc
try:
output = str(eval(output))
except Exception as e:
output = "E:" + str(e)
else:
# add other key
output += ch
# update display
window["-output-"].update(output)
46 changes: 46 additions & 0 deletions tests/tabgroup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import TkEasyGUI as eg

layout = [
[
eg.TabGroup(
layout=[
[
eg.Tab(
"Tab 1",
[
[eg.Text("This is Tab 1")],
[eg.Text("This is Tab 1")],
[eg.Text("This is Tab 1")],
[eg.Text("This is Tab 1")],
[eg.Text("This is Tab 1")],
[eg.Button("Button 1")],
],
)
],
[
eg.Tab(
"Tab 2",
[[eg.Text("This is Tab 2")], [eg.Button("Button 2")]],
)
],
],
vertical_alignment="top",
expand_x=True,
expand_y=True,
)
]
]

# window create
window = eg.Window(
"UI test",
layout=layout,
font=("Arial", 12),
finalize=True,
resizable=True,
)
# event loop
while window.is_running():
event, values = window.read()
print("#", event, values)
window.close()
18 changes: 18 additions & 0 deletions tests/theme/ttk_button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Compare ttk and classic button rendering."""

import TkEasyGUI as eg

layout = [
[eg.Text("This is a modern button using ttk styles.")],
[eg.Button("Modern", use_ttk_buttons=True)],
[eg.HSeparator()],
[eg.Text("This is a classic button using Tkinter styles.")],
[eg.Button("Classic", use_ttk_buttons=False)],
]
window = eg.Window("Buttons", layout)
for event, values in window.event_iter():
if event == "Modern":
eg.popup("You clicked the modern button!")
elif event == "Classic":
eg.popup("You clicked the classic button!")
window.close()
Loading