如何在egui中通过鼠标拖拽移动窗口?
实现egui窗口的拖拽移动功能
要实现点击窗口任意区域并拖拽移动窗口的功能,你需要添加拖拽状态管理,并通过egui的指针输入和窗口API来更新位置。以下是修改后的完整代码:
fn main() { let nativeoption = eframe::NativeOptions { always_on_top: false, maximized: false, decorated: true, fullscreen: false, drag_and_drop_support: true, initial_window_size: Some(egui::Vec2::new(300.0, 300.0)), min_window_size: None, max_window_size: None, resizable: true, ..Default::default() }; eframe::run_native( "my egui app", nativeoption, Box::new(|cc| Box::new(MyEguiApp::new(cc))), ) .expect("Failed to run native app"); } #[derive(Default)] struct MyEguiApp { name: String, is_dragging: bool, drag_start_pos: egui::Pos2, window_start_pos: egui::Pos2, } impl MyEguiApp { fn new(_cc: &eframe::CreationContext<'_>) -> Self { Self { name: String::new(), ..Default::default() } } } impl eframe::App for MyEguiApp { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { let pointer = ctx.input().pointer; // 处理拖拽逻辑 if pointer.button_down(egui::PointerButton::Primary) { if !self.is_dragging { // 初始化拖拽状态 self.is_dragging = true; self.drag_start_pos = pointer.hover_pos().unwrap_or_default(); self.window_start_pos = frame.info().window_info.position; } else { // 计算鼠标偏移量,更新窗口位置 let current_pos = pointer.hover_pos().unwrap_or_default(); let delta = current_pos - self.drag_start_pos; let new_window_pos = self.window_start_pos + delta; frame.set_window_pos(new_window_pos); } } else { // 释放鼠标,结束拖拽 self.is_dragging = false; } // 原有UI渲染逻辑 egui::CentralPanel::default().show(ctx, |ui| { ui.heading("hello welcome to egui"); ui.separator(); ui.horizontal(|ui| { ui.label("Enter your name"); let _res = ui.text_edit_singleline(&mut self.name); }); ui.label(format!("my name is {}", &self.name)); }); } }
关键修改说明:
添加拖拽状态变量:
is_dragging:标记当前是否处于拖拽状态drag_start_pos:记录鼠标左键按下时的屏幕位置window_start_pos:记录拖拽开始时的窗口初始位置
拖拽逻辑处理:
- 当鼠标左键按下时,若未开始拖拽则初始化状态;若已在拖拽中,计算鼠标移动的偏移量,调用
frame.set_window_pos()更新窗口位置 - 鼠标左键释放时,重置拖拽状态
- 当鼠标左键按下时,若未开始拖拽则初始化状态;若已在拖拽中,计算鼠标移动的偏移量,调用
修正原代码错误:
- 修复了
MyEguiApp::new()中错误的返回逻辑(原代码创建实例后未使用,直接返回默认值) - 简化了
initial_window_size的写法(Some(...)替代Option::from(...))
- 修复了
额外说明:
- 如果你保留
decorated: true,窗口默认的标题栏仍可拖拽,此实现补充了窗口任意区域的拖拽功能 - 若只想通过自定义逻辑拖拽窗口,可将
decorated设为false,隐藏系统标题栏
内容的提问来源于stack exchange,提问作者user20957580
相关产品推荐
相关产品推荐

