1 个不稳定版本
0.29.4 | 2024年1月12日 |
---|
#946 in GUI
2,014 每月下载量
在 6 个包 (2 直接) 中使用
2MB
42K SLoC
你可能正在寻找 真正的 winit 包。
Floem 依赖于尚未上传到上游的 winit 变更。为了使 Floem 可在 crates.io 上发布,所有依赖项都必须在那里发布 - 因此这是一个非官方包。
lib.rs
:
Winit 是一个跨平台的窗口创建和事件循环管理库。
构建窗口
在您能够构建一个 Window
之前,您首先需要构建一个 EventLoop
。这可以通过 EventLoop::new()
函数完成。
use winit::event_loop::EventLoop;
let event_loop = EventLoop::new().unwrap();
完成此操作后,有两种方法可以创建一个 Window
第一种方法是最简单的,将为所有内容提供默认值。第二种方法允许您通过修改创建Window
之前WindowBuilder
对象的字段来自定义Window
的外观和行为。
事件处理
一旦创建了一个Window
,它将生成不同的事件。当发生某些输入事件时,例如光标在窗口上移动或在窗口聚焦时按键按下,Window
对象可以生成WindowEvent
。设备可以生成包含未过滤事件数据的DeviceEvent
,这些数据不是特定于某个窗口的。一些用户活动,如鼠标移动,可以同时生成一个WindowEvent
和一个DeviceEvent
。如果需要,您还可以创建并处理自己的自定义Event::UserEvent
。
您可以通过调用EventLoop::run()
来检索事件。此函数将为使用该特定EventLoop
创建的每个Window
分发事件,并运行直到使用exit()
,此时将发出Event::LoopExiting
。
由于在某些平台(例如,Web、iOS)上无法正确实现,并且在大多数其他平台上表现不佳,Winit不再使用基于EventLoop::poll_events() -> impl Iterator<Event>
的事件循环模型。然而,可以通过[^1]在一定程度上重新实现此模型。请参阅该方法的文档以获取更多关于为什么不鼓励使用此模型的原因,而不仅仅是因为兼容性的原因。
use winit::{
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
let event_loop = EventLoop::new().unwrap();
let window = WindowBuilder::new().build(&event_loop).unwrap();
// ControlFlow::Poll continuously runs the event loop, even if the OS hasn't
// dispatched any events. This is ideal for games and similar applications.
event_loop.set_control_flow(ControlFlow::Poll);
// ControlFlow::Wait pauses the event loop if no events are available to process.
// This is ideal for non-game applications that only update in response to user
// input, and uses significantly less power/CPU time than ControlFlow::Poll.
event_loop.set_control_flow(ControlFlow::Wait);
event_loop.run(move |event, elwt| {
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
println!("The close button was pressed; stopping");
elwt.exit();
},
Event::AboutToWait => {
// Application update code.
// Queue a RedrawRequested event.
//
// You only need to call this if you've determined that you need to redraw in
// applications which do not always need to. Applications that redraw continuously
// can render here instead.
window.request_redraw();
},
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
// Redraw the application.
//
// It's preferable for applications that do not render continuously to render in
// this event rather than in AboutToWait, since rendering in here allows
// the program to gracefully handle redraws requested by the OS.
},
_ => ()
}
});
WindowEvent
有一个WindowId
成员。在多窗口环境中,它应该与Window::id()
返回的值进行比较,以确定哪个Window
派发了事件。
在窗口上绘图
Winit不直接提供在Window
上绘制的方法。但是,它允许您检索窗口的原始句柄和显示(请参阅platform
模块和/或raw_window_handle
和raw_display_handle
方法),这反过来又允许您创建一个OpenGL/Vulkan/DirectX/Metal等.上下文,可用于渲染图形。
请注意,如果应用程序在桌面合成器准备好向用户显示窗口之前没有向窗口渲染任何内容,许多平台将在窗口的客户区域显示垃圾数据。如果您注意到这种情况发生,您应该创建一个将 visible
设置为 false
的窗口,并且只有当您准备好向其渲染时才明确使其可见。
[^1]: EventLoopExtPumpEvents::pump_events()
仅在 Windows、macOS、Android、X11 和 Wayland 上可用。
依赖项
~0.3–21MB
~333K SLoC