Hello World!


Okay, that's not "hello world". Lets do something slightly more fun: a push button. Source.

use kas::widget::{TextButton, Window};

fn main() -> Result<(), kas_wgpu::Error> {

    let content = TextButton::new("Push me");
    let window = Window::new("Hello", content);

    let theme = kas_theme::ShadedTheme::new();
cargo run --example hello

Hopefully that is clear enough? Let me explain anyway:

  • our main function may fail with the kas_wgpu::Error type; Toolkit::new and Toolkit::with can fail (the ? "try" operator)
  • we initialise a logger, env_logger (optional, but lets us get useful messages; try setting the environment variable RUST_LOG=kas=info or trace before running the example)
  • we construct a TextButton and a Window around that
  • we use the ShadedTheme (with default colours)
  • we initialise the toolkit with our theme, add our window, and run it

Note that Toolkit::run does not return. It is in fact a wrapper around winit::event_loop::EventLoop::run, which does not return. By default, the program will exit after all windows have closed.

Also note that we only import our widgets into the module (use kas::widget::{..}), but don't import anything from the other crates: we use env_logger::init, kas_theme::ShadedTheme and kas_wgpu::Toolkit directly since we don't need any other items from these crates.

Event handling

You may have noticed that the button used above doesn't do anything. Lets fix that.

If you look at the TextButton docs, you'll notice that it has an on_push method, allowing a closure to be set as a "push" event handler. This closure must have the following type:

F: Fn(&mut Manager<'_>) -> Option<M> + 'static

In other words, it takes a reference to the Manager and returns an optional message of type M. We'll come back to messages later; for now we can just return None — well, we could if type inference worked, but since None could be an option of any type we have to specify that we want VoidMsg:

fn main() {
let content = TextButton::new("Push me").on_push::<VoidMsg, _>(|_| {

But let's not just print to the command-line: lets use the Manager to open a message dialog!

fn main() {
let content = TextButton::new("&Push me").on_push::<VoidMsg, _>(|mgr| {
    let mbox = MessageBox::new("Message", "You pushed the button.");

One final note: did you see we put an ampersand in "&Push me"? Try holding Alt and pressing P when you run the example:

cargo run --example hello-handler