You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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));
        });
    }
}

关键修改说明:

  1. 添加拖拽状态变量:

    • is_dragging:标记当前是否处于拖拽状态
    • drag_start_pos:记录鼠标左键按下时的屏幕位置
    • window_start_pos:记录拖拽开始时的窗口初始位置
  2. 拖拽逻辑处理:

    • 当鼠标左键按下时,若未开始拖拽则初始化状态;若已在拖拽中,计算鼠标移动的偏移量,调用frame.set_window_pos()更新窗口位置
    • 鼠标左键释放时,重置拖拽状态
  3. 修正原代码错误:

    • 修复了MyEguiApp::new()中错误的返回逻辑(原代码创建实例后未使用,直接返回默认值)
    • 简化了initial_window_size的写法(Some(...)替代Option::from(...))

额外说明:

  • 如果你保留decorated: true,窗口默认的标题栏仍可拖拽,此实现补充了窗口任意区域的拖拽功能
  • 若只想通过自定义逻辑拖拽窗口,可将decorated设为false,隐藏系统标题栏

内容的提问来源于stack exchange,提问作者user20957580

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 08:02:05