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

相关推荐
CodeCraft Studio9 小时前
国产化Word处理组件Spire.DOC教程:使用Python将文件自动化批量附加到 Word文档
python·自动化·word·spire.doc·文档自动化·word文档中添加附件·文档批量处理
Mryan20059 小时前
基于 Nao 机器人的摄像头和声呐结合寻路方式
python·机器人·nao 机器人·naoqi
Salt_07289 小时前
DAY 37 MLP 神经网络的训练
人工智能·python·深度学习·神经网络·机器学习
东方佑9 小时前
使用Python实现Word文档与JSON格式双向转换:完整教程与代码解析
python·json·word
三斗米9 小时前
mac系统查看所有安装的Python版本
python
信看9 小时前
树莓派CAN(FD) 测试
开发语言·python
yaoh.wang10 小时前
力扣(LeetCode) 67: 二进制求和 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
电饭叔10 小时前
自定义重载运算符--《python语言程序设计》2018版--第8章20题使用Rational类求和数列之一
开发语言·python
Evan芙10 小时前
基于Nginx和Python的动态站点安装配置
数据库·python·nginx