[![Qml.Net](https://img.shields.io/nuget/v/Qml.Net.svg?style=flat&label=Qml.Net)](http://www.nuget.org/packages/Qml.Net/) [![Build status](https://travis-ci.com/qmlnet/qmlnet.svg?branch=develop)](https://travis-ci.com/qmlnet/qmlnet) [![Build status](https://ci.appveyor.com/api/projects/status/l0hh7ranqawj682y/branch/develop?svg=true)](https://ci.appveyor.com/project/pauldotknopf/qmlnet/) [![Gitter](https://img.shields.io/gitter/room/qmlnet/Lobby.svg?style=flat)](https://gitter.im/qmlnet/Lobby) [![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg)](#contributors) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/pauldotknopf)
A Qt/Qml integration with .NET Supported platforms/runtimes: * Runtimes: * .NET Framework * .NET Core * Mono * Operating systems * Linux * OSX * Windows # First look # Elevator pitch * Proven in production. * Established GUI/control framework, used in many industries, from desktop to embedded. * Excellent community with many open-sourced controls available. * Native rendering, done in native code. No expensive PInvoke calls for rendering/animations/etc. The only interop between .NET and Qt is the data models used to drive the GUI. # Documentation WIP: https://qmlnet.github.io/ # Getting started ```bash dotnet add package Qml.Net dotnet add package Qml.Net.WindowsBinaries dotnet add package Qml.Net.OSXBinaries dotnet add package Qml.Net.LinuxBinaries ``` **Note for Linux users**: Package `libc6-dev` is required to be installed because it contains `libdl.so` that is needed. # Examples Checkout the [examples](https://github.com/qmlnet/qmlnet-examples) on how to do many things with Qml.Net. # Quick overview **Define a .NET type (POCO)** ```c# //QmlType.cs using Qml.Net; using System.Threading.Tasks; namespace QmlQuickOverview { [Signal("customSignal", NetVariantType.String)] // You can define signals that Qml can listen to. public class QmlType { /// /// Properties are exposed to Qml. /// [NotifySignal("stringPropertyChanged")] // For Qml binding/MVVM. public string StringProperty { get; set; } /// /// Methods can return .NET types. /// The returned type can be invoked from Qml (properties/methods/events/etc). /// /// public QmlType CreateNetObject() { return new QmlType(); } /// /// Qml can pass .NET types to .NET methods. /// /// public void TestMethod(QmlType parameter) { } /// /// Async methods can be invoked with continuations happening on Qt's main thread. /// public async Task TestAsync() { // On the UI thread await Task.Run(() => { // On the background thread }); // On the UI thread return "async result!"; } /// /// Qml can also pass Qml/C++ objects that can be invoked from .NET /// /// public void TestMethodWithQObject(dynamic o) { string result = o.propertyDefinedInCpp; o.methodDefinedInCpp(result); // You can also listen to signals on QObjects. var qObject = o as INetQObject; var handler = qObject.AttachSignal("signalName", parameters => { // parameters is a list of arguements passed to the signal. }); handler.Dispose(); // When you are done listening to signal. // You can also listen to when a property changes (notify signal). handler = qObject.AttachNotifySignal("property", parameters => { // parameters is a list of arguements passed to the signal. }); handler.Dispose(); // When you are done listening to signal. } /// /// .NET can activate signals to send notifications to Qml. /// public void ActivateCustomSignal(string message) { this.ActivateSignal("customSignal", message); } } } ``` **Register your new type with Qml.** ```c# //QmlExample.cs using Qml.Net; using Qml.Net.Runtimes; namespace QmlQuickOverview { class QmlExample { static int Main(string[] args) { RuntimeManager.DiscoverOrDownloadSuitableQtRuntime(); using (var app = new QGuiApplication(args)) { using (var engine = new QQmlApplicationEngine()) { // Register our new type to be used in Qml Qml.Net.Qml.RegisterType("test", 1, 1); engine.Load("Main.qml"); return app.Exec(); } } } } } ``` **Use the .NET type in Qml** ```js //Main.qml import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import test 1.1 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") QmlType { id: test Component.onCompleted: function() { // We can read/set properties console.log(test.stringProperty) test.stringPropertyChanged.connect(function() { console.log("The property was changed!") }) test.stringProperty = "New value!" // We can return .NET types (even ones not registered with Qml) var netObject = test.createNetObject(); // All properties/methods/signals can be invoked on "netObject" // We can also pass the .NET object back to .NET netObject.testMethod(netObject) // We can invoke async tasks that have continuation on the UI thread var task = netObject.testAsync() // And we can await the task Net.await(task, function(result) { // With the result! console.log(result) }) // We can trigger signals from .NET test.customSignal.connect(function(message) { console.log("message: " + message) }) test.activateCustomSignal("test message!") } function testHandler(message) { console.log("Message - " + message) } } } ``` # Currently implemented - [x] Support for all the basic Qml types and the back-and-forth between them (```DateTime```, ```string```, etc). - [x] Reading/setting properties on .NET objects. - [x] Invoking methods on .NET obejcts. - [x] Declaring and activating signals on .NET objects. - [x] ```async``` and ```await``` with support for awaiting and getting the result from Qml. - [x] Passing dynamic javascript objects to .NET as ```dynamic```. - [x] Custom V8 type that looks like an array, but wraps a .NET ```IList``` instance, for modification of list in Qml, and performance. - [x] Dynamically compiled delegates for increased performance. - [x] Passing ```QObject``` types to .NET with support for interacting with signals/slots/properties on them. There aren't really any important features missing that are needed for prime-time. This product is currently used on embedded devices in the medical industry. # Running Unit Tests The unit tests can be found in [src/native/Qml.Net.Tests](src/net/Qml.Net.Tests). They can be run directly from Visual Studio, or by using the `dotnet test` command line tool. Since the tests rely on the native QmlNet library, you have to ensure the library is in the `PATH` (on Windows) or otherwise discoverable. If you are trying to run tests against the native library built from the same repository, you can put the `src/native/output` folder into your `PATH` or `LD_LIBRARY_PATH` after running the `build.bat` or `build.sh` script. ## Contributors ✨ Thanks goes to these wonderful people!
Michael Lamers
Michael Lamers

💻
TripleWhy
TripleWhy

💻
Max
Max

💻 📖 💵
geigertom
geigertom

💻
James Davila
James Davila

💻
Andy Fillebrown
Andy Fillebrown

💻
Vadim Peretokin
Vadim Peretokin

📖
Linus Juhlin
Linus Juhlin

📖