QT中创建自定义行列可点击方格网格的最优实现方案
最优QT方案:QGraphicsScene + QGraphicsRectItem
直接给结论:用QGraphicsScene搭配QGraphicsRectItem是最优选择,完全能解决你担心的大网格点击查找性能问题,同时适配路径可视化的需求。
核心性能优化:跳过循环查找,直接坐标定位
你担心的循环查找问题根本不用发生——因为网格是规则的,只要提前记录每个单元格的宽高,鼠标点击时直接通过坐标计算得到行列索引,O(1)时间就能找到目标单元格:
// 假设每个单元格宽cellWidth,高cellHeight QPointF scenePos = view->mapToScene(event->pos()); int col = static_cast<int>(scenePos.x() / cellWidth); int row = static_cast<int>(scenePos.y() / cellHeight); // 从预先存储的二维数组中直接取对应Item QGraphicsRectItem* cell = grid[row][col];
把所有单元格存在二维数组(比如QVector<QVector<QGraphicsRectItem*>>)里,索引直接定位,完全不需要遍历所有元素。
QGraphicsItem的天然优势
- 点击逻辑内聚:每个QGraphicsRectItem可以重写
mousePressEvent,自己处理点击变色,不用全局捕获事件再分发,代码逻辑更清晰。 - 渲染优化:QGraphicsScene本身支持视口裁剪,只会渲染当前可见区域的单元格,哪怕是1000x1000的大网格,也不会因为渲染全部元素导致卡顿。
- 扩展性强:后续做路径可视化时,很容易给单元格添加不同状态(比如起点、终点、路径、障碍),通过修改brush或者pen就能实现,还能支持动画效果。
为什么不选QRect映射方案?
用QRect存储在映射结构里的问题很明显:
- 点击时必须遍历所有QRect判断是否包含点击点,大网格下是O(n)操作,性能直接崩盘。
- 自己需要手动处理渲染、点击事件分发,重复造轮子,代码量更大,维护成本高。
实现小技巧
- 初始化网格时,一次性创建所有QGraphicsRectItem,设置好位置、大小,并存入二维数组。
- 可以给每个Item用
setData()绑定行列信息,点击时直接读取,避免重复计算坐标。 - 调整QGraphicsView的更新模式为
QGraphicsView::MinimalViewportUpdate,减少不必要的渲染开销。
内容的提问来源于stack exchange,提问作者Teemu Harju
相关产品推荐
相关产品推荐

