• 《QDebug 2022年8月》


    一、Qt Widgets 问题交流

    1.QWidget鼠标事件穿透

    对于一些透明或者半透明的QWidget,可能需要点击其下方的按钮或其他组件,但是QWidget本身是会接收这些鼠标事件的,需要一些额外的处理。下面是百度到的一些方法:

    方式A.设置setAttribute(Qt::WA_TransparentForMouseEvents, true),设置之后该QWidget对象树就不再处理鼠标事件。最大的缺点就是不仅该QWidget不响应鼠标事件,它上面的其他组件也没法响应鼠标事件了。

    方式B.setMask把底部要点击的地方抠出来,缺点是抠出来的地方就成了全透明,不适合半透明的需求:

    1. QRegion reg(ui->widget->rect());
    2. //bottom为被widget挡住的按钮
    3. auto btn_area=ui->btnBottom->geometry();
    4. btn_area.moveTo(btn_area.topLeft()-ui->widget->geometry().topLeft());
    5. reg-=QRegion(btn_area);
    6. ui->widget->setMask(reg);

    方法C. QWdidget鼠标事件处理先判断坐标点下方是否有其他组件,有则传递下去:

    1. void mouseMoveEvent(QMouseEvent *event){
    2. transMouseEvents(event);
    3. }
    4. void mousePressEvent(QMouseEvent *event){
    5. transMouseEvents(event);
    6. }
    7. void mouseReleaseEvent(QMouseEvent *event){
    8. transMouseEvents(event);
    9. }
    10. void mouseDoubleClickEvent(QMouseEvent *event){
    11. transMouseEvents(event);
    12. }
    13. void transMouseEvents(QMouseEvent *event){
    14. if (this->parentWidget()) {
    15. this->setAttribute(Qt::WA_TransparentForMouseEvents, true);
    16. QPoint pt = this->mapTo(this->parentWidget(), event->pos());
    17. QWidget *wid = this->parentWidget()->childAt(pt);
    18. if (wid) {
    19. pt = wid->mapFrom(this->parentWidget(), pt);
    20. QMouseEvent *mEvent = new QMouseEvent(event->type(), pt, event->button(), event->buttons(), event->modifiers());
    21. QApplication::postEvent(wid, mEvent);
    22. }
    23. this->setAttribute(Qt::WA_TransparentForMouseEvents, false);
    24. }
    25. }

    参考:QT 鼠标穿透 - 知乎 

    二、Qt Quick 问题交流

    1.打包命令问题

    百度搜(QML打包),找到的结果一般都是这样的:

    windeployqt 程序.exe --qmldir C:\Qt\Qt5.15.2\5.15.2\msvc2019_64\qml
    

    这些博文上,--qmldir的参数一般都是指向Qt安装目录,但是通过查看文档可知,qmldir应该指向项目源码的qml目录,以查找导入了哪些模块,qmlimport才是用来指向安装路径或者其他依赖模块路径的。

    文档:https://doc.qt.io/qt-5/windows-deployment.html 

    三、其他

    1.QAXObject在WPS环境下读取Excel的UsedRange.Value为空

    一开始测试MS Office时如下的代码可以正常的读取到UsedRange的表格内容:

    1. QAxObject *used_range = work_sheet->querySubObject("UsedRange");
    2. auto range_data = used_range->property("Value").toList();

    但是在测试WPS时,读取到的值是空的,修改为dynamicCall后就能正常读取了:

    1. QAxObject *used_range = work_sheet->querySubObject("UsedRange");
    2. auto range_data = used_range->dynamicCall("Value()").toList();

    完整的测试代码如下:

    1. void parseExcel()
    2. {
    3. const QString filepath = QFileDialog::getOpenFileName(this);
    4. if(filepath.isEmpty()){
    5. qDebug()<<"filepath is empty";
    6. return;
    7. }
    8. QSharedPointer excel{new QAxObject};
    9. //分别尝试WPS和MS Office的excel组件
    10. if(!excel->setControl("KET.Application" )){
    11. qDebug() << "open wps excel failed";
    12. if(!excel->setControl("Excel.Application")){
    13. qDebug() << "open office excel failed";
    14. return;
    15. }
    16. }
    17. qDebug()<<"excel open";
    18. auto scope = qScopeGuard([=]{
    19. qDebug()<<"excel quit";
    20. //退出时关闭,不然excel进程没退出
    21. excel->dynamicCall("Quit()");
    22. });
    23. Q_UNUSED(scope)
    24. excel->setProperty("Visible", false);
    25. excel->setProperty("EnableEvents", false);
    26. excel->setProperty("DisplayAlerts", false);
    27. QAxObject *work_books = excel->querySubObject("WorkBooks");
    28. if(!work_books){
    29. qDebug()<<"query WorkBooks error";
    30. return;
    31. }
    32. work_books->dynamicCall("Open(const QString&)", filepath);
    33. QAxObject *active_book = excel->querySubObject("ActiveWorkBook");
    34. if(!active_book){
    35. qDebug()<<"query ActiveWorkBook error";
    36. return;
    37. }else{
    38. qDebug()<<"book open";
    39. auto book_scope = qScopeGuard([=]{
    40. qDebug()<<"book close";
    41. //bool是否保存修改
    42. active_book->dynamicCall("Close(Boolean)", false);
    43. });
    44. Q_UNUSED(book_scope)
    45. QAxObject *work_sheet = active_book->querySubObject("WorkSheets(int)", 1);
    46. if(!work_sheet){
    47. qDebug()<<"query WorkSheets error";
    48. return;
    49. }
    50. QAxObject *used_range = work_sheet->querySubObject("UsedRange");
    51. if(!used_range){
    52. qDebug()<<"query UsedRange error";
    53. return;
    54. }
    55. //全部读取,范围是上下左右最边上的数据所围城的矩形区域
    56. auto range_data = used_range->dynamicCall("Value()").toList();
    57. qDebug()<<"range data:"<
    58. }
    59. }

  • 相关阅读:
    安装MySql8.0详细教程
    一分钟学习数据安全——自主管理身份SSI基本概念
    虚幻引擎5:增强输入的使用方法
    Mybatis-plus怎么忽略映射字段
    应对数据安全典型薄弱点,这家医院“外防内控”筑牢屏障
    java8 Lambda表达式以及Stream 流
    LDAPWordlistHarvester:基于LDAP数据的字典生成工具
    JS案例----轮播图
    Filter
    python读取视频长度
  • 原文地址:https://blog.csdn.net/gongjianbo1992/article/details/126633078