Skip to main content

Qt integration for Blender

Project description

blender_qt

Qt integration for Blender with support for:

  • custom node-editor spaces backed by QML or QWidget
  • viewport gizmos backed by QML or QWidget
  • managed top-level Qt windows

Developer-oriented architecture and workaround notes live in docs/developer-guide.md.

Stable public API is exposed from the top-level blender_qt package. Modules under blender_qt.core, blender_qt.qml, blender_qt.widgets, and blender_qt._internal should be treated as implementation details unless explicitly documented otherwise.

Installation

pip install blender_qt

The wheel is published for add-on authors who want to depend on Blender Qt from normal Python packaging workflows. The package can be imported outside Blender for metadata and API discovery, but runtime features still require Blender's Python environment and modules such as bpy.

Sample Extension

See the blender_qt_sample repository for a sample Blender extension project that uses this wheel and packages it with beb:

https://github.com/minimalefforttech/blender_qt_sample

That sample uses beb because it is a convenient way to build a Blender extension archive around the published blender_qt package. You do not need to use beb for your own Blender Qt-based add-ons unless that workflow fits your packaging needs.

Lifecycle

Call blender_qt.init() before registering spaces, gizmos, or windows. Call blender_qt.shutdown() when your add-on unloads.

import blender_qt


def register() -> None:
    blender_qt.init()


def unregister() -> None:
    blender_qt.shutdown()

Register a custom QML space

Use register_qml_space() to add a custom node-editor space rendered from a QML root item.

from pathlib import Path

import blender_qt

TREE_TYPE = "MY_ADDON_QML_NT"
QML_PATH = Path(__file__).with_name("main.qml")

blender_qt.register_qml_space(
    tree_type=TREE_TYPE,
    label="My QML Space",
    qml_path=QML_PATH,
    icon="NODETREE",
    sidebar_category="My Tools",
)

Unregister a custom space

Use unregister_space() with the same tree_type.

blender_qt.unregister_space("MY_ADDON_QML_NT")

Register a custom widget space

Use register_widget_space() when your UI is a QWidget tree.

from PySide6 import QtWidgets
import blender_qt


class MyWidgetSurface(QtWidgets.QWidget):
    def __init__(self, parent: QtWidgets.QWidget | None = None) -> None:
        super().__init__(parent)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(QtWidgets.QLabel("Hello from a widget space"))


blender_qt.register_widget_space(
    tree_type="MY_ADDON_WIDGET_NT",
    label="My Widget Space",
    widget_factory=MyWidgetSurface,
    icon="NODETREE",
    sidebar_category="My Tools",
)

Unregister it the same way:

blender_qt.unregister_space("MY_ADDON_WIDGET_NT")

List active custom spaces:

tree_types = blender_qt.registered_space_types()

Register a QML viewport gizmo

Use register_qml_viewport_gizmo() to render a floating viewport panel from QML.

from pathlib import Path

import blender_qt

blender_qt.register_qml_viewport_gizmo(
    gizmo_id="MY_ADDON_QML_GIZMO",
    qml_path=Path(__file__).with_name("gizmo.qml"),
    space_type="VIEW_3D",
    width=320,
    height=220,
    is_2d=True,
    initial_position=(80, 80),
)

3D QML gizmo

Set is_2d=False to anchor the panel in world space.

blender_qt.register_qml_viewport_gizmo(
    gizmo_id="MY_ADDON_QML_GIZMO_3D",
    qml_path=Path(__file__).with_name("gizmo.qml"),
    space_type="VIEW_3D",
    width=320,
    height=220,
    is_2d=False,
    initial_3d_position=(0.0, 0.0, 1.0),
    billboard=True,
    use_depth_test=True,
)

Register a widget viewport gizmo

Use register_widget_viewport_gizmo() to render a floating viewport panel from a QWidget.

from PySide6 import QtWidgets
import blender_qt


class MyViewportPanel(QtWidgets.QWidget):
    def __init__(self, parent: QtWidgets.QWidget | None = None) -> None:
        super().__init__(parent)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(QtWidgets.QPushButton("Action"))


blender_qt.register_widget_viewport_gizmo(
    gizmo_id="MY_ADDON_WIDGET_GIZMO",
    widget_factory=MyViewportPanel,
    label="My Widget Gizmo",
    space_type="VIEW_3D",
    width=280,
    height=180,
    is_2d=True,
    initial_position=(120, 120),
)

Unregister a viewport gizmo

Use unregister_viewport_gizmo() with the same gizmo_id.

blender_qt.unregister_viewport_gizmo("MY_ADDON_WIDGET_GIZMO")

List active gizmos:

gizmo_ids = blender_qt.registered_viewport_gizmo_ids()

Managed windows

Use register_window() for standalone top-level windows.

from PySide6 import QtWidgets
import blender_qt

window = QtWidgets.QDialog()
window.setWindowTitle("My Tool")
blender_qt.register_window(window, unique=True)

Optional close callback:

def _on_window_closed(widget: QtWidgets.QWidget) -> None:
    print("Closed", widget.objectName())


blender_qt.register_window(window, unique=True, on_close=_on_window_closed)

Get active managed windows:

windows = blender_qt.managed_windows()

Close them all:

blender_qt.close_managed_windows()

Recommended add-on structure

import blender_qt


def register() -> None:
    blender_qt.init()
    blender_qt.register_qml_space(
        tree_type="MY_ADDON_QML_NT",
        label="My Space",
        qml_path="/path/to/main.qml",
    )
    blender_qt.register_qml_viewport_gizmo(
        gizmo_id="MY_ADDON_GIZMO",
        qml_path="/path/to/gizmo.qml",
        is_2d=True,
    )


def unregister() -> None:
    blender_qt.unregister_viewport_gizmo("MY_ADDON_GIZMO")
    blender_qt.unregister_space("MY_ADDON_QML_NT")
    blender_qt.shutdown()

Notes

  • tree_type and gizmo_id must be unique.
  • Registering a duplicate space or gizmo raises ValueError.
  • Missing QML files raise FileNotFoundError during registration.
  • QML viewport gizmos use is_2d instead of mode.
  • QML viewport gizmos do not use a label argument.
  • Widget viewport gizmos still accept label, which is used as the host window title.
  • Use VIEW_3D, IMAGE_EDITOR, NODE_EDITOR, CLIP_EDITOR, or SEQUENCE_EDITOR for space_type where supported by Blender.

Project Layout

  • blender_qt: importable package
  • docs: contributor documentation
  • tests: standalone smoke tests for package metadata and public API imports

Releases

GitHub Actions runs tests and build validation on pushes and pull requests, and publishes tagged releases to PyPI.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

blender_qt-0.4.1.tar.gz (75.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blender_qt-0.4.1-py3-none-any.whl (93.3 kB view details)

Uploaded Python 3

File details

Details for the file blender_qt-0.4.1.tar.gz.

File metadata

  • Download URL: blender_qt-0.4.1.tar.gz
  • Upload date:
  • Size: 75.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for blender_qt-0.4.1.tar.gz
Algorithm Hash digest
SHA256 0b3c3936345a9378556562baf41aa34992e810bf37688f9ae65bb78e79d8c4dd
MD5 9945db1f8d161d532554046380aa8ccb
BLAKE2b-256 cbe233ca3fa2c914c686cee67c7694a489d268f55991cba27801a6643c9e1fa2

See more details on using hashes here.

Provenance

The following attestation bundles were made for blender_qt-0.4.1.tar.gz:

Publisher: publish.yml on minimalefforttech/blender_qt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blender_qt-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: blender_qt-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 93.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for blender_qt-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9f1655d0dab83b12f3425dbffe893afbec9284bde70a575850f8d490bd3740dc
MD5 4dff8f2fa6bf1fa288d17e53f538cf65
BLAKE2b-256 525dbbfa0357e11cc6e00333b8e9eb8840b8fa45f5ec22ad4e1775aa026df733

See more details on using hashes here.

Provenance

The following attestation bundles were made for blender_qt-0.4.1-py3-none-any.whl:

Publisher: publish.yml on minimalefforttech/blender_qt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page