Regula is a lightweight, simplified Python wrapper around the Tkinter library, designed to make creating basic desktop applications faster and more readable, especially for small projects or educational purposes.
It abstracts away some of the complexities of Tkinter's layout managers (like grid and pack), offering a streamlined, declarative way to build GUIs.
- Simplified Widget Creation: One function call for common widgets (
Label,Button,Entry,Frame, etc.). - Automatic Layout: Automatically handles placement using
grid(whenlineandpositionare provided) orpack. - Built-in Utilities: Simple functions for message boxes (
Info,Error), file dialogues (FileOpener), and input prompts (Ask). - Unified Value Retrieval: Use the
Get(widget)function to easily retrieve the current value from all input widgets.
Assuming you have Python 3.8+ installed:
pip install regula
import regula as sg
import random
import sys # Needed for file reading error handling
# Set the window title and size using the fluent interface for Window configuration
sg.Window().Title("Regula Example App - Full Demo").Size("890x380").Background("#E6E6FA")
# --- Global Widgets for Tab 7 & 8 ---
# Need a global reference to the Textarea so the button command can update it
text_output_area = None
# Global reference for the Entry widget in Tab 8
password_entry = None
def open_file_and_read():
"""Opens a file dialog, reads the selected file, and updates Tab 7 Textarea."""
global text_output_area
# Use sg.FileOpener() to open the native OS file dialog.
filepath = sg.FileOpener(
('Text Files', '*.txt'),
('All Files', '*.*')
)
if filepath:
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Clear Textarea and insert new content
# Accessing the underlying Tk constant via the regula alias 'sg'
text_output_area.delete('1.0', sg.tk.END)
text_output_area.insert('1.0', content)
sg.Info("File Loaded", f"Content from file loaded successfully.")
except FileNotFoundError:
sg.Error("Error", f"File not found: {filepath}")
except Exception as e:
sg.Error("Read Error", f"An error occurred while reading the file: {e}")
else:
sg.Info("Cancelled", "File selection was cancelled.")
# --- Tab Setup ---
notebook = sg.Notebook(expand=True)
# Tabs 1-6 remain the same size for consistency
tab1 = sg.Frame(notebook, 'Button, Label and Info', expand=True, tab_color='lightgreen', _height=350, _width=500)
tab2 = sg.Frame(notebook, 'Textarea and Error', expand=True, tab_color='lightgreen', _height=350, _width=500)
tab3 = sg.Frame(notebook, 'Entry and Scale', expand=True, tab_color='lightgreen', _height=350, _width=500)
tab4 = sg.Frame(notebook, 'Listbox', expand=True, tab_color='lightgreen', _height=350, _width=500)
tab5 = sg.Frame(notebook, 'Ask', expand=True, tab_color='lightgreen', _height=350, _width=500)
tab6 = sg.Frame(notebook, 'Wait and Configure', expand=True, tab_color='lightgreen', _height=350, _width=500)
# --- Tab 7: FileOpener ---
tab7 = sg.Frame(notebook, 'FileOpener', expand=True, tab_color='#ADD8E6', _height=350, _width=500)
# --- Tab 8: New Configure (is_password) ---
tab8 = sg.Frame(notebook, 'New Configure', expand=True, tab_color='#FFD700', _height=350, _width=500)
# -----------------------------------------------------
## Tab 1 Content: Button, Label, Info
# -----------------------------------------------------
def to_do():
sg.Info("Yay!", "Haha!")
# Demonstrating 'bold' configuration on a Label
sg.Label(tab1, line=0, position=0, align='left', expand=True, bold=True, content='Press the button: ')
# Demonstrating Button configuration args (_width, _height)
sg.Button(tab1, _command=to_do, line=0, position=1, align='center', expand=True, _width=15, _height=1)
# -----------------------------------------------------
## Tab 2 Content: Textarea, Error
# -----------------------------------------------------
texter = sg.Textarea(tab2, 'Do not enter text!', expand=True)
def get_texter():
global texter
results = sg.Get(texter)
if not results == 'Do not enter text!':
sg.Error('Hey!', f'Hey! you should not enter text here, especially not "{results}"!')
else:
sg.Error('Hey!', 'Thanks for not entering text, but WHY DID YOU PRESS THE BUTTON?!')
# Demonstrating passing direct Tkinter args (like background) to Button
sg.Button(tab2, "And don't press here", expand=True, _command=get_texter, background_color='red')
# -----------------------------------------------------
## Tab 3 Content: Entry, Scale, Get
# -----------------------------------------------------
sg.Label(tab3, 'Your username: ', line=0, position=0, expand=True, align='left')
# Demonstrating initial_content arg in Entry
username = sg.Entry(tab3, 'superprogrammer', expand=True, align='center', line=0, position=1)
sg.Label(tab3, 'Your age: ', line=1, position=0, expand=True, align='left')
# Demonstrating from_value and to_value in Scale
age = sg.Scale(tab3, from_value=5, to_value=100, line=1, position=1, expand=True, align='center')
def get_settings():
global username, age
yuser = sg.Get(username)
yager = sg.Get(age)
yager = int(yager)
if yuser:
if yager >= 18:
sg.Info('Hello!', f'Hello!, {yuser}, you are an adult (Age: {yager})!')
else:
sg.Info('Hello!', f'Hello, {yuser}, you are a child (Age: {yager})!')
else:
sg.Info('Hey!', f'You need to enter a username!')
sg.Button(tab3, 'Get Data', _command=get_settings, position=1, line=2, expand=True, align='center')
# -----------------------------------------------------
## Tab 4 Content: Listbox
# -----------------------------------------------------
sg.Label(tab4, 'Select the best GUI wrapper:', line=0, position=0, align='left', expand=True, content_size=14, bold=True)
# Demonstrating Listbox creation and values argument
my_list = sg.Listbox(tab4, ['Regula', 'Tkinter', 'PySimpleGUI'], line=1, position=0, align='left', expand=True, height=5)
def get_gui():
global my_list
results = sg.Get(my_list)
# Handle both single string (single mode) or list of strings (multi/extended mode)
selected_value = results if isinstance(results, str) else results[0] if results else None
if selected_value and selected_value != 'Regula':
sg.Error('Hey!', f'Hey! Regula is better than {selected_value}!')
elif selected_value == 'Regula':
sg.Info('Yeah!', 'Yeah! Regula is the best!')
else:
sg.Info('Selection', 'Nothing was selected.')
sg.Button(tab4, 'Choose', _command=get_gui, line=2, position=0, align='center')
# -----------------------------------------------------
## Tab 5 Content: Ask (BMI Calculator)
# -----------------------------------------------------
def ask():
name = sg.Ask('Name', 'Name:', 'string')
if name:
age = sg.Ask('Age', 'Age:', 'int')
if age:
if age > 17:
weight = sg.Ask('Weight', 'Weight (kg):', 'float')
if weight:
height = sg.Ask('Height', 'Height in meters (e.g., 1.75):', 'float')
if height and height > 0:
def imc():
# Corrected BMI calculation: weight / (height ** 2)
return weight / (height**2)
healthy = imc()
if healthy > 18.4 and healthy < 25.0:
status = 'healthy'
elif healthy < 18.5:
status = 'not so healthy, too slim'
elif healthy >= 25.0 and healthy < 30.0:
status = 'not so healthy, a little overweight (or too many muscles)'
else:
status = 'not healthy, a lot overweight (or too many muscles)'
healthy = round(healthy, 1)
sg.Info('Health Condition', f'We calculated your IMC, {name}, and it returned: {status} (Your IMC is {healthy})')
else:
sg.Info('Sorry', f"Sorry, {name}, but we can't calculate the IMC of kids")
return
sg.Button(tab5, 'Calculate health condition', _command=ask, position=0, line=0, expand=True, align='center')
# -----------------------------------------------------
## Tab 6 Content: Wait and Configure
# -----------------------------------------------------
def changer():
timer = random.randint(1500, 3000)
# Uses sg.Wait()
sg.Wait(timer, change)
# Demonstrating initial button configuration
my_Button = sg.Button(tab6, 'I will change some seconds after you click me!', content_size=12, content_color='black', _command=changer)
def change():
global my_Button
colors = ['red', 'green', 'yellow', 'blue', 'orange', 'purple', 'magenta']
color = random.choice(colors) # foreground color
color2 = random.choice(colors) # background color
if color2 == color:
new_colors = colors.copy()
new_colors.remove(color)
color2 = random.choice(new_colors)
messages = ['Changed! (I can change again)', 'Told ya I would change!', 'CHAAANGEED!', 'New look!']
message = random.choice(messages)
# Uses sg.Configure() with Regula arguments: content, content_color (fg), background_color (bg)
sg.Configure(my_Button,
content=message,
content_color=color,
background_color=color2,
bold=True, # New Configure arg
_width=40) # New Configure arg
# -----------------------------------------------------
## Tab 7 Content: FileOpener
# -----------------------------------------------------
# Button to trigger the file dialog
sg.Button(
parent=tab7,
content="Select and Load Text File (.txt)",
_command=open_file_and_read,
line=0,
position=0,
align='n'
)
# Textarea to display the file content
text_output_area = sg.Textarea(
parent=tab7,
initial_content="File content will appear here here after you select a file...",
line=1,
position=0,
height=15,
width=75,
expand=True,
align='center'
)
# -----------------------------------------------------
## Tab 8 Content: New Configure (is_password)
# -----------------------------------------------------
# Create the password Entry widget globally in the tab
password_entry = sg.Entry(
parent=tab8,
initial_content='RegulaIsAwesome',
is_password=True, # Initial setting: hidden
width=30,
line=0,
position=0,
expand=True,
align='center'
)
def show_password():
"""Configures the Entry widget to show characters."""
global password_entry
# Configure using the Regula argument 'is_password=False'
sg.Configure(password_entry, is_password=False)
def hide_password():
"""Configures the Entry widget to hide characters."""
global password_entry
# Configure using the Regula argument 'is_password=True'
sg.Configure(password_entry, is_password=True)
# Create the Checkbutton, linking select_command and unselect_command to the configuration functions
sg.Checkbutton(
parent=tab8,
content='Show password',
is_checked=False, # Initial state: hidden
select_command=show_password,
unselect_command=hide_password, # New Checkbutton command logic
line=1,
position=0,
expand=True,
align='w'
)
# -----------------------------------------------------
## Run the application
# -----------------------------------------------------
sg.Run()Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
Distributed under the MIT License. See LICENSE for more information.