Cpython and UI elements (eg dialogs)

I just wanted to check the current state of pyRevit in relation to using CPython and being able to build UIs.
From my research, it sounds like this wasn’t achievable in the past, and people had to write tools in IronPython and use subprocess to execute cpython code if they needed to connect other libraries to their tooling?

I want to build a simple dialog with a form from a CPython script.

What’s the recommended approach to take, and are there any up to date examples I can refer to?

Thanks!

You can use winforms for simple dialogs.
What doesn’t work is the WPF XAML bindings, and for that the pyrevit.forms is not available for cpython scripts.

A simple Winform example. I had to replicate the Toaster as my IT department burnt the pyRevit Toaster.

__author__ = "Aaron Rumple, AIA"
__copyright__ = "Copyright 2025, Aaron Rumple"
__credits__ = ["Aaron Rumple"]
__license__ = "GPL"
__version__ = "2025.2.07"
__maintainer__ = "Aaron Rumple"
__email__ = "aaronrumple@gmail.com"
__status__ = "Production"

import System
import clr
import sys
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")

from System.Windows.Forms import Application, Form, Label, Timer, Button, DockStyle
from System.Drawing import Color, Font, Point, Size, ContentAlignment, FontStyle

class OttoPilotToaster(Form):
    def __init__(self, title="Notification", message="You have a new message!"):
        # Set form properties
        self.FormBorderStyle = 0  # No border
        self.StartPosition = 0  # Manual position
        self.Size = Size(400, 120)
        self.BackColor = Color.Black
        self.Opacity = 0.666
        self.TopMost = True
        self.ShowInTaskbar = False

        # Get screen dimensions
        screen = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea
        self.Location = Point(screen.Width - self.Width - 10, screen.Height - self.Height - 10)

        # Create title label
        self.title_label = Label()
        self.title_label.Text = title
        self.title_label.ForeColor = Color.White
        self.title_label.Font = Font("Arial", 11, FontStyle.Bold)
        self.title_label.BackColor = Color.DarkGray
        self.title_label.Size = Size(self.Width, 30)
        self.title_label.TextAlign = ContentAlignment.MiddleLeft
        self.title_label.Padding = System.Windows.Forms.Padding(10, 0, 0, 0)
        self.title_label.Dock = DockStyle.Top
        self.title_label.BackColor = Color.Black  # Black title bar
        self.title_label.Click += self.close_notification  # Close on click
        self.Controls.Add(self.title_label)

        # Create message label
        self.message_label = Label()
        self.message_label.Text = message
        self.message_label.ForeColor = Color.White
        self.message_label.Font = Font("Arial", 9, FontStyle.Bold)
        self.message_label.TextAlign = ContentAlignment.MiddleLeft
        self.message_label.Padding = System.Windows.Forms.Padding(10, 0, 0, 0)
        self.message_label.Dock = DockStyle.Fill
        self.message_label.Click += self.close_notification  # Close on click
        self.Controls.Add(self.message_label)

        # Timer for auto-close
        self.timer = Timer()
        self.timer.Interval = 5000  # 15 seconds
        self.timer.Tick += self.close_notification
        self.timer.Start()

        # Close form when clicked anywhere
        self.Click += self.close_notification

    def close_notification(self, sender, event=None):
        self.Close()

def Inflate(ottotitle, ottomessage):
    title = sys.argv[1] if len(sys.argv) > 1 else ottotitle
    message = sys.argv[2] if len(sys.argv) > 2 else ottomessage
    Application.EnableVisualStyles()
    Application.Run(OttoPilotToaster(title, message))
 
    
if __name__ == "__main__":
    Inflate("Otto Pilot says...", "Hello from IronPython!")

2 Likes