当前位置: 首页 > news >正文

QTableView鼠标双击先触发单击信号

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、QAbstractItemView
  • 二、解决问题
  • 总结


前言

最近开发一个项目遇到了一个问题,QTableView同时绑定doubleClicked和clicked信号,结果发现鼠标左键双击必然先触发一次单击信号,鼠标右键双击就不会触发单击信号。我的需求是同时绑定单击和双击信号,结果某些场景下同时触发信号,我该怎么办呢?

这个问题我终于在源代码里找到了答案。


一、QAbstractItemView

QTableView继承这个类,它的单击和双击信号就是从这个类触发的。

单击:鼠标抬起事件

void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
{Q_D(QAbstractItemView);QPoint pos = event->pos();QPersistentModelIndex index = indexAt(pos);if (state() == EditingState) {if (d->isIndexValid(index)&& d->isIndexEnabled(index)&& d->sendDelegateEvent(index, event))update(index);return;}bool click = (index == d->pressedIndex && index.isValid());bool selectedClicked = click && (event->button() == Qt::LeftButton) && d->pressedAlreadySelected;EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers);const bool edited = click ? edit(index, trigger, event) : false;d->ctrlDragSelectionFlag = QItemSelectionModel::NoUpdate;if (d->selectionModel && d->noSelectionOnMousePress) {d->noSelectionOnMousePress = false;d->selectionModel->select(index, selectionCommand(index, event));}setState(NoState);if (click) {if (event->button() == Qt::LeftButton)emit clicked(index);if (edited)return;QStyleOptionViewItem option = d->viewOptionsV1();if (d->pressedAlreadySelected)option.state |= QStyle::State_Selected;if ((d->model->flags(index) & Qt::ItemIsEnabled)&& style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, &option, this))emit activated(index);}
}

重点是下面这几句:

    if (click) {if (event->button() == Qt::LeftButton)emit clicked(index);

先不用管它做了什么判断,我简略说下:只有index有效才会触发单击信号;换言之,index无效不会触发这个信号。而且必须是鼠标左键点击才行!

可以明显看到,clicked总是在doubleClicked之前触发。也就是第一次鼠标抬起的时候触发,那个时候还没触发双击信号。

双击信号:双击事件触发时

void QAbstractItemView::mouseDoubleClickEvent(QMouseEvent *event)
{Q_D(QAbstractItemView);QModelIndex index = indexAt(event->pos());if (!index.isValid()|| !d->isIndexEnabled(index)|| (d->pressedIndex != index)) {QMouseEvent me(QEvent::MouseButtonPress,event->localPos(), event->windowPos(), event->screenPos(),event->button(), event->buttons(), event->modifiers(), event->source());mousePressEvent(&me);return;}// signal handlers may change the modelQPersistentModelIndex persistent = index;emit doubleClicked(persistent);if ((event->button() == Qt::LeftButton) && !edit(persistent, DoubleClicked, event)&& !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, nullptr, this))emit activated(persistent);d->pressedIndex = QModelIndex();
}

重点是下面这几句:

emit doubleClicked(persistent);

鼠标双击事件由底层系统触发,鼠标左键和右键均可以触发。

由此,我们看到当你用鼠标左键单击的时候总会发送一个单击信号+一个双击信号,而且单击信号一定在双击信号前面。

二、解决问题

其实没有什么问题需要解决,本来就可以同时绑定单击和双击信号。严格来说只要你的单击信号和双击信号没有重叠的业务逻辑,你就可以无视这个问题。但是,有时候偏偏出现我只要双击不要单击的场景怎么办呢?

办法还是有的,先看下面的函数:

int doubleClickInterval = QApplication::doubleClickInterval();  // 单位:毫秒

其实是有双击触发间隔的,意思就是只要两次单击在这个时间间隔内就可以触发双击信号,要不然就触发两次单击。这个值在Windows上默认是500ms,在Mac/Linux上默认是400ms,我们暂时不考虑更改这个值,但这个值对我们有用。

解决思路也不难,触发单击的时候等待这个时间间隔,如果间隔内触发了双击就拦截单击信号,否则放行。

// 推荐做法:使用系统间隔
connect(&m_timer, &QTimer::timeout, this, &MyClass::handleSingleClick);
m_timer.setSingleShot(true);
m_timer.start(QApplication::doubleClickInterval());  // 关键点

总结

1、如果你遇到了非解决不可的场景可以考虑我的方法,如果你对这个场景无所谓就无需关心。


文章转载自:
http://carritch.alwpc.cn
http://casita.alwpc.cn
http://bet.alwpc.cn
http://accelerogram.alwpc.cn
http://analogy.alwpc.cn
http://ampersand.alwpc.cn
http://caducous.alwpc.cn
http://ashen.alwpc.cn
http://antiquer.alwpc.cn
http://addressograph.alwpc.cn
http://anacreon.alwpc.cn
http://admonish.alwpc.cn
http://aristo.alwpc.cn
http://cellarway.alwpc.cn
http://becky.alwpc.cn
http://androdioecism.alwpc.cn
http://anvil.alwpc.cn
http://aphlogistic.alwpc.cn
http://cherenkov.alwpc.cn
http://agrometeorological.alwpc.cn
http://allegorical.alwpc.cn
http://capybara.alwpc.cn
http://absorbed.alwpc.cn
http://ardency.alwpc.cn
http://bandhnu.alwpc.cn
http://ambiplasma.alwpc.cn
http://burmese.alwpc.cn
http://cheerfulness.alwpc.cn
http://attached.alwpc.cn
http://apostrophize.alwpc.cn
http://www.dtcms.com/a/281675.html

相关文章:

  • Vue 常用的 ESLint 规则集
  • resources为什么是类的根目录
  • Linux 基本操作与服务器部署
  • 【高等数学】第三章 微分中值定理与导数的应用——第一节 不定积分的概念与性质
  • Android 图片压缩
  • 21.映射字典的值
  • 【强化学习】Reinforcement Learning基础概述
  • 如何进行 Docker 数据目录迁移
  • 三轴云台之深度学习算法篇
  • vscode配置运行完整C代码项目
  • QGIS新手教程9:字段计算器进阶用法与批量处理技巧
  • onecode 3.0 微内核引擎 基础注解驱动的速查手册(服务治理及通讯)
  • Altium Designer(AD)25软件下载及安装教程(7.9)
  • Axios方法完成图书管理页面完整版
  • Redis Desktop Manager(RDM)下载与安装使用教程
  • JavaScript中关于环境对象的拓展
  • 【Qt】 设计模式
  • Docker 镜像推送至 Coding 制品仓库超时问题排查与解决
  • 业务分析业务架构视角
  • 软件测试面试经历分享?
  • 在 SymPy 中精确提取三角函数系数的深度分析
  • LLM面试题目 3
  • 项目进度与预算脱节,如何进行同步管理
  • Linux部署Redis
  • 46. 携带研究材料(01背包二维数组)
  • Java程序员学从0学AI(五)
  • 发票查验接口的计费规则-核验成功返回参数
  • SpringBoot集成RocketMQ的两种方式
  • WGAS+WGCNA分析文章套路
  • LeetCode Hot100 【1.两数之和、2.两数相加、3.无重复字符的最长子串】