Skip to main content

Qutie

Yet another pythonic UI library for rapid prototyping using PyQt5.

Quick start

import qutie as ui

app = ui.Application()
window = ui.Widget(
    title="Example",
    icon='orange',
    width=320,
    height=240,
    layout=ui.Column(
        ui.Label("Hello world!"),
        ui.Row(
            ui.Button("Go!", clicked=lambda: ui.show_info(text="Hello world!")),
            ui.Button("Quit", clicked=app.quit)
        )
    )
)
window.show()
app.run()

Documentation

Qutie (pronounced as cutie) provides a simple and easy to use pythonic interface to PyQt5.

Install

pip install qutie

Application

A single Application object must be created before other widgets. To make use of the event system the application event loop must be executed.

import qutie as ui

# Create an application object.
app = ui.Application(name='app', version='1.0')

# Create a window.
window = ui.MainWindow()
window.resize(800, 600)
window.show()

# Run the event loop.
app.run()

Widgets

Any widget can be a top level window or part of another widget using the layout property. All properties can be assigned using the constructor.

window = ui.Widget(title="Example", width=320, height=240)

To make a top level window visible use property visible or call method show().

window.show()
window.visible = True # equivalent to show

Layouts

The simplified layout system provides a horizontal Row and a vertical Column box. Items can be added while constructing the layout or using list like methods append and insert. The consumed space of every child widget can be adjusted using the stretch attribute.

window.layout = ui.Row(
    ui.Column(
        ...
    ),
    ui.Column(
        ui.Row(...),
        ui.Row(...),
        ui.Row(...),
        stretch=(1, 0, 0)
    ),
    stretch=(2, 3)
)

Inputs

# Single line text input
text = ui.Text(value="spam")
# Numeric input
number = ui.Number(value=4, minimum=0, maximum=10, step=1.0, decimals=1)
# A multi line text area
textarea = ui.TextArea(value="Lorem ipsum et dolor.")

Events

Events provide a simplified interface to Qt's signal and slot system. Events can be emitted from any class inheriting from Object by calling method emit().

# Use any callable class attribute as event callback.
window.issue_call = lambda: print("Call to action!")
# Emit an event executing attribute `issue_call` (if callable).
window.emit('issue_call')

Events can also propagate positional and keyword arguments.

# Use any callable class attribute as event callback.
window.update_progress = lambda a, b: print(f"Progress: {a} of {b}")
# Emit an event executing attribute `update_progress` (if callable).
window.emit('update_progress', 42, 100)

Many widgets provide predefined events.

# Assigning callback functions
ui.Number(value=4, changed=on_change, editing_finished=on_edited)

Timers

Call repeating or delayed events using timers.

timer = ui.Timer(interval=1.0, timeout=lambda: print("Done!"))
timer.start()

Function single_shot exposes a convenient single shot timer.

ui.single_shot(interval=1.0, timeout=lambda: print("Done!"))

Note that timer events are only processed when running the application event loop.

Settings

Persistent settings can be stored/restored using a Settings object as context manager. It provides application wide settings as a JSON dictionary.

with ui.Settings() as settings:
    value = settings.get('key', 'default')
    settings['key'] = value

Use attribute filename to inspect the persistent JSON data.

>>> ui.Settings().filename
'/home/user/.config/app.qutie'

Menus

Menu bars and menus behave like python lists.

window = ui.MainWindow()
file_menu = window.menubar.append("&File")
quit_action = file_menu.append("&Quit")
quit_action.triggered = window.close
foo_menu = window.menubar.insert(window.menubar.index(file_menu), "&Foo")
file_menu = window.menubar.remove(file_menu)

Toolbars

Toolbars also behave like python lists, the main window toolbars property behaves like a set.

window = ui.MainWindow()
toolbar = window.toolbars.add("toolbar")
toolbar.append(quit_action)
toolbar.insert(quit_action)
window.toolbars.remove(toolbar)

Workers

The Worker class provides a convenient way to work with background threads. Use attribute target to assign the function to be executed in the background.

def calculate(worker):
    for i in range(100):
        ...

worker = ui.Worker(target=calculate)
worker.start()

Important: use only the event system to propagate information from inside the worker. Do not access widgets from within the worker function.

def calculate(worker):
    for i in range(100):
        # Emit custom events.
        worker.emit('progress', i, 100)
        worker.emit('message', "All ok...")

worker = ui.Worker(target=calculate)
# Assign custom event callbacks.
worker.progress = lambda step, max: print(f"progress: {step}/{max}")
worker.message = lambda msg: print(f"message: {msg}")
worker.start()

To control worker lifetime use method stop() and attribute stopping.

def calculate(worker):
    while not worker.stopping:
        ...

worker = ui.Worker(target=calculate)
worker.start()
...
worker.stop()

To wait for a worker to actually stop use method join().

worker.stop()
worker.join()

Example

A simple dialog with progress bar running a calculation in the background.

import random
import time

import qutie as ui

class Dialog(ui.Dialog):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Create worker
        self.worker = ui.Worker(target=self.calculate)
        self.worker.finished = self.close
        self.worker.update_progress = self.update_progress
        # Create layout
        self.progress_bar = ui.ProgressBar()
        self.layout = self.progress_bar

    def run(self):
        # Start, stop and join worker
        self.worker.start()
        super().run()
        self.worker.stop()
        self.worker.join()

    def update_progress(self, value, maximum):
        self.progress_bar.maximum = maximum
        self.progress_bar.value = value

    def calculate(self, worker):
        n = 32
        for i in range(n):
            if worker.stopping:
                break
            # Emit custom event
            worker.emit('update_progress', i, n)
            time.sleep(random.random())

app = ui.Application()

dialog = Dialog(title="Worker")
dialog.run()

Something missing?

Any underlying PyQt5 instance can be accessed directly using property qt. This also enables to mix in custom PyQt5 classes and instances.

widget.qt.setWindowTitle("Spam!")
widget.qt.customContextMenuRequested.connect(lambda pos: None)
widget.qt.layout().addWidget(QtWidgets.QPusbButton())

License

Qutie is licensed under the GNU General Public License Version 3.

Metadata

Release files for qutie 1.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qutie 1.7.0
File Size Uploaded
qutie-1.7.0.tar.gz 32.8 kB Details

Release files / qutie-1.7.0.tar.gz

Download URL qutie-1.7.0.tar.gz
Size 32.8 kB
Tags Source
SHA-256 checksum
How to use checksums
57e86ba014beaea4ff6c3afa5994a235371c942823125988ae9e1cb7c36ac05d
BLAKE2b-256 checksum
How to use checksums
a330141e38e6b838f494fba1dc13abcfa302ece4fa4a70d7f33b11253b31f447
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/39.0.1 requests-toolbelt/0.9.1 tqdm/4.57.0 CPython/3.6.9

Release history Release notifications | RSS feed

This release

1.7.0 This release

1 release file

1.6.1

1 release file

1.6.0

1 release file

1.5.2

1 release file

1.5.1

1 release file

1.5.0

1 release file

1.4.1

1 release file

1.4.0

1 release file

1.3.3

1 release file

1.3.2

1 release file

1.3.1

1 release file

1.3.0

1 release file

1.2.0

1 release file

1.1.1

1 release file

1.1.0

1 release file

1.0.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page