Description
Azul is a library for creating graphical user interfaces or GUIs in Rust. It mixes
paradigms from functional, immediate mode GUI programming commonly found in games
and game engines with an API suitable for developing desktop applications.
Instead of focusing on an object-oriented approach to GUI programming ("a button
is an object"), it focuses on combining objects by composition ("a button is a function")
and achieves complex layouts by composing widgets into a larger DOM tree.
Azul separates the concerns of business logic / callbacks, data model and UI
rendering / styling by not letting the UI / rendering logic have mutable access
to the application data. Widgets of your user interface are seen as a "view" into
your applications data, they are not "objects that manage their own state", like
in so many other toolkits. Widgets are simply functions that render a certain state,
more complex widgets combine buttons by calling a function multiple times.
The generated DOM itself is immut
Azul alternatives and similar packages
Based on the "GUI" category.
Alternatively, view Azul alternatives based on common mentions on social networks and blogs.
-
SixtyFPS
DISCONTINUED. Slint is a toolkit to efficiently develop fluid graphical user interfaces for any display: embedded devices and desktop applications. We support multiple programming languages, such as Rust, C++ or JavaScript. [Moved to: https://github.com/slint-ui/slint] -
Relm4
DISCONTINUED. An idiomatic GUI library inspired by Elm and based on gtk4-rs [Moved to: https://github.com/Relm4/Relm4] -
Kiss-ui
A simple UI framework for Rust built on top of IUP (http://webserver2.tecgraf.puc-rio.br/iup/)
InfluxDB - Purpose built for real-time analytics at any scale.
Do you think we are missing an alternative of Azul or a related project?
Popular Comparisons
README
Azul - Desktop GUI framework
<!-- [START badges] --> [](LICENSE) <!-- [END badges] -->
Azul is a free, functional, reactive GUI framework for Rust, C and C++, built using the WebRender rendering engine and a CSS / HTML-like document object model for rapid development of beautiful, native desktop applications
Features
Azul uses webrender (the rendering engine behind Firefox) to render your UI, so it supports lots of common CSS features like:
- gradients (linear, radial, conic)
- box shadows
- SVG filters
- composition operators (multiply, darken, etc.)
- border styling
- border-radii
- scrolling / automatic overflow
- CSS transforms
See the list of supported CSS keys / values for more info.
On top of that, Azul features...
- lots of built-in widgets (Button, TextInput, CheckBox, ColorInput, TextInput, NumberInput)
- embedding OpenGL textures
- simplified HTML-like relative/absolute layout system based on CSS flexbox
- 60+ FPS animations via Animation API
- cross-platform native dialogs
- cross-platform text shaping and rendering
- SVG parsing and rendering
- shape tesselation for rendering large numbers of 2D lines, circles, rects, shapes, etc. in a single draw call
- managing off-main-thread tasks for I/O
- dynamic linking via shared library*
- usable from Rust, C, C++ and Python via auto-generated API bindings**
- HTML-to-Rust compilation for fast prototyping / hot reload
* static linking not yet available
** C++ bindings and Python are not yet stabilized and might not work depending on the branch you're using. They will be stabilized before the release.
Screenshots
Hello World
Python
from azul import *
class DataModel:
def __init__(self, counter):
self.counter = counter
def render_dom(data, info):
label = Dom.text("{}".format(data.counter))
label.set_inline_style("font-size: 50px;")
button = Button("Increment counter")
button.set_on_click(data, increment_counter)
dom = Dom.body()
dom.add_child(label)
dom.add_child(button.dom())
return dom.style(Css.empty())
def increment_counter(data, info):
data.counter += 1;
return Update.RefreshDom
app = App(DataModel(5), AppConfig(LayoutSolver.Default))
app.run(WindowCreateOptions(render_dom))
Rust
use azul::prelude::*;
use azul::widgets::{button::Button, label::Label};
struct DataModel {
counter: usize,
}
extern "C"
fn render_dom(data: &mut RefAny, _: &mut LayoutInfo) -> StyledDom {
let data = data.downcast_ref::<DataModel>()?;
let label = Dom::text(format!("{}", data.counter))
.with_inline_style("font-size: 50px;");
let button = Button::new("Increment counter")
.onmouseup(increment_counter, data.clone());
Dom::body()
.with_child(label)
.with_child(button.dom())
.style(Css::empty())
}
extern "C"
fn increment_counter(data: &mut RefAny, _: &mut CallbackInfo) -> Update {
let mut data = data.downcast_mut::<DataModel>()?;
data.counter += 1;
Update::RefreshDom // call render_dom() again
}
fn main() {
let initial_data = RefAny::new(DataModel { counter: 0 });
let app = App::new(initial_data, AppConfig::default());
app.run(WindowCreateOptions::new(render_dom));
}
C
#include "azul.h"
typedef struct {
uint32_t counter;
} DataModel;
void DataModel_delete(DataModel* restrict A) { }
AZ_REFLECT(DataModel, DataModel_delete);
AzStyledDom render_dom(AzRefAny* data, AzLayoutInfo* info) {
DataModelRef d = DataModelRef_create(data);
if !(DataModel_downcastRef(data, &d)) {
return AzStyledDom_empty();
}
char buffer [20];
int written = snprintf(buffer, 20, "%d", d->counter);
AzString const labelstring = AzString_copyFromBytes(&buffer, 0, written);
AzDom label = AzDom_text(labelstring);
AzString const inline_css = AzString_fromConstStr("font-size: 50px;");
AzDom_setInlineStyle(&label, inline_css);
AzString const buttontext = AzString_fromConstStr("Increment counter");
AzButton button = AzButton_new(buttontext, AzRefAny_clone(data));
AzButton_setOnClick(&button, incrementCounter);
AzDom body = Dom_body();
AzDom_addChild(body, AzButton_dom(&button));
AzDom_addChild(body, label);
AzCss global_css = AzCss_empty();
return AzDom_style(body, global_css);
}
Update incrementCounter(RefAny* data, CallbackInfo* event) {
DataModelRefMut d = DataModelRefMut_create(data);
if !(DataModel_downcastRefMut(data, &d)) {
return Update_DoNothing;
}
d->ptr.counter += 1;
DataModelRefMut_delete(&d);
return Update_RefreshDom;
}
int main() {
DataModel model = { .counter = 5 };
AzApp app = AzApp_new(DataModel_upcast(model), AzAppConfig_default());
AzApp_run(app, AzWindowCreateOptions_new(render_dom));
return 0;
}
License
Azul is licensed under the MPL-2.0. Which means that yes, you can build proprietary applications using azul without having to publish your code: you only have to publish changes made to the library itself.
Copyright 2017 - current Felix Schütt
*Note that all licence references and agreements mentioned in the Azul README section above
are relevant to that project's source code only.