qtrs — Rust-style Qt6 bindings
A type-safe, builder-pattern-driven Qt6 GUI library for Rust. Built on
cxx for zero-cost C++ interop, with RAII memory
management and signal/callback bridging.
Features
- Builder pattern — chain
.title("X").size(800, 600).show() - RAII cleanup — automatic C++ deletion, parent-child aware (no double-free)
- Signal bridging — Qt signals invoke Rust closures via a global trampoline
- Layout ownership — adding a widget to a layout transfers ownership
- QML / Qt Quick support — load
.qmlfiles with Rust backend (feature = "qml") - .ui file loading — load Qt Designer
.uifiles at runtime (feature = "ui") - Zero unsafe in public API — all FFI is encapsulated
Quick Start
use *;
Widgets
| Type | Qt class | Signals |
|---|---|---|
Application |
QApplication |
— |
Widget |
QWidget |
— |
PushButton |
QPushButton |
on_clicked |
Label |
QLabel |
— |
LineEdit |
QLineEdit |
on_return_pressed |
CheckBox |
QCheckBox |
on_toggled(bool) |
ComboBox |
QComboBox |
on_current_text_changed |
TextEdit |
QTextEdit |
on_text_changed |
Slider |
QSlider |
on_value_changed(i32) |
Timer |
QTimer |
on_timeout |
VBoxLayout |
QVBoxLayout |
— |
HBoxLayout |
QHBoxLayout |
— |
GridLayout |
QGridLayout |
— |
QML Example
use *;
With main.qml:
import QtQuick 2.15
import QtQuick.Controls 2.15
Window {
width: 400
height: 300
title: "QML with qtrs"
visible: true
Button {
text: "Click me"
anchors.centerIn: parent
onClicked: backend.onButtonClicked()
}
Connections {
target: backend
function onButtonClicked() {
console.log("Button clicked from Rust!")
}
}
}
Run with:
Prerequisites
Qt6 with development headers:
| Platform | Instructions |
|---|---|
| Debian / Ubuntu | sudo apt install qt6-base-dev qt6-declarative-dev |
| Fedora | sudo dnf install qt6-qtbase-devel qt6-qtdeclarative-devel |
| Arch | sudo pacman -S qt6-base qt6-declarative |
| macOS (Homebrew) | brew install qt@6 |
| Windows | Install from qt.io or via vcpkg |
macOS notes
After installing via Homebrew, tell pkg-config where to find Qt:
Add this to your ~/.zshrc or ~/.bashrc for persistence.
Windows notes
The build script uses pkg-config to locate Qt. When using vcpkg,
set the environment variable:
$env:PKG_CONFIG_PATH = "$env:VCPKG_ROOT\installed\x64-windows\lib\pkgconfig"
When using the official Qt installer, set CMAKE_PREFIX_PATH and
ensure qmake6 is on your PATH.
$env:CMAKE_PREFIX_PATH = "C:\Qt\6.8.2\msvc2022_64"
$env:PATH += ";C:\Qt\6.8.2\msvc2022_64\bin"
A Microsoft Visual Studio build toolchain (MSVC) is required on Windows.
Installation
Add to your Cargo.toml:
[]
= "0.1.0"
Enable QML support:
[]
= { = "0.1.0", = ["qml"] }
Enable .ui file loading:
[]
= { = "0.1.0", = ["ui"] }
Enable both:
[]
= { = "0.1.0", = ["qml", "ui"] }
Memory management
Widgets are deleted automatically on Drop — unless they have a Qt
parent (set explicitly or via layout). In that case Qt's parent-child tree
handles deletion, preventing double-free.
Widget created without parent -> Drop deletes C++ object
Widget created with parent -> Drop skips deletion (Qt handles it)
Widget added to layout -> Layout takes ownership, Drop skips deletion
Thread safety
Qt GUI classes are not thread-safe. All widget creation, mutation, and the event loop must happen on the main thread.
License
MIT OR Apache-2.0 — see LICENSE-MIT and LICENSE-APACHE.