QPrintDialog弹出慢的问题

embedded/2025/3/28 13:30:56/

开发环境

            操作系统: openkylin2qt版本  : 5.15.10

排查过程

        首先看下问题的现象,

问题现象

        

      复现问题的demo很简单,只能是从跟踪qt代码方面入手

            void MainWindow::on_pushButton_clicked(){QPrinter printer;QPrintDialog dialog(&printer,this);dialog.exec();}

        现在需要找一个代码的起点去跟踪,想了半天没有思绪,于是设置环境变量export QT_DEBUG_PLUGINS=1看看有没有提示,结果发现程序会在这一行阻塞一段时间

     load library  "xxx/plugins/printsupport/libcupsprintersupport.so"

        怀疑可能与加载libcupsprintersupport.so库有关,可以从QLibrary加载插件库的代码开始查,经过gdb+打日志双重定位下,找到了耗时的代码范围

            //这个函数在运行过程中被调用了多次QPrinterInfo QPrinterPrivate::findValidPrinter(const QPrinterInfo &printer){// Try find a valid printer to use, either the one given, the default or the first availableQPrinterInfo printerToUse = printer;if (printerToUse.isNull()) {printerToUse = QPrinterInfo::defaultPrinter(); //调用耗时1秒if (printerToUse.isNull()) {QStringList availablePrinterNames = QPrinterInfo::availablePrinterNames(); //调用耗时1秒if (!availablePrinterNames.isEmpty())printerToUse = QPrinterInfo::printerInfo(availablePrinterNames.at(0));}}return printerToUse;}//这个构造函数被调用了一次QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p, QPrinter *prn): parent(p), propertiesDialog(nullptr), printer(prn),#if QT_CONFIG(cups)m_duplexPpdOption(nullptr),#endifoptionsPane(nullptr), filePrintersAdded(false){q = nullptr;if (parent)q = qobject_cast (parent->parent());widget.setupUi(parent);int currentPrinterIndex = 0;QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();if (ps) {const QStringList printers = ps->availablePrintDeviceIds(); //调用耗时1秒const QString defaultPrinter = ps->defaultPrintDeviceId();  //调用耗时1秒widget.printers->addItems(printers);const QString selectedPrinter = prn && !prn->printerName().isEmpty() ? prn->printerName() : defaultPrinter;const int idx = printers.indexOf(selectedPrinter);if (idx >= 0)currentPrinterIndex = idx;}widget.properties->setEnabled(true);#if QT_CONFIG(filesystemmodel) && QT_CONFIG(completer)QFileSystemModel *fsm = new QFileSystemModel(widget.filename);fsm->setRootPath(QDir::homePath());widget.filename->setCompleter(new QCompleter(fsm, widget.filename));#endif_q_printerChanged(currentPrinterIndex);QObject::connect(widget.printers, SIGNAL(currentIndexChanged(int)),parent, SLOT(_q_printerChanged(int)));QObject::connect(widget.fileBrowser, SIGNAL(clicked()), parent, SLOT(_q_btnBrowseClicked()));QObject::connect(widget.properties, SIGNAL(clicked()), parent, SLOT(_q_btnPropertiesClicked()));// disable features that QPrinter does not yet support.widget.preview->setVisible(false);}//上面调用耗时的函数就是下面这两个QStringList QCupsPrinterSupport::availablePrintDeviceIds() const{QStringList list;cups_dest_t *dests;int count = cupsGetDests(&dests); //调用耗时1秒list.reserve(count);for (int i = 0; i < count; ++i) {QString printerId = QString::fromLocal8Bit(dests[i].name);if (dests[i].instance)printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance);list.append(printerId);}cupsFreeDests(count, dests);return list;}QString QCupsPrinterSupport::staticDefaultPrintDeviceId(){QString printerId;cups_dest_t *dests;int count = cupsGetDests(&dests); //调用耗时1秒for (int i = 0; i < count; ++i) {if (dests[i].is_default) {printerId = QString::fromLocal8Bit(dests[i].name);if (dests[i].instance) {printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance);break;}}}cupsFreeDests(count, dests);return printerId;}

               cupsGetDests是cups库的api

 (1) cups 是一个开放源代码的打印系统,为Unix类操作系统(如Linux)提供了标准的打印架构。(2) libcupsprintersupport.so库为qt开发者提供更便捷的api, libcupsprintersupport.so库内部调用的还是cups库api

                

               我单独写了一个调用cups api的demo,进一步验证是cupsGetDests耗时

            #include < cups/cups.h >#include < iostream >#include < ctime >#include < sys/time.h >//编译命令 g++ test.cpp -lcups/*开始 cupsGetDestsTimestamp (milliseconds): 1742524701156Timestamp (milliseconds): 1742524702187结束 cupsGetDests开始 cupsFreeDestsTimestamp (milliseconds): 1742524702187Timestamp (milliseconds): 1742524702187结束 cupsFreeDests*/void getime(){struct timeval tv;gettimeofday(&tv, nullptr);long timestamp = tv.tv_sec * 1000 + tv.tv_usec / 1000;std::cout << "Timestamp (milliseconds): " << timestamp << std::endl;}int main() {// 获取打印机列表cups_dest_t* dests = nullptr;std::cout << "开始 cupsGetDests" << std::endl;getime();int num_dests = cupsGetDests(&dests);  //此处耗时大约1秒getime();std::cout << "结束 cupsGetDests" << std::endl;/*if (num_dests == 0) {std::cerr << "No printers found!" << std::endl;return 1;}*/// 遍历打印机列表for (int i = 0; i < num_dests; i++) {cups_dest_t& dest = dests[i];// 打印打印机名称std::cout << "Printer Name: " << dest.name << std::endl;// 打印打印机是否默认if (dest.is_default) {std::cout << "  (Default Printer)" << std::endl;}// 打印打印机选项for (int j = 0; j < dest.num_options; j++) {std::cout << "  Option: " << dest.options[j].name<< " = " << dest.options[j].value << std::endl;}std::cout << std::endl;}// 释放打印机列表std::cout << "开始 cupsFreeDests" << std::endl;getime();cupsFreeDests(num_dests, dests);getime();std::cout << "结束 cupsFreeDests" << std::endl;return 0;}

排查结论

        qt程序运行过程中使用cups库的api,调用api耗时,导致qt组件弹出慢


http://www.ppmy.cn/embedded/174777.html

相关文章

Spring(以 Spring Boot 为核心)与 JDK、Maven、MyBatis-Plus、Tomcat 的版本对应关系及关键注意事项

以下是 Spring&#xff08;以 Spring Boot 为核心&#xff09;与 JDK、Maven、MyBatis-Plus、Tomcat 的版本对应关系及关键注意事项&#xff0c;基于最新技术生态整理&#xff1a; 一、Spring Boot 与 JDK 版本对应 Spring Boot 2.x 系列 最低要求&#xff1a;JDK 1.8推荐版本…

报错 - redis - Unit redis.service could not be found.

报错&#xff1a; Unit redis.service could not be found.Could not connect to Redis at 127.0.0.1:6379: Connection refused解决方法&#xff1a; 检查状态、有必要的话 重新安装 Linux 上查看状态 systemctl status redis显示以下内容&#xff0c;代表正常服务 出现下面…

【设计模式】装饰模式

六、装饰模式 装饰(Decorator) 模式也称为装饰器模式/包装模式&#xff0c;是一种结构型模式。这是一个非常有趣和值得学习的设计模式&#xff0c;该模式展现出了运行时的一种扩展能力&#xff0c;以及比继承更强大和灵活的设计视角和设计能力&#xff0c;甚至在有些场合下&am…

NocoBase 本周更新汇总:优化表格区块的列和操作

原文链接&#xff1a;https://www.nocobase.com/cn/blog/weekly-updates-202503020 汇总一周产品更新日志&#xff0c;最新发布可以前往我们的博客查看。 NocoBase 目前更新包括的版本更新包括三个分支&#xff1a;main &#xff0c;next和 develop。 main &#xff1a;截止目…

uniapp中的vue组件与组件使用差异

Vue组件 动态组件 <component> 功能&#xff1a;渲染一个“元组件”为动态组件。依 is 的值&#xff0c;来决定哪个组件被渲染。 平台差异说明&#xff1a; 平台支持情况App√ (Vue2 需传入 String 类型)HarmonyOS NextHBuilderX 4.24H5√微信小程序/支付宝小程序/百度…

基于Python编程语言实现“机器学习”,用于车牌识别项目

基于Python的验证码识别研究与实现 1.摘要 验证码的主要目的是区分人类和计算机&#xff0c;用来防止自动化脚本程序对网站的一些恶意行为&#xff0c;目前绝大部分网站都利用验证码来阻止恶意脚本程序的入侵。 验证码的自动识别对于减少自动登录时长&#xff0c;识别难以识别…

Python 爬取 1688 关键词搜索接口数据返回说明

在当今的电子商务时代&#xff0c;获取商品信息对于商家和消费者都具有重要意义。1688 作为国内知名的 B2B 电商平台&#xff0c;提供了丰富的商品数据。通过利用 Python 爬虫技术&#xff0c;我们可以自动化地获取 1688 平台上按关键字搜索的商品信息&#xff0c;从而为数据分…

Java复习

在开篇前首先申明一下&#xff0c;本文虽不够系统&#xff0c;但复习够用&#xff0c;尤其是快速回忆( •̀ ω •́ )✧与提问。 主打一个速度。 本文将会从Java的基础语法、面向对象、API、字符串、集合、进阶...等六方面讲起。 一、Java的基础语法&#xff1a; 1、Java入门…