Quick Start¶
This guide walks you through PyWry's core functionality with practical examples. Each example builds on concepts introduced earlier.
Prerequisites¶
Make sure you have PyWry installed:
For Plotly examples, also install Plotly:
1. Hello World¶
The simplest PyWry application:
from pywry import PyWry
app = PyWry()
app.show("Hello World!")
app.block() # Keep the window open until user closes it
What's happening:
PyWry()creates an application instanceapp.show()opens a native window with your content (can be plain text, HTML, or anHtmlContentobject)app.block()pauses your script until the window is closed
When to use block()
Your application exits when the script finishes, or the IDE is stopped.
Use app.block() at the end of scripts to keep the window alive.
In notebooks or servers, you typically don't need it.
Use this technique to block the main application while waiting for oAuth2 providers to respond.
2. Display HTML Content¶
PyWry renders HTML, not just text:
from pywry import PyWry
app = PyWry()
html = """
<div style="padding: 20px; text-align: center;">
<h1 id="greeting">Welcome to PyWry</h1>
<p>This is rendered HTML with styling.</p>
<button onclick="window.pywry.emit('app:button-click', {clicked: true})">
Click me!
</button>
</div>
"""
app.show(html, title="My First Window", width=600, height=400)
app.block()
Key points:
- Pass any valid HTML string to
app.show() - Use
title,width,heightto customize the window - JavaScript can call
window.pywry.emit()to send events to Python
3. Handle Events with Callbacks¶
The real power of PyWry is bidirectional communication. Python can respond to JavaScript events:
from pywry import PyWry
app = PyWry()
def on_button_click(data, event_type, label):
"""Called when the button is clicked."""
print(f"Button clicked! Data: {data}")
# Update the page content
app.emit("pywry:set-content", {"id": "greeting", "text": "Button was clicked!"}, label)
html = """
<div style="padding: 20px; text-align: center;">
<h1 id="greeting">Click the button below</h1>
<button onclick="window.pywry.emit('app:button-click', {time: Date.now()})">
Click me!
</button>
</div>
"""
app.show(
html,
callbacks={"app:button-click": on_button_click},
)
app.block()
How callbacks work:
- JavaScript calls
window.pywry.emit('app:button-click', {...})when the button is clicked - PyWry routes this to your Python callback registered in
callbacks={"app:button-click": on_button_click} - Your callback receives three arguments:
data: The payload from JavaScript (the second argument toemit)event_type: The event name ("app:button-click")label: The window/widget identifier (for targeting responses)- Your callback can send events back using
app.emit()orhandle.emit()
4. Use Toolbar Components¶
Instead of writing HTML buttons, use PyWry's declarative toolbar components:
from pywry import PyWry, Toolbar, Button
app = PyWry()
def on_click(data, event_type, label):
"""Update the heading when button is clicked."""
app.emit("pywry:set-content", {"selector": "h1", "text": "Toolbar Works!"}, label)
toolbar = Toolbar(
position="top",
items=[
Button(label="Update Text", event="app:click"),
Button(label="Show Alert", event="app:alert", variant="secondary"),
]
)
def on_alert(data, event_type, label):
"""Show a toast notification."""
app.emit("pywry:alert", {"message": "Hello from Python!"}, label)
app.show(
"<h1>Hello, World!</h1>",
toolbars=[toolbar],
callbacks={
"app:click": on_click,
"app:alert": on_alert,
},
)
app.block()
Toolbar concepts:
Toolbar(position="top", items=[...])creates a toolbar at one of 7 positions:top,bottom,left,right,header,footer,insideButton(label="...", event="...")creates a button that emits the specified event when clicked- The
eventname follows thenamespace:event-namepattern (e.g.,app:click,view:reset) variantcontrols the button style:primary,secondary,neutral,ghost,outline,danger,warning,icon
5. Display a Pandas DataFrame with AgGrid¶
PyWry includes first-class support for displaying DataFrames using AG Grid:
from pywry import PyWry
import pandas as pd
app = PyWry()
df = pd.DataFrame({
"name": ["Alice", "Bob", "Carol", "David"],
"age": [30, 25, 35, 28],
"department": ["Engineering", "Marketing", "Engineering", "Sales"],
})
def on_row_selected(data, event_type, label):
"""Called when rows are selected in the grid."""
rows = data.get("rows", [])
if rows:
names = ", ".join(row["name"] for row in rows)
app.emit("pywry:alert", {"message": f"Selected: {names}"}, label)
handle = app.show_dataframe(
df,
title="Employee Data",
callbacks={"grid:row-selected": on_row_selected},
)
app.block()
Grid features:
show_dataframe()automatically converts your DataFrame to an AG Grid- Pre-wired events like
grid:row-selected,grid:cell-clicked,grid:cell-value-changedare ready to use - Click rows to select them; your callback receives the selected row data
- Use
grid_optionsparameter for advanced AG Grid configuration
6. Display a Plotly Chart¶
PyWry integrates seamlessly with Plotly for interactive charts:
from pywry import PyWry, Toolbar, Button
import plotly.express as px
app = PyWry(theme="light")
# Create a Plotly figure
fig = px.scatter(
px.data.iris(),
x="sepal_width",
y="sepal_length",
color="species",
title="Iris Dataset"
)
def on_chart_click(data, event_type, label):
"""Called when a point on the chart is clicked."""
point = data["points"][0]
new_title = f"Clicked: ({point['x']:.2f}, {point['y']:.2f}) - {point.get('marker.color', 'N/A')}"
app.emit("plotly:update-layout", {"layout": {"title": new_title}}, label)
def on_reset(data, event_type, label):
"""Reset the chart zoom level."""
app.emit("plotly:reset-zoom", {}, label)
toolbar = Toolbar(
position="top",
items=[Button(label="Reset Zoom", event="app:reset")]
)
handle = app.show_plotly(
fig,
toolbars=[toolbar],
callbacks={
"plotly:click": on_chart_click,
"app:reset": on_reset,
},
)
app.block()
Plotly features:
show_plotly()renders any Plotly figure with full interactivity- Pre-wired events:
plotly:click,plotly:hover,plotly:select,plotly:double-click - Use
plotly:update-layoutto dynamically update chart properties - Use
plotly:reset-zoomto reset the view - Combine with toolbars for Dash-like dashboards
7. Combine Everything¶
Here's a more complete example combining a chart with interactive controls:
from pywry import PyWry, Toolbar, Button, Select, Option
import plotly.express as px
app = PyWry(theme="light")
# Load sample data
df = px.data.gapminder()
def create_chart(year):
"""Create a chart for the given year."""
filtered = df[df["year"] == year]
return px.scatter(
filtered,
x="gdpPercap",
y="lifeExp",
size="pop",
color="continent",
hover_name="country",
log_x=True,
title=f"Life Expectancy vs GDP ({year})",
)
def on_year_change(data, event_type, label):
"""Update chart when year selection changes."""
year = int(data["value"])
fig = create_chart(year)
# Update the entire chart
app.emit("plotly:replace", {"figure": fig.to_dict()}, label)
# Create year selector
years = sorted(df["year"].unique())
toolbar = Toolbar(
position="top",
items=[
Select(
label="Year:",
event="app:year-change",
options=[Option(label=str(y), value=str(y)) for y in years],
selected=str(years[-1]),
),
]
)
# Initial chart
fig = create_chart(years[-1])
handle = app.show_plotly(
fig,
toolbars=[toolbar],
callbacks={"app:year-change": on_year_change},
width=1000,
height=600,
)
app.block()
Next Steps¶
You now understand the basics of PyWry. Continue with:
- Rendering Paths — Native windows, notebook widgets, and browser mode
- Event System — How callbacks work and common patterns
- Event Reference — Complete list of all events and payloads
- Toolbar System — Building interactive controls
- Configuration — TOML files, environment variables, security presets