Rust bindings for the FLTK Graphical User Interface library.
The FLTK crate is a crossplatform lightweight gui library which can be statically linked to produce small, self-contained and fast gui applications.
Why choose FLTK?
- Lightweight. Small binary, around 1mb after stripping. Small memory footprint.
- Speed. Fast to install, fast to build, fast at startup and fast at runtime.
- Single executable. No DLLs to deploy.
- Supports old architectures.
- FLTK's permissive license which allows static linking for closed-source applications.
- Themability (4 supported themes: Base, GTK, Plastic and Gleam).
- Provides around 80 customizable widgets.
- Has inbuilt image support.
Here is a list of software using FLTK.
Just add the following to your project's Cargo.toml file:
[dependencies]
fltk = "^0.9"
The library is automatically built and statically linked to your binary.
You can also enable ninja builds for a faster build of the C++ source using the "use-ninja" feature.
An example hello world application:
use fltk::{app::*, window::*};
fn main() {
let app = App::default();
let mut wind = Window::new(100, 100, 400, 300, "Hello from rust");
wind.end();
wind.show();
app.run().unwrap();
}
Another example showing the basic callback functionality:
use fltk::{app::*, button::*, frame::*, window::*};
fn main() {
let app = App::default();
let mut wind = Window::new(100, 100, 400, 300, "Hello from rust");
let mut frame = Frame::new(0, 0, 400, 200, "");
let mut but = Button::new(160, 210, 80, 40, "Click me!");
wind.end();
wind.show();
but.set_callback(Box::new(move || frame.set_label("Hello World!")));
app.run().unwrap();
}
Please check the examples directory for more examples. You will notice that all widgets are instantiated with a new() method, taking the x and y coordinates, the width and height of the widget, as well as a label which can be left blank if needed. Another way to initialize a widget is using the builder pattern: (The following buttons are equivalent)
let but1 = Button::new(10, 10, 80, 40, "Button 1");
let but2 = Button::default()
.with_pos(10, 10)
.with_size(80, 40)
.with_label("Button 2");
An example of a counter showing use of the builder pattern:
fn main() {
let app = App::default();
let mut wind = Window::default()
.with_size(160, 200)
.center_screen()
.with_label("Counter");
let mut frame = Frame::default()
.with_size(100, 40)
.center_of(&wind)
.with_label("0");
let mut but_inc = Button::default()
.size_of(&frame)
.above_of(&frame, 0)
.with_label("+");
let mut but_dec = Button::default()
.size_of(&frame)
.below_of(&frame, 0)
.with_label("-");
wind.make_resizable(true);
wind.end();
wind.show();
/* Event handling */
}
Event handling must be done after the drawing is done and the main window shown. And must be done in the main thread
Events can be handled using the set_callback method (as above) or the available fltk::app::set_callback() free function, which will handle the default trigger of each widget(like clicks for buttons):
/* previous hello world code */
but.set_callback(Box::new(move || frame.set_label("Hello World!")));
app.run().unwrap();
Another way is to use message passing:
/* previous counter code */
let (s, r) = app::channel::<Message>();
but_inc.emit(s, Message::Increment);
but_dec.emit(s, Message::Decrement);
while app.wait().unwrap() {
let label: i32 = frame.label().parse().unwrap();
match r.recv() {
Some(Message::Increment) => frame.set_label(&(label + 1).to_string()),
Some(Message::Decrement) => frame.set_label(&(label - 1).to_string()),
None => (),
}
}
For the remainder of the code, check the full example here.
For custom event handling, the handle() method can be used:
some_widget.handle(Box::new(move |ev: Event| {
match ev {
/* handle ev */
}
}));
Handled or ignored events using the handle method should return true, unhandled events should return false. More examples are available in the fltk/examples directory.
FLTK offers 4 application themes (called schemes):
- Base
- Gtk
- Gleam
- Plastic
These can be set using the App::with_scheme() method.
let app = App::default().with_scheme(AppScheme::Gleam);
Themes of individual widgets can be optionally modified using the provided methods in the WidgetExt trait, such as set_color(), set_label_font(), set_frame() etc:
some_button.set_color(Color::Light1); // You can use one of the provided colors in the fltk enums
some_button.set_color(Color::from_rgb(255, 0, 0)); // Or you can specify a color by rgb or hex/u32 value
some_button.set_color(Color::from_u32(0xffebee));
some_button.set_frame(FrameType::RoundUpBox);
some_button.set_font(Font::TimesItalic);
The following are the features offered by the crate:
- use-ninja: If you have ninja build installed, it builds faster than make or VS
- system-libpng: Uses the system libpng
- system-libjpeg: Uses the system libjpeg
- system-zlib: Uses the system zlib
- fltk-bundled: Support for bundled versions of cfltk and fltk on selected platforms (requires curl and tar)
- enable-glwindow: Support for drawing using OpenGL functions.
Rust (version > 1.38), CMake (version > 3.0), Git and a C++11 compiler need to be installed and in your PATH for a crossplatform build from source. This crate also offers a bundled form of fltk on selected platforms, this can be enabled using the fltk-bundled feature flag (which requires curl and tar to download and unpack the bundled libraries).
- Windows: No dependencies.
- MacOS: No dependencies.
- Linux: X11 and OpenGL development headers need to be installed for development.
For Debian-based GUI distributions, that means running:
$ sudo apt-get install libx11-dev libxext-dev libxft-dev libxinerama-dev libxcursor-dev libxrender-dev libxfixes-dev libgl1-mesa-dev libglu1-mesa-dev
For RHEL-based GUI distributions, that means running:
$ sudo yum groupinstall "X Software Development"
For Arch-based GUI distributions, that means running:
$ sudo pacman -S libx11 libxext libxft libxinerama libxcursor libxrender libxfixes libgl mesa --needed
If you have ninja-build installed, you can enable it using the "use-ninja" feature. This should accelerate build times significantly.
please check the FAQ page for frequently asked questions, encountered issues, guides on deployment, and contribution.
To build, just run:
$ git clone https://github.com/MoAlyousef/fltk-rs
$ cd fltk-rs
$ cargo build
To run the examples:
$ cargo run --example editor
$ cargo run --example calculator
$ cargo run --example gallery
$ cargo run --example terminal_colored
$ cargo run --example counter
$ cargo run --example hello
$ cargo run --example hello_button
...
Setting the scheme to Gtk:
Check the full code for the custom theming.
Setting the scheme to Gtk:
Different frame types which can be used with many different widgets such as Frame, Button widgets, In/Output widgets...etc.
The most commonly widgets are implemented:
- Image widgets
- SharedImage
- BmpImage
- JpegImage
- GifImage
- PngImage
- SvgImage
- Pixmap
- RgbImage
- XpmImage
- XbmImage
- PnmImage
- TiledImage
- Buttons
- Button
- RadioButton
- ToggleButton
- RoundButton
- CheckButton
- LightButton
- RepeatButton
- RadioLightButton
- RadioRoundButton
- Dialogs
- Native FileDialog
- FileChooser
- HelpDialog
- Message dialog
- Alert dialog
- Password dialog
- Choice dialog
- Input dialog
- ColorChooser dialog
- Frame (Fl_Box)
- Windows
- Window
- SingleWindow
- DoubleWindow
- MenuWindow
- GlWindow (requires the "enable-glwindow" flag)
- Groups
- Group
- Pack
- Tabs
- Scroll
- Tile
- Wizard
- ColorChooser
- Text display widgets
- TextDisplay
- TextEditor
- SimpleTerminal
- Input widgets
- Input
- IntInput
- FloatInput
- MultilineInput
- SecretInput
- FileInput
- Output widgets
- Output
- MultilineOutput
- Menu widgets
- MenuBar
- MenuItem
- Choice (dropdown list)
- SysMenuBar (MacOS menu bar which appears at the top of the screen)
- Valuator widgets
- Slider
- NiceSlider
- ValueSlider
- Dial
- LineDial
- Counter
- Scrollbar
- Roller
- Adjuster
- ValueInput
- ValueOutput
- FillSlider
- FillDial
- HorSlider (Horizontal slider)
- HorFillSlider
- HorNiceSlider
- HorValueSlider
- Browsing widgets
- Browser
- SelectBrowser
- HoldBrowser
- MultiBrowser
- FileBrowser
- Miscelaneous widgets
- Spinner
- Clock (Round and Square)
- Chart (several chart types are available)
- Progress (progress bar)
- Tooltip
- Table widgets
- Table
- TableRow
- Trees
- Tree
- TreeItem
- Drawing primitives
- Basics
- User input
- Client-side web todo app
- Create a media player using the vlc crate
- Custom dialogs
- Add drag and drop to the editor example
- Drawing things with fltk
- Working with images
More videos in the playlist here.