• Qt4问题集锦


    一、Qt程序发布后加载的jpg、jpeg图片不可见

    问题的提出:

    最近在客户机器上部署安装QT编写的软件,发现只要是jpg、jpeg格式的图片都无法显示出来。最后发现必须按如下述步骤才能显示jpg、jpeg格式的图片:
    1、 在你主启动程序即exe同一目录下新建一个目录,目录名必须和QT安装目录下的imageformats目录同名。也即新建一个名为imageformats的文件夹。
    2 、找到QT安装目录下C:Qt4.8.5pluginsimageformats子目录,将该子目录下的qjpeg4.dll文件复制到步骤1中新建的imageformats目录即可。
          此时再次启动主程序,现在发现jpg、jpeg格式的图片可以显示出来了。

    说明:步骤2中红色路径我QT的安装路径,你的路径可能和我这不一样,请自行更改。

    二、运行Qt程序时碰到QWidget: Must construct a QApplication before a QPaintDevice

    问题的提出:

    之前编译Qwt源码生成qwtd.dll,qwt.dll,然后在工程.pro文件中使用时引入Qwt模块:

    DEFINES += QT_DLL QWT_DLL
    INCLUDEPATH += C:/QtSDK/Desktop/Qt/4.8.1/mingw/include/Qwt
    LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwtd
    LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwt
    结果程序运行时,出现QWidget: Must construct a QApplication before a QPaintDevice
    网上搜索的结果是Releases和DEBUG版本的库混在一起了,虽然他们是不同的名字(Debug版本带个d),但是一直不明白。我生成release版后,直接运行.exe时发现提示缺少qwtd.dll库,
    此时才发现果然是库的问题,生成release版却调用了debug版的库qwtd.dll。

    问题解决:将.pro文件中Qwt模块引入代码改为:

    DEFINES += QT_DLL QWT_DLL
    INCLUDEPATH += C:/QtSDK/Desktop/Qt/4.8.1/mingw/include/Qwt
    CONFIG(debug,debug|release) {
     unix|win32: LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwtd
    } else {
     unix|win32: LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwt
    }

    此时,编译成debug版则只会调用qwtd.dll,而生成release版则只会调用qwt.dll。

    三、Qt编写上位机一定要初始化变量以及谨慎操作指针(尤其是QWidget控件指针)

    背景:在编写QT上位机界面时,界面在运行的时候经常出现卡死或者直接挂掉的怪现象。

    正文:上位机有个函数为check_receive();该函数的作用为定时调用循环检测USB是否有数据。若有,则将信息打印到界面窗体上。界面上有两个QTableWidget窗体

    "ui->can1tableWidget与ui->can2tableWidget",根据传上来的的数据某个字节信息为1、或2来打印到对应的窗体上。代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    QTableWidget *canselWidget = NULL;
    unsigned int CANSelCnt;
     
    if(CANData.CANSel == 1)
    {
        CANSelCnt = 第1个窗体显示的行数;    //伪代码
        canselWidget = ui->can1tableWidget ;
    }
    else if(CANData.CANSel == 2)
    {
        CANSelCnt = 第2个窗体显示的行数;    //伪代码
        canselWidget = ui->can2tableWidget ;
    }
    //接着即使用canselWidget来对界面进行操作。

    接着,总会出现,QT上位机界面直接卡死甚至挂掉的问题。观察现象发现,APP在显示数据窗体时即疯狂地新增新的行数。再研究代码,然后将CANSelCnt打印出来,发现其值为一个很大的随机值。

    解决方案:CANSelCnt 在定义的时候要初始化!!!
    接着运行上位机发现,APP显示数据窗体不再疯狂的新增行数了。可还是出现挂掉的现象!!
    进一步调试才发现若是CANData.CANSel的值不是为1、2那会出现什么情况! 就会对canselWideget这个NULL指针进行操作!更改代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    switch(CANData.CANSel)
    {
        case 1:
            CANSelCnt = 第1个窗体显示的行数;    //伪代码
            canselWidget = ui->can1tableWidget ;
             break;
        case 2:
            CANSelCnt = 第2个窗体显示的行数;    //伪代码
            canselWidget = ui->can2tableWidget ;
            break;
        default:
            // 防止后续代码对空指针进行操作,直接返回。
            return;
    }

    总结:

    1、此处代码写的非常不小心,犯如此低级的错误却花费了1天多的时间(还以为是下位机没配置好!)!下次一定要把握住程序运行的每个通路,杜绝此现象再次发生。

    2、由于之前一直在写下位机代码,所以不赋初值的习惯也带入到这里,出了这次惨痛教训!

    (以下讨论仅针对下位机)在下位机,为何会经常出现不赋初值的情况发生。(应该说是在声明的时候不会赋初值。)

      首先,最重要的是,下位机保存全局变量的区域为掉电易失区域,所以得到的变量值会为默认"0"值,严谨的做法还是会初始化全局变量。

      其次,在多个".c"文件包含一个".h"文件的情况下,若在".h"文件中赋初值,则相当于在其内即声明又定义了,那么编译时,即会出现如下报错:keil *** ERROR L104: MULTIPLE PUBLIC DEFINITIONS (报错信息不完整,只挑了重点部分)。所以说有多个".c"文件需要包含该".h"文件时,不能进行变量的定义,只能进行声明!然后在"main函数"内对其进行初始化操作,否则会出现以上错误,即重复定义!

         那么多个"c"文件包含一个".h"文件具体该如何操作呢?

      我自己当时的错误想法既是:

      在".h"文件内,声明全局变量、函数,譬如uchar aa;void sum(uchar aa); 然后多个".c"文件#include该".h"文件,结局很显然,重复定义错误跑不掉。

      何不使用 #ifndef #define #endif ?结果证明并没有什么卵用。

      正确的做法是,

      在".c"文件内声明全局变量、函数,譬如uchar aa;void sum(uchar aa);,并在".c"文件内实现该函数。

      然后,在".h"文件,将变量aa,函数void sum(uchar aa);声明为extern,这样,其他".c"包含该".h"文件即不会提示重复定义,也可以调用其内部的函数。

      其实这种做法其实相当于某个需要调用该".c"文件的其他"XXX.c"文件在其文件内 extern 该“.c"文件内实现的函数及定义的变量。若是多个文件需要使用使用,每个".c"文件都需 extern 同样的变量和函数,显然在做重复工作,于是就将它放在一个".h"文件,多个".c"文件需要调用时直接包含该".h"文件就可以实现 extern 了。

    总之,要养成良好的编程习惯,编写下位机时最好不要在.h文件去定义一个变量,更不能在.h文件去初始化变量。变量定义与初始化在.c文件进行,若多个外部.c文件需要调用,则在.h文件中添加extern进行外部声明即可。

  • 相关阅读:
    DataStructure期末复习小tips
    MediaPlayer
    Java中Calendar的用法
    C++小tips
    函数返回局部变量的问题
    framebuffer
    MTK gpio adb 控制 和 查看中断INDEX
    emmc
    No 'Access-Control-Allow-Origin' header is present on the requested resource.解决方法(亲测有效)
    JavaScript的Promise必须要会的几个点
  • 原文地址:https://www.cnblogs.com/King-Gentleman/p/5986331.html
Copyright © 2020-2023  润新知