view就是widget

一、setWindowFlags 常用值(对系统窗口管理器说话

| 标志 | 作用 |
| ————————– | ——————————– |
| Qt::FramelessWindowHint | 去掉系统标题栏/边框 |
| Qt::WindowStaysOnTopHint | 本应用内最上层 |
| Qt::Tool | 小工具板(紧凑标题、不进 Cmd+) | | Qt::Window | 普通独立窗口(默认就有) | | Qt::Popup | 弹出层(点击外部自动消失) | | Qt::Dialog` | 对话框样式(仅关闭按钮) |

用法:按位或

view.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint)

二、setAttribute 常用值(对 Qt 自身行为说话

属性 作用
WA_TranslucentBackground 允许背景透明(你自己画 rgba)
WA_DeleteOnClose 关闭时自动 delete
WA_ShowWithoutActivating 弹出但不抢焦点(适合浮层提示)
WA_NoSystemBackground 不擦除背景(省一次 fillRect)
WA_AlwaysShowToolTips 父窗未激活也显示 tooltip
WA_Hover 强制产生 hoverMoveEvent(无此则只有 enter/leave)
WA_NoMousePropagation 不接受焦点

用法:单属性开关

view.setAttribute(Qt.WA_TranslucentBackground, True)

三、view 的「拖动/缩放/手势」设置 —— 都不是虚函数,只是普通接口

功能 接口(非虚函数) 说明
滚轮缩放 view.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) 锚点
居中缩放 view.setResizeAnchor(...) 窗口resize时锚点
抗锯齿 view.setRenderHint(QPainter.Antialiasing) 普通设置
拖拽模式 view.setDragMode(QGraphicsView.ScrollHandDrag) 手型拖画布
手势 view.grabGesture(Qt.PinchGesture) 注册即可收 gestureEvent
滚动条 view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 关掉原生滚动条
对齐网格 view.setAlignment(Qt.AlignLeft | Qt.AlignTop) 视图对齐方式

QGraphicsView 就是 Qt 的“输入中枢”——所有鼠标、滚轮、键盘、手势、触摸、拖拽、快捷键、缩放、平移都能通过它捕获


一、鼠标 & 滚轮(最常用)

功能 相关接口/设置 典型一行代码
左键点击拾取 重载 mousePressEvent it = self.itemAt(e.pos())
中键拖拽平移 setDragMode(ScrollHandDrag) 一行设置,自带手型
滚轮缩放 重载 wheelEvent + scale() self.scale(1.15, 1.15)
鼠标样式 setCursor(Qt::OpenHand) 实时变手型
拾取精度 setViewportUpdate(MinimalUpdate) 减少闪烁

二、键盘 & 快捷键

功能 相关接口/设置 典型一行代码
方向键移动选中项 重载 keyPressEvent if e.key()==Qt.Key_Left: item.moveBy(-10,0)
全局快捷键 QAction + QKeySequence action = QAction("Del", self); action.setShortcut(QKeySequence.Delete)
视图级热键 QShortcut(self) QShortcut(QKeySequence("Ctrl+="), self, self.zoomIn)
焦点策略 setFocusPolicy(Qt.StrongFocus) 让 View 能收键盘事件

三、手势 & 多点触控(macOS trackpad / Win 触控)

功能 相关接口/设置 典型一行代码
两指捏合缩放 grabGesture(Qt.PinchGesture) QPinchGesture
两指滑动平移 grabGesture(Qt.PanGesture) QPanGesture
兜底总入口 重载 event() if e.type()==QEvent.Gesture: ...

四、拖拽(文件拖进来生成节点)

功能 相关接口/设置 典型一行代码
接收文件拖放 setAcceptDrops(True) View 级
开始拖拽 QDrag + mimeData Item 里 mousePressEvent 启动
拖拽进入 重载 dragEnterEvent 判断 mimeData().hasUrls()
放下 重载 dropEvent pos = event.scenePos()

五、缩放/旋转/对齐(非虚函数,纯设置)

功能 相关接口/设置 典型一行代码
以光标为中心缩放 setTransformationAnchor(AnchorUnderMouse) 单手型缩放
平滑缩放 setRenderHint(Antialiasing) 边缘不锯齿
旋转 rotate(angle) / setTransform view.rotate(15)
对齐网格 setAlignment(Qt.AlignLeft | Qt.AlignTop) 视图左上角对齐
最大性能 setViewportUpdate(MinimalUpdate) 只重绘变化矩形

六、触摸 & 平板笔

功能 相关接口/设置 典型一行代码
多点触控 grabGesture(Qt.TapGesture | Qt.PanGesture | Qt.PinchGesture) 统一收 QGesture
压感/倾斜 重载 tabletEvent(QTabletEvent) pressure/rotation
兜底总入口 重载 event() 先拦截 QEvent::TouchUpdate

七、事件过滤 & 全局钩子

功能 相关接口/设置 典型一行代码
全局事件过滤器 installEventFilter(self) 可拦截所有事件
Scene 级过滤器 installSceneEventFilter(item) 只过滤指定 Item 的事件
底层兜底 重载 event(QEvent) 任何新事件都能先拦截

八、性能 & 调试开关

功能 相关接口/设置 典型一行代码
显示 FPS setViewport(new QOpenGLWidget) + QElapsedTimer 60 FPS 实测
只更新变化区 setViewportUpdate(MinimalUpdate) 大场景不闪
打印场景 render(QPainter, targetRect, sourceRect) 一键导出 PNG/PDF

处理分类

  • 手动处理事件(大部分情况并不需要), 重载某个虚函数xxxEvent
  • 缩放平移 → setXxx + 非虚函数
  • 手势触摸 → grabGesture + event() 兜底
  • 性能 → OpenGL + MinimalUpdate

关于虚函数和设置

  • setXxx / grabXxx / scale / rotate → 普通接口,非虚函数,按需开关
  • xxxEvent → 虚函数,以 Event 结尾,必须重载才能收事件

所以:

  • 想「打开平滑缩放」→ 调 setRenderHint()普通接口
  • 想「自己处理滚轮」→ 重载 wheelEvent()虚函数

用普通接口 vs 必须虚函数」的**红绿灯表


🟢 普通接口就够(不调也能跑

功能 接口/设置 是否必须自己写代码
无父全局菜单 + 快捷键 QAction::setShortcut 零代码,菜单栏挂 action 即可
画布整体拖动 view.setDragMode(ScrollHandDrag) 一行设置,自带手型
双指滑动平移 view.grabGesture(Qt.PanGesture) 一行注册,收 QPanGesture 即可
双指捏合缩放 view.grabGesture(Qt.PinchGesture) 一行注册,收 QPinchGesture 即可
滚轮缩放 view.wheelEventscale() 可选重载,默认也能缩放
右键菜单(一致的) # 1. 让视图能发右键信号
self.setContextMenuPolicy(Qt.CustomContextMenu)
# 2. 连接信号 → 普通槽函数(非虚函数)
self.customContextMenuRequested.connect(菜单函数下面是2行核心代码)
menu = QMenu()
menu.exec(self.mapToGlobal(pos))
 

🔴 必须虚函数(你不写,Qt 不会帮你

功能 虚函数 原因
空白 vs Item 不同右键菜单 Scene::contextMenuEvent 系统只分发一次,你必须 hitTest 后决定给谁弹
Item 键盘+鼠标组合 Item::keyPressEvent + Item::mousePressEvent Item 才收得到,Scene/View 不会自动转发
手势兜底/新事件 View::event() 只有这里能先拦截未公开事件

🟡 可选虚函数(普通接口也能跑,但重载更精细

功能 普通接口 重载好处
滚轮缩放 wheelEventscale() 可控制倍率、锚点、动画
画布边界自动扩大 scene.setSceneRect 可动态计算,不用每帧调

结论

「全局菜单、整体拖动、双指滑动/捏合、滚轮缩放」普通接口一行搞定
「空白/Item 不同菜单、Item 组合键、新手势兜底」必须写虚函数

  • 普通接口负责「整体行为
  • 虚函数只负责「命中测试 + Item 私有交互