绘制事物 Drawing things
fltk-rs
在draw mod
中提供了可以绘制自定义元素的函数。但是只有当绘制函数的调用是在特定的上下文中时,例如在WidgetBase::draw()
方法中或在Offscreen
上下文中,绘制才有效:
在组件上绘制
注意,我们在组件的draw方法中使用了draw
:
use fltk::{enums, prelude::*, *}; fn main() { let a = app::App::default(); let mut win = window::Window::default().with_size(400, 300); win.end(); win.show(); win.draw(|w| { use draw::*; // 白色窗口 draw_rect_fill(0, 0, w.w(), w.h(), enums::Color::White); // 画一个蓝色的圆 set_draw_color(enums::Color::Blue.inactive()); draw_pie(w.w() / 2 - 50, w.h() / 2 - 50, 100, 100, 0.0, 360.0); // 让文字旋转一定角度 set_draw_color(enums::Color::Red); set_font(enums::Font::Courier, 16); draw_text_angled(45, "Hello World", w.w() / 2, w.h() / 2); }); a.run().unwrap(); }
我们用了整个窗口当绘制的画板,任何其他组件理论上都可以进行绘制。还有许多其他函数可以让你绘制直线、矩形、弧线、饼、循环、多边形,甚至图像。
屏幕外事件的绘制
有时可能会需要通过绘制来响应一些事件,例如拖动鼠标时,在屏幕上绘制出鼠标的轨迹。在这种情况下,你可以使用draw::Offscreen
来做到这一点。我们所用组件的draw
方法只是复制屏幕外事件的内容,例如鼠标的坐标,而绘制是在组件的handle
方法中进行的。
use fltk::{ app, draw::{ draw_line, draw_point, draw_rect_fill, set_draw_color, set_line_style, LineStyle, Offscreen, }, enums::{Color, Event, FrameType}, frame::Frame, prelude::*, window::Window, }; use std::cell::RefCell; use std::rc::Rc; const WIDTH: i32 = 800; const HEIGHT: i32 = 600; fn main() { let app = app::App::default().with_scheme(app::Scheme::Gtk); let mut wind = Window::default() .with_size(WIDTH, HEIGHT) .with_label("RustyPainter"); let mut frame = Frame::default() .with_size(WIDTH - 10, HEIGHT - 10) .center_of(&wind); frame.set_color(Color::White); frame.set_frame(FrameType::DownBox); wind.end(); wind.show(); // 用白色填充 let offs = Offscreen::new(frame.width(), frame.height()).unwrap(); #[cfg(not(target_os = "macos"))] { offs.begin(); draw_rect_fill(0, 0, WIDTH - 10, HEIGHT - 10, Color::White); offs.end(); } let offs = Rc::from(RefCell::from(offs)); frame.draw({ let offs = offs.clone(); move |_| { let mut offs = offs.borrow_mut(); if offs.is_valid() { offs.rescale(); offs.copy(5, 5, WIDTH - 10, HEIGHT - 10, 0, 0); } else { offs.begin(); draw_rect_fill(0, 0, WIDTH - 10, HEIGHT - 10, Color::White); offs.copy(5, 5, WIDTH - 10, HEIGHT - 10, 0, 0); offs.end(); } } }); frame.handle({ let mut x = 0; let mut y = 0; move |f, ev| { // println!("{}", ev); // println!("coords {:?}", app::event_coords()); // println!("get mouse {:?}", app::get_mouse()); let offs = offs.borrow_mut(); match ev { Event::Push => { offs.begin(); set_draw_color(Color::Red); set_line_style(LineStyle::Solid, 3); let coords = app::event_coords(); x = coords.0; y = coords.1; draw_point(x, y); offs.end(); f.redraw(); set_line_style(LineStyle::Solid, 0); true } Event::Drag => { offs.begin(); set_draw_color(Color::Red); set_line_style(LineStyle::Solid, 3); let coords = app::event_coords(); draw_line(x, y, coords.0, coords.1); x = coords.0; y = coords.1; offs.end(); f.redraw(); set_line_style(LineStyle::Solid, 0); true } _ => false, } } }); app.run().unwrap(); }
注意,这里我们用offs.begin()
开始了OffScreen
上下文,用offs.end()
表示上下文结束。只有在上下文内,我们才能调用Offscreen
绘图函数: