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

windowHandle().startSystemResize(edges)与PythonOCC窗口缩放异常求助

问题与解决方案:PySide2+PythonOCC自定义窗口缩放异常修复

问题描述

使用PySide2结合PythonOCC开发程序时,通过windowHandle().startSystemResize(edges)实现的自定义窗口缩放功能异常:有时无法触发缩放,有时无法调整到正确尺寸。移除PythonOCC相关代码后,功能恢复正常。

原因分析

PythonOCC的qtViewer3d是基于OpenGL的3D视图控件,会主动捕获鼠标事件用于模型交互(旋转、平移等),导致主窗口的事件过滤器无法稳定捕获窗口边缘的鼠标操作,进而干扰startSystemResize的触发与执行。

解决方案

放弃全局事件过滤器,改为直接重写主窗口的鼠标事件处理方法,优先处理窗口缩放逻辑,仅在非缩放区域将事件传递给OCC控件。

修改后的代码

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *

from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox
from OCC.Display.backend import load_backend, get_loaded_backend
load_backend("qt-pyside2")
import OCC.Display.qtDisplay as qtDisplay

import sys

class MainWindow(QMainWindow):
    BORDER_WIDTH = 5
    def __init__(self):
        super().__init__()

        self.main_widget = QWidget()
        self.main_layout = QVBoxLayout()
        self.main_widget.setLayout(self.main_layout)
        self.setCentralWidget(self.main_widget)

        self.canvas = qtDisplay.qtViewer3d(self)
        self.canvas.InitDriver()
        self.main_layout.addWidget(self.canvas)

        self.setWindowFlags(Qt.CustomizeWindowHint)
        self._isResizeEnabled = True
        
        # 添加测试立方体
        box = BRepPrimAPI_MakeBox(10, 10, 10).Shape()
        self.canvas.DisplayShape(box, update=True)

    def _get_resize_edges(self, pos):
        edges = Qt.Edge(0)
        if pos.x() < self.BORDER_WIDTH:
            edges |= Qt.LeftEdge
        if pos.x() >= self.width() - self.BORDER_WIDTH:
            edges |= Qt.RightEdge
        if pos.y() < self.BORDER_WIDTH:
            edges |= Qt.TopEdge
        if pos.y() >= self.height() - self.BORDER_WIDTH:
            edges |= Qt.BottomEdge
        return edges

    def mouseMoveEvent(self, event):
        if not self._isResizeEnabled or self.windowState() != Qt.WindowNoState:
            super().mouseMoveEvent(event)
            return
        
        pos = event.pos()
        edges = self._get_resize_edges(pos)
        # 更新光标样式
        if edges in (Qt.LeftEdge | Qt.TopEdge, Qt.RightEdge | Qt.BottomEdge):
            self.setCursor(Qt.SizeFDiagCursor)
        elif edges in (Qt.RightEdge | Qt.TopEdge, Qt.LeftEdge | Qt.BottomEdge):
            self.setCursor(Qt.SizeBDiagCursor)
        elif edges in (Qt.TopEdge, Qt.BottomEdge):
            self.setCursor(Qt.SizeVerCursor)
        elif edges in (Qt.LeftEdge, Qt.RightEdge):
            self.setCursor(Qt.SizeHorCursor)
        else:
            self.setCursor(Qt.ArrowCursor)
            super().mouseMoveEvent(event)

    def mousePressEvent(self, event):
        if not self._isResizeEnabled:
            super().mousePressEvent(event)
            return
        
        pos = event.pos()
        edges = self._get_resize_edges(pos)
        if edges:
            self.windowHandle().startSystemResize(edges)
        else:
            super().mousePressEvent(event)

app = QApplication(sys.argv)
win = MainWindow()
win.show()
app.exec_()

关键修改点

  1. 移除全局事件过滤器,改为重写主窗口的mouseMoveEvent和mousePressEvent,直接在窗口层面处理事件,优先级高于子控件。
  2. 新增_get_resize_edges方法统一计算缩放边缘,简化代码逻辑。
  3. 在鼠标移动事件中,仅当鼠标不在缩放区域时,才将事件传递给OCC控件,避免光标样式被覆盖。
  4. 在鼠标点击事件中,仅检测到缩放边缘点击时触发系统缩放,否则将事件交给OCC处理模型交互。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:29:59