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

QPrintDialog弹出慢的问题

开发环境

            操作系统: openkylin2
            qt版本  : 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 available
                QPrinterInfo 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),
            #endif
                optionsPane(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
            
            /*
                开始 cupsGetDests
                Timestamp (milliseconds): 1742524701156
                Timestamp (milliseconds): 1742524702187
                结束 cupsGetDests
                
                开始 cupsFreeDests
                Timestamp (milliseconds): 1742524702187
                Timestamp (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组件弹出慢

相关文章:

  • 图表的黄金比例
  • clamav服务器杀毒(Linux服务器断网状态下如何进行clamav安装、查杀)
  • Office 2024 专业版系统安装
  • 黑马程序员-微服务开发-MybatisPlus的使用
  • 【LLM学习】论文学习-Qlora: QLoRA: Efficient Finetuning of Quantized LLMs
  • docker compose部署minio报错
  • 到底爱不爱我
  • 【数据挖掘】数据预处理——以鸢尾花数据集为例
  • 网络空间安全(41)权限维持
  • 蓝桥与力扣刷题(蓝桥 立方变自身)
  • DeepBI:重构流量逻辑,助力亚马逊广告实现高效流量增长
  • UML中的类图、时序图等常见图形的作用和基本元素
  • nginx 反向代理 ubuntu
  • c#难点2
  • 【芯片设计- RTL 数字逻辑设计入门 9.3 -- SoC 设计中的 Macro】
  • 经典笔试题 小于 n 的最大整数 贪心 回溯
  • vulnhub-Tr0ll ssh爆破、wireshark流量分析,exp、寻找flag。思维导图带你清晰拿到所以flag
  • 2025年上半年NPDP报名已开启,附报名流程!
  • 家庭 企业数据仓库:如何配置和管理 NAS 系统
  • @AuthenticationPrincipal user null
  • 成都警方通报:8岁男孩落水父母下水施救,父亲遇难
  • 沙县小吃中东首店在沙特首都利雅得开业,首天营业额5万元
  • 李公明谈“全球南方”与美术馆
  • 吉林:消纳绿电,“氢”装上阵
  • 王毅集体会见加勒比建交国外长及代表
  • 寒武纪陈天石:公司的产品力获得了行业客户广泛认可,市场有望迎来新增量需求