A lightweight, simplified wrapper around the Tkinter library for faster desktop application development.
Project description
Regula
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.
✨ Features
- 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.
🚀 Installation
Assuming you have Python 3.8+ installed:
pip install regula
Example Usage
import regula as sg
import random
import sys # Needed for file reading error handling
sg.Window(title="Regula Example App", geometry="890x380", bg="#E6E6FA")
# --- Global Widgets for Tab 7 ---
# Need a global reference to the Textarea so the button command can update it
text_output_area = 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
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 1 Content ---
def to_do():
sg.Info("Yay!", "Haha!")
sg.Label(tab1, line=0, position=0, align='left', expand=True, bold=False, content='Press the button: ')
sg.Button(tab1, _command=to_do, line=0, position=1, align='center', expand=True, _width=5, _height=0)
# --- Tab 2 Content ---
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?!')
sg.Button(tab2, "And don't press here", expand=True, _command=get_texter)
# --- Tab 3 Content ---
sg.Label(tab3, 'Your username: ', line=0, position=0, expand=True, align='left')
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')
age = sg.Scale(tab3, 5, 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!')
else:
sg.Info('Hello!', f'Hello, {yuser}, you are a child!')
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 ---
my_list = sg.Listbox(tab4, ['Regula', 'Tkinter', 'Pygame'], line=1, position=0, align='left', expand=True)
def get_gui():
global my_list
results = sg.Get(my_list)
if not results == 'Regula':
sg.Error('Hey!', f'Hey! Regula is better than {results}!')
else:
sg.Info('Yeah!', 'Yeah! Regula is the best!')
sg.Button(tab4, 'Choose', _command=get_gui, line=1, position=2)
# --- Tab 5 Content (Corrected IMC Logic) ---
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:', '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 ---
def changer():
timer = random.randint(1500, 3000)
sg.Wait(timer, change)
my_Button = sg.Button(tab6, 'I will change some seconds after you click me!', 12, 'black', _command=changer)
def change():
global my_Button
colors = ['red', 'green', 'yellow', 'blue', 'orange']
color = random.choice(colors)
color2 = random.choice(colors)
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!']
message = random.choice(messages)
sg.Configure(my_Button, text=message, fg=color, bg=color2)
# --- 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'
)
sg.Run()
🤝 Contributing
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
📄 License
Distributed under the MIT License. See LICENSE for more information.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file regula-0.1.1.tar.gz.
File metadata
- Download URL: regula-0.1.1.tar.gz
- Upload date:
- Size: 14.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
084a0a5aee47e13e7317a66f5373adab4754612d50f3a76af8d1bcde9a978c12
|
|
| MD5 |
6fe880143d6bc8f1791f3322ea1738bc
|
|
| BLAKE2b-256 |
5308c187c7834e63436f03730ff50221b7c2346cf3d170e8d8b284066e0b37e1
|
File details
Details for the file regula-0.1.1-py3-none-any.whl.
File metadata
- Download URL: regula-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47f2b33ff5ae1c9e64daa7c23da0159e2fe538e08183dab4b99f9bcdcede49ca
|
|
| MD5 |
8d98b647812d098390a4430a4d2b4303
|
|
| BLAKE2b-256 |
1b3c99df460bfb136bafbe4bede481b878b11efd2eaa2556b506f35838dfbf19
|