pywebview窗口移动解决方案

pywebview 无边框窗口移动解决方案

问题

pywebview 设置 frameless=True 后,窗口无边框无法移动。

解决方案

1. Python 后端(main.py

python 复制代码
import webview

class Api:
    """API 类,供前端调用"""
    
    def __init__(self):
        self._window = None  # ⚠️ 必须使用私有属性(下划线开头),避免 COM 错误
    
    def set_window(self, window):
        self._window = window
    
    def close_window(self):
        """关闭窗口"""
        if self._window:
            self._window.destroy()
    
    def minimize_window(self):
        """最小化窗口"""
        if self._window:
            self._window.minimize()

# 创建 API 实例
api = Api()
window = webview.create_window(
    title='窗口标题',
    url='./index.html',
    frameless=True,
    js_api=api  # 传入 API 对象
)
api.set_window(window)
webview.start()

2. HTML 前端

2.1 标题栏 HTML
html 复制代码
<div class="titlebar">
    <div class="titlebar-drag-region" id="titlebar-drag">
        <span class="titlebar-title">窗口标题</span>
    </div>
    <div class="titlebar-buttons">
        <div class="titlebar-btn minimize" onclick="minimizeWindow()">最小化</div>
        <div class="titlebar-btn close" onclick="closeWindow()">关闭</div>
    </div>
</div>
2.2 拖拽功能 JavaScript
javascript 复制代码
let initialX = 0;
let initialY = 0;

function onMouseMove(ev) {
    let x = ev.screenX - initialX;
    let y = ev.screenY - initialY;
    
    if (window.pywebview && typeof window.pywebview._jsApiCallback === 'function') {
        window.pywebview._jsApiCallback('pywebviewMoveWindow', [x, y], 'move');
    }
}

function onMouseUp() {
    window.removeEventListener('mousemove', onMouseMove);
    window.removeEventListener('mouseup', onMouseUp);
}

function onMouseDown(ev) {
    initialX = ev.clientX;
    initialY = ev.clientY;
    window.addEventListener('mouseup', onMouseUp);
    window.addEventListener('mousemove', onMouseMove);
}

// 关闭窗口
function closeWindow() {
    if (window.pywebview && window.pywebview.api) {
        window.pywebview.api.close_window();
    }
}

// 最小化窗口
function minimizeWindow() {
    if (window.pywebview && window.pywebview.api) {
        window.pywebview.api.minimize_window();
    }
}

// 初始化拖拽功能(延迟确保 pywebview API 就绪)
window.onload = function() {
    setTimeout(() => {
        const dragRegion = document.getElementById('titlebar-drag');
        if (dragRegion) {
            dragRegion.addEventListener('mousedown', onMouseDown);
        }
    }, 100);
};
2.3 标题栏样式(可选)
css 复制代码
.titlebar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 40px;
    background: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: space-between;
    align-items: center;
    user-select: none;
    z-index: 1000;
}

.titlebar-drag-region {
    flex: 1;
    height: 100%;
    cursor: move;
}

.titlebar-buttons {
    display: flex;
    gap: 10px;
    padding-right: 10px;
}

.titlebar-btn {
    padding: 5px 15px;
    cursor: pointer;
}

核心原理

  1. 拖拽原理 :监听鼠标按下位置(相对坐标),计算鼠标移动后的屏幕位置(绝对坐标),调用 pywebview 内部 API pywebviewMoveWindow 移动窗口
  2. API 通信 :通过 js_api 参数将 Python 类暴露给前端 JavaScript
  3. 延迟初始化 :使用 setTimeout 确保 pywebview API 准备就绪后再绑定事件

注意事项

⚠️ 关键 :API 类中的 window 属性必须使用私有属性(_window),否则会触发 Windows COM 组件错误:

arduino 复制代码
System.InvalidCastException: 无法将类型为"System.__ComObject"的 COM 对象强制转换为接口类型"Accessibility.IAccessible"

正确self._window = None

错误self.window = None

相关推荐
程序员小远1 小时前
接口测试之文件上传
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
江华森2 小时前
Python 实现高德地图找房(三):地图可视化与高德 JS API
开发语言·javascript·python
曲幽2 小时前
Anki插件开发必知必会:钩子函数与右键菜单定制
python·fastapi·anki·menu·browser·addons
技术工小李2 小时前
现场评分系统|景泰2026“农创客”杯大赛实战应用宣传
python
nanawinona3 小时前
2026年AI量化学习,交易认知和技术实现要一起走
人工智能·python
Csvn4 小时前
Python 开发技巧 · 生成器(Generator)进阶 —— 从 yield 到 yield from,写出省内存的生产者-消费者模式
后端·python
GEO_ai_zhijian4 小时前
口碑好的工业GEO优秀企业
python·搜索引擎
mikejahn4 小时前
解析ISO网站单个标准的静态网址
python
Java面试题总结5 小时前
Python 开发技巧 · 高级装饰器 —— 从基础到工业级实战
开发语言·python
AC赳赳老秦5 小时前
传感器数据自动汇总:OpenClaw 采集多类传感器数据、清洗入库、生成趋势分析
java·人工智能·python·自动化·github·php·openclaw