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

相关推荐
m0_602857766 小时前
如何提升SQL存储过程逻辑复用_封装通用存储过程函数
jvm·数据库·python
傻啦嘿哟7 小时前
如何在 Python 中使用 colorama 库来给输出添加颜色
开发语言·python
forEverPlume7 小时前
mysql如何实现高可用集群架构_基于MHA环境搭建与部署
jvm·数据库·python
方安乐12 小时前
python之向量、向量和、向量点积
开发语言·python·numpy
zh15702314 小时前
JavaScript中WorkerThreads解决服务端计算瓶颈
jvm·数据库·python
蜡台15 小时前
Python包管理工具pip完全指南-----2
linux·windows·python
Mr.朱鹏15 小时前
【Python 进阶 | 第四篇】Psycopg3 + Flask 实现 PostgreSQL CRUD 全流程:从连接池到RESTful接口
python·postgresql·flask·virtualenv·fastapi·pip·tornado
2401_8714928515 小时前
Vue.js监听器watch利用回调函数处理级联下拉框数据联动
jvm·数据库·python
FreakStudio15 小时前
亲测可用!可本地部署的 MicroPython 开源仿真器
python·单片机·嵌入式·面向对象·并行计算·电子diy·电子计算机
SilentSamsara16 小时前
Python 环境搭建完整指南:从下载安装到运行第一个程序
开发语言·python