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_()
关键修改点
- 移除全局事件过滤器,改为重写主窗口的
mouseMoveEvent和mousePressEvent,直接在窗口层面处理事件,优先级高于子控件。 - 新增
_get_resize_edges方法统一计算缩放边缘,简化代码逻辑。 - 在鼠标移动事件中,仅当鼠标不在缩放区域时,才将事件传递给OCC控件,避免光标样式被覆盖。
- 在鼠标点击事件中,仅检测到缩放边缘点击时触发系统缩放,否则将事件交给OCC处理模型交互。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

