对于一些透明或者半透明的QWidget,可能需要点击其下方的按钮或其他组件,但是QWidget本身是会接收这些鼠标事件的,需要一些额外的处理。下面是百度到的一些方法:
方式A.设置setAttribute(Qt::WA_TransparentForMouseEvents, true),设置之后该QWidget对象树就不再处理鼠标事件。最大的缺点就是不仅该QWidget不响应鼠标事件,它上面的其他组件也没法响应鼠标事件了。
方式B.setMask把底部要点击的地方抠出来,缺点是抠出来的地方就成了全透明,不适合半透明的需求:
- QRegion reg(ui->widget->rect());
- //bottom为被widget挡住的按钮
- auto btn_area=ui->btnBottom->geometry();
- btn_area.moveTo(btn_area.topLeft()-ui->widget->geometry().topLeft());
- reg-=QRegion(btn_area);
- ui->widget->setMask(reg);
方法C. QWdidget鼠标事件处理先判断坐标点下方是否有其他组件,有则传递下去:
- void mouseMoveEvent(QMouseEvent *event){
- transMouseEvents(event);
- }
-
- void mousePressEvent(QMouseEvent *event){
- transMouseEvents(event);
- }
-
- void mouseReleaseEvent(QMouseEvent *event){
- transMouseEvents(event);
- }
-
- void mouseDoubleClickEvent(QMouseEvent *event){
- transMouseEvents(event);
- }
-
- void transMouseEvents(QMouseEvent *event){
- if (this->parentWidget()) {
- this->setAttribute(Qt::WA_TransparentForMouseEvents, true);
- QPoint pt = this->mapTo(this->parentWidget(), event->pos());
- QWidget *wid = this->parentWidget()->childAt(pt);
- if (wid) {
- pt = wid->mapFrom(this->parentWidget(), pt);
- QMouseEvent *mEvent = new QMouseEvent(event->type(), pt, event->button(), event->buttons(), event->modifiers());
- QApplication::postEvent(wid, mEvent);
- }
- this->setAttribute(Qt::WA_TransparentForMouseEvents, false);
- }
- }
参考:QT 鼠标穿透 - 知乎
百度搜(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
一开始测试MS Office时如下的代码可以正常的读取到UsedRange的表格内容:
- QAxObject *used_range = work_sheet->querySubObject("UsedRange");
- auto range_data = used_range->property("Value").toList();
但是在测试WPS时,读取到的值是空的,修改为dynamicCall后就能正常读取了:
- QAxObject *used_range = work_sheet->querySubObject("UsedRange");
- auto range_data = used_range->dynamicCall("Value()").toList();
完整的测试代码如下:
- void parseExcel()
- {
- const QString filepath = QFileDialog::getOpenFileName(this);
- if(filepath.isEmpty()){
- qDebug()<<"filepath is empty";
- return;
- }
-
- QSharedPointer
excel{new QAxObject}; - //分别尝试WPS和MS Office的excel组件
- if(!excel->setControl("KET.Application" )){
- qDebug() << "open wps excel failed";
- if(!excel->setControl("Excel.Application")){
- qDebug() << "open office excel failed";
- return;
- }
- }
-
- qDebug()<<"excel open";
- auto scope = qScopeGuard([=]{
- qDebug()<<"excel quit";
- //退出时关闭,不然excel进程没退出
- excel->dynamicCall("Quit()");
- });
- Q_UNUSED(scope)
-
- excel->setProperty("Visible", false);
- excel->setProperty("EnableEvents", false);
- excel->setProperty("DisplayAlerts", false);
- QAxObject *work_books = excel->querySubObject("WorkBooks");
- if(!work_books){
- qDebug()<<"query WorkBooks error";
- return;
- }
- work_books->dynamicCall("Open(const QString&)", filepath);
- QAxObject *active_book = excel->querySubObject("ActiveWorkBook");
- if(!active_book){
- qDebug()<<"query ActiveWorkBook error";
- return;
- }else{
- qDebug()<<"book open";
- auto book_scope = qScopeGuard([=]{
- qDebug()<<"book close";
- //bool是否保存修改
- active_book->dynamicCall("Close(Boolean)", false);
- });
- Q_UNUSED(book_scope)
-
- QAxObject *work_sheet = active_book->querySubObject("WorkSheets(int)", 1);
- if(!work_sheet){
- qDebug()<<"query WorkSheets error";
- return;
- }
- QAxObject *used_range = work_sheet->querySubObject("UsedRange");
- if(!used_range){
- qDebug()<<"query UsedRange error";
- return;
- }
- //全部读取,范围是上下左右最边上的数据所围城的矩形区域
- auto range_data = used_range->dynamicCall("Value()").toList();
- qDebug()<<"range data:"<
- }
- }