如图,在△ABC中,∠B=90°,AD=BD=FC,E为DF的中点,求证:∠AFD=∠ECB?

  • QMake包含.pri文件:include(../test.pri)。理论上任何能写入.pro文件的内容都可以写到.pri文件中,但通常大家都是把公用的配置选项或者个别非常小的子项目写到.pri文件中。

  • Qt 的版本号,可以用这个做一些判断,来实现一些特别的操作。

  • qmake获取 Qt 相关的文件夹路径:

    主机的可执行程序所在的路径
    Qt二进制文件(工具和应用)所在的路径
    Qt配置文件所在的路径。不适用于Windows
    Qt示例项目所在的路径
    Qt库文件所在的路径(Windows是.lib所在的文件夹)
    Qt测试用例所在的路径
    Qt翻译文件所在的路径
  • 在 Windows 平台上使用MinGW编译 Qt 时不能开启 LTO,否则会报错,不清楚具体的原因

  • 编译 Qt 时常用的参数:

    同意许可协议。加上这个参数会跳过手动同意许可协议这个步骤。
    同时编译调试版本和发布版本
    即使是发布版本也生成调试信息
    编译为动态库(.dll/.so)(默认)
    编译为静态库(.lib/.a)
    静态链接运行时(仅限 MSVC,相当于 -MT/-MTd)
    设置目标平台(交叉编译时)
    隐藏不必要的信息,仅输出警告和错误
    指定链接器,仅可在 bfd,gold 和 lld 这三者中选择(仅限 Linux 平台)
  • 如何使控制台输出的调试信息着色:

    
    
    • 经过我在 Ubuntu 19.04 上的测试,$(echo ...)不是必需的,不加它仍然可以改变控制台字体的颜色,加了它反而会在控制台把它作为文字输出
    • String,不要使用QStringLiteral或者QLatin1String包裹,否则那几个转义字符会被转换成一般的文字而被输出而不是作为控制字符起作用】,但第二次测试时又不会被QStringLiteralQLatin1String影响了,非常奇怪,不知道为什么,以后自己使用时多加注意
  • Qt创建快捷方式(Windows)或符号链接(UNIX):

    
    
  • // 请参考 Qt::CursorShape 这个枚举来获取更多鼠标指针的不同形状
  • 判断、比较版本号:推荐使用Qt提供的QVersionNumber类,直接把版本号的完整字符串传过去,它就能自行识别主版本号、次版本号、修订号和一些其他字符串后缀,也能方便的比较版本号的高低,非常方便好用。

  • 输出调试信息有两种方式(以qDebug为例):

    两者基本只是形式上有所不同,用起来大差不差,具体使用哪种方式,请自行取舍。

  • 这个函数的作用是可以修改日志输出的格式,但它最大的用途是可以利用自定义的回调函数将日志信息写入到文件。

  • Qt 5在使用qInstallMessageHandler设置回调函数时,不能通过常规方法设置为类的成员函数,一般都是设置为全局函数,如果非要设置为一个类的成员函数,请参考以下示例:

    
    
  • QMake如何使Qt编译生成的带版本信息的动态库,文件名末尾不带主版本号:

  • QMake如何使QML插件支持静态加载(只是简单的能静态编译是不行的):

    # 下面这个设置不管静态还是动态都是需要的 # 静态版插件需要将所有资源打包进静态库中,动态链接库不需要 # 资源文件里包含的是插件的qmldir文件和所有.qml文件
  • qtLibraryTarget这个qmake函数会自动添加平台对应的调试版后缀(发布版本不会添加后缀),如果是Linux平台,这个函数还会添加lib前缀。不要用qt5LibraryTarget,这个函数除了添加后缀,还会添加Qt5这个前缀,是Qt自己的库才需要的函数。

  • XmlPatterns无法编译,这四个仓库在编译时都需要开启异常处理,请注意。如果必须禁用异常处理,可以在配置Qt时使用-skip参数来跳过这四个仓库。已经编译完成的Qt库不受影响,可以随意开启和关闭异常处理。

  • 编译Qt时,如果使用了Ofast优化级别(Clang,GCC和ICC都支持,只有MSVC和类MSVC编译器才不支持),会导致Qt的sqlite插件无法编译。这个插件不支持高于O3的优化级别。然而这个是QtCore模块中无法禁用或者跳过的基础插件,如果编译出错就会中断整个Qt的编译,因此只能通过修改这个插件的.pro/.pri文件来规避这个问题(使用自定义的QMAKE_CFLAGS_RELEASEQMAKE_CXXFLAGS_RELEASE)。已经编译完成的Qt库不受影响,可以随意调整优化级别。

  • Windows平台如何获取是否开启深色模式/浅色模式:详见

  • Windows平台如何将窗口设置为深色模式:详见

  • Qt5如何从C++方面调用QML函数/信号?

    注意:如果函数带参数,不管其参数都是什么类型,在调用时一定统一使用QVariant,否则调用无法成功。这不是Bug,这是Qt官方文档中所提到的注意事项。

  • QMake使程序默认请求管理员权限(Windows平台)

  • Qt5开启高DPI缩放支持(Qt6默认开启,不需要手动设置)

    
    
  • 样式表更改:设置样式表、移除样式表、刷新样式表

    
    
  • 使用Qt内置的标准图标

    • QStyle::StandardPixmap这个枚举里包含很多很常用的标准图标,比如最小化按钮,最大化按钮以及关闭按钮等,尽量多利用,不要再费心费力去第三方网站上找或者自己绘制相关的图片素材了。

    • 使用这个函数时一定要记得把一个QStyleOption的指针作为第二个参数传给它,有了这个参数后QStyle内部会根据系统的DPI自动进行尺寸换算,没有这个参数的话返回的图标是没有针对DPI进行调整的。

  • 使用inherits函数判断是否属于某个类

  • QComboBoxaddItem方法的第二个参数可以给对应的item添加一个数据,并可以用itemData这个方法将之取出。

  • 如何使每个控件都拥有独立的句柄:

    
    
  • QMediaPlayer依赖本地解码器,默认状态下仅支持非常有限的格式,Windows平台上下载或者安装即可解决。但QMediaPlayer官方没有提供开启硬件解码的接口,默认全部软件解码,对CPU和内存的占用较高,除非继承QAbstractVideoFilter这个类自己写一个解码插件,自己实现硬件解码(具体方法请查看Qt手册。这个对多媒体文件的编解码知识要求较高,我暂时还干不了这个)。

  • 使用SQLite数据库时如果不想产生数据库文件,可以创建内存数据库:

  • Qt5提供了QScroller这个类直接将控件滚动:

    
    
  • 获取系统窗口标题栏高度:

    • PM_TitleBarHeightQStyle::PixelMetric这个枚举里的一个,这个枚举里还包含很多系统标准控件的尺寸,都可以通过这个函数获取。

    • 使用pixelMetric函数时一定要记得把一个QStyleOption的指针作为第二个参数传给它,有了这个参数后pixelMetric内部会根据系统的DPI自动进行换算,没有这个参数的话返回的是一个无视DPI的固定值。

  • 获取桌面的总尺寸以及可用尺寸(即去掉任务栏后的尺寸):

    注:一定不要再用QDesktopWidget这个类了,这个类早就废弃了,会在以后的版本中移除。

  • 调用系统默认的程序打开一个文件或网址:

    // 如果url是一个本地文件,则调用对应的程序打开。例如,如果url指向了一个word文档,则调用Word或WPS打开它。
    // 如果url是一个网址,则调用默认浏览器打开。
    
  • 在保存文件时,尽量使用QSaveFile这个类而不是传统的QFile,因为QSaveFile会在保存前创建一个临时文件,在保存前的一切操作都是作用于那个临时文件,只有写入操作正常完成了才会替换旧的文件,所以不会损坏当前的文件。而QFile是直接对当前文件进行操作,因此如果遇到突发情况(例如计算机突然断电等),可能会损坏当前文件。

    注意:QSaveFile的用法与QFile基本相同,但前者没有void close()函数,而是用bool QSaveFile::commit()这个函数代替了它。只有执行了commit这个函数,对文件所作的一切修改才会生效。

  • 判断一个文件是否为快捷方式/软链接,并获取其所指向的目标:

    
    

    注意:还有一个叫isSymLink的函数与上面提到的isSymbolicLink函数名字很像,这两个函数的区别是,isSymLink函数对于Windows系统的快捷方式(.lnk文件)和Unix系统的软链接都会返回true,而isSymbolicLink函数只对Unix系统的软链接返回true。但以后尽量不要再用isSymLink这个函数了,Qt会在以后的版本中去掉它。

  • 遍历文件夹下的所有文件:

    
    

    注意事项:由于是遍历文件夹下的所有文件(包括所有子文件夹),因此当文件数量很多时,函数执行的时间会比较长,进而导致用户体验不好,所以尽量在协程或多线程中使用这个函数,尽量不要直接在UI线程中阻塞式的调用。

  • 连接信号和槽函数时参数重载:

  • Qt内置的常用数学函数

    
    
  • 设置Qt默认的图形引擎

    
    
  • 也可以通过设置环境变量来实现这个功能(即不写任何代码):将QT_OPENGL设置为desktopanglesoftware。当使用ANGLE时,设置QT_ANGLE_PLATFORM这个环境变量为d3d11d3d9warp可以修改ANGLE默认使用的DirectX版本。但请注意,这些环境变量的名字及其值都是大小写敏感的。
  • 设置Qt默认使用的OpenGL版本:

    
    

    注:以上代码必须在第一次调用OpenGL前使用,否则不会生效。

  • 如何使能进行翻译的字符串都被tr函数包裹,不被遗漏:

  • 在Linux平台发布Qt程序:

    • 将所有用到的动态库都复制到二进制文件所在的文件夹。可以使用一个叫linuxdeployqt的第三方小工具(Qt官方没有提供类似的工具):

    • 将以下脚本保存到二进制文件所在的文件夹下,并重命名为二进制文件的名字(不包括后缀名,脚本的后缀名一直都是.sh):

    • 每次运行程序都要改为执行这个脚本,不能直接运行二进制文件,否则无法正常启动程序。

  • 如何动态的从外部文件加载资源(仅限使用RCC工具制作的资源文件):

    // 加载资源文件。其中 mapRoot 参数为资源加载后的根节点。
    
  • 
    
  • 无边框窗口+自定义标题栏+拖动窗体+8向拉伸+窗口阴影:

  • Qt Quick获取正在显示QML文档的系统窗口

    注:在使用QQuickView时,由于QQuickView本身就是继承自QWindow,因此可以直接对其本身进行操作。

  • 限制程序只运行一个实例:

    • 原理是使用Qt Network模块的QLocalServer以及QLocalSocket建立一个本地服务器,实现进程间通信。由于Qt Network模块是跨平台的,所以这个项目理论上也是能跨平台的。

    • 使用了TCP/IP以及共享内存等多种技术,理论上也是跨平台的。

  • 进程间通信(IPC):7种方式

  • QProcess:QProcessQIODevice的派生类,因此支持readwrite等函数。当然也可以通过传递和读取命令行参数实现通信。
    • 
       
      
    • Linux:D-Bus。使用Qt D-Bus模块实现。用法较简单,请自行查阅Qt手册。

  • 下载文件:由于代码较多,我放到了一个单独的仓库中

    • 支持 Windows + Unix 平台,但早已经停止维护了(2011年左右),是一个比较老的代码库。用还是能用的,只不过可能用了不少现在看来已经非常过时的技术。

  • 获取操作系统的详细信息

    // 返回Qt面向的CPU的完整架构。 // 返回当前正在运行的CPU的完整架构。 // 返回Qt面向的操作系统的内核类型(同时也是当前操作系统的内核类型) // 返回当前操作系统的内核版本。 // 返回当前计算机的主机名 // 返回更加易读的产品名(内核类型+内核版本,但会更易读。例如:Windows 10 Version 1903)
  • 输出日志时的时间,以进程启动以来的秒数为基准
    输出日志时的时间,以系统启动以来的秒数为基准
    输出日志时的系统时间,以format为输出格式
  • 
    

    注意:QXmlStreamReaderQXmlStreamWriter的性能优化的很好,Qt官方也推荐在操作XML文件时使用这两个类,但使用它们有一个不能忽略的前提条件,那就是被操作的XML文件一定要有良好的格式,例如有正确的缩进以及完好的标签(tag)等,文档本身一定不能是损坏的。

  • 
    
  • 注:某些特殊的或重要的键值没有管理员权限无法修改,例如HKEY_LOCAL_MACHINE等,如果发现无法写入或修改注册表的某个键值,先看是不是权限的原因,不是的话再去看是不是程序本身有bug,实在找不到问题根源再去怀疑是不是Qt本身的bug。

    • 
      
    • 
       
      
    • 
      

    注:任务栏进度条和任务栏小按钮都要使用setWindow函数设置一个有效的QWindow句柄,但这个句柄只有在showEvent执行完毕后(即窗口显示出来以后)才能获得(请参考:)。

  • lupdate:将源码中能进行翻译的字符串制作为Qt Linguist专用的.ts翻译文件

    去除所有废弃的和消失的翻译文本
    不要记录待翻译文本在.ui文件里的行号
    指定输出文件。允许有多个输出文件
    
    
  • lrelease:将.ts文件编译为.qm文件,起到压缩和加密的作用。

    使用ID而不是源码文本作为消息索引
    去除与源码文本完全相同的翻译文本(即翻译了和没翻译一样的文本)
    
    
  • lconvert:将多个.qm文件合并为一个(重复的条目会自动合并)。

    指定输入文件(这个参数可以有多个,意为有多个输入文件)
  • rcc:Qt专用的资源编译器

    使用name创建一个外部的初始化函数
    设置资源文件的根节点(添加到资源文件自己的根节点之前,如果有的话)
    设置压缩算法,可选值为zstd(推荐,三者中压缩率和解压速度最优)、zlibnone
    设置压缩级别。zstd:1~19,zlib:1~9。数字越大,压缩率越高
    设置压缩阈值(临界值),可取值为1~100,只有文件大小的减小量超过原文件大小的level %,rcc才会压缩它,否则rcc会直接存储而不进行压缩。默认值为70
    输出一个二进制文件以便动态加载(可以视为经过压缩和加密的外部资源文件)
  • 显示托盘图标+自定义托盘菜单(使用QWidget而不是QMenu)+弹出消息

    // 返回当前操作系统是否支持显示托盘图标
    // 返回当前操作系统是否支持显示气泡消息
    
    1. QMenuQWidget的派生类,因此,可以直接把一个QWidget传给setContextMenu,使用这个方法就可以不受QMenu的限制了,可以将任何QWidget设置为托盘菜单。
    2. 使用setToolTip函数设置托盘图标的提示信息
    3. 使用setIcon函数设置托盘图标的图标
  • 使用showhide函数来显示或隐藏托盘图标
    • Qt Concurrent模块。如果需要获取线程函数的返回值,或者线程的执行状态和进度,需要搭配QFuture一起使用。

      
      
  • 打开 Qt Creator,菜单选择:工具 -> 选项 -> 文本编辑器 -> 片段,点击“添加”按钮,添加新的“片段”。其中,“触发”为这个片段的触发条件,即当用户输入一个特定的字符串时提示是否插入这个片段的完整版。“触发种类”可以随便填写,这是为了方便用户记忆和区分而设置的。

    • rectangle有效时截取其指定范围内的图像,无效时截取整个窗口(默认)。

    • 截取其他程序的窗口或截屏:

      
      

      grabWindow函数第一个参数传一个窗口句柄window就能对此屏幕上的指定窗口进行截图,传一个空指针则对整个屏幕进行截图。后四个参数则能设置截图范围,若范围无效则对整个窗口或屏幕进行截图(默认)。

  • Windows平台使GUI程序显示控制台窗口:

  • 具体的原理是不要让程序的子系统为WINDOWS,也不要让程序的入口点为(w)WinMainCRTStartup

  • 当想要注释大段的内容时,建议用 #if 0#endif 将代码块包起来,而不是将该段代码选中然后全部 // ,想要取消注释时只要把0改成1即可,效率大大提升。

  • 在使用QFile的过程中,不建议频繁的打开文件写入然后再关闭文件,比如间隔5ms输出日志,IO性能瓶颈很大,这种情况建议先打开文件不要关闭,等待合适的时机比如析构函数中或者日期变了需要重新变换日志文件的时候关闭文件。不然短时间内大量的打开关闭文件会很卡,文件越大越卡。

  • 有时候在界面上加了弹簧,需要动态改变弹簧对应的拉伸策略,对应方法为changeSize,很多人会选择使用set开头去找,找不到的。

  • Qt中继承QWidget之后,样式表不起作用:三个方法

    1. 改成继承QFrame,因为QFrame自带paintEvent函数已做了实现,在使用样式表时会进行解析和绘制。

  • Qt默认不支持大资源文件,需要的话要手动开启:

  • 具体的原理是处理小文件时rcc会将其翻译为C++代码,然后与项目其他的源文件一起参与编译和链接过程,而处理大文件时rcc会直接生成.obj文件,不参与编译过程,只参与最后的链接过程。

  • 如果需要窗口无边框,但是又需要保留操作系统的边框特性,例如可以自由拉伸边框和窗口阴影等,可以使用 setWindowFlags(Qt::Window |

    • 在Windows平台上,这种窗口的顶端会有一个几像素宽的白条,我专门请教过Qt公司的工程师Friedemann Kleint,他调试后告诉我,这个白条在这种状态下是无法去掉的,要去掉白条就只能将系统提供的窗口边框同时去掉,即那个白条和窗口边框是一体的,无法单独去掉。
  • 判断一个类是否是QWidget或QWindow(或它们的派生类):

    
    
    • 编译时版本:QT_VERSION_STR宏(这个宏返回的是编译程序时所链接的Qt库的版本,这个值在编译完成后永远不会改变)
    • 运行时版本:const char *qVersion();函数(这个函数返回的是当前加载的Qt库的版本,它可能会在程序运行期间发生改变)
  • 将最小化或被其他窗口挡住的窗口移到最前:

    
     
     
     
     
     
    
  • 窗口如何置顶?置顶后如何取消置顶?

    
    
  • 解决方法:窗口只是单纯的不可见了,重新将窗口显示出来即可。

    
    
  • 窗口最小化后恢复原始大小,窗口假死:

    在窗口显示前激活窗口的Qt::WA_Mapped属性。

  • 连接信号和槽函数时,尽量使用函数指针

    使用这种连接方式,有三个很明显的优点:

    1. 如果信号或槽函数的函数名打错了或函数签名不匹配,根本就不能通过编译,因此能在编译期就发现问题并加以解决。
    2. 使用的是函数指针,省却了根据字符串查找信号和槽函数的过程,运行速度有所提高。
    3. 使用的是函数指针而不是字符串,节约了部分内存。而且由于不再构建QString对象,性能也有所提高。
  • 启用了鼠标跟踪的时候(setMouseTracking(true)),如果该窗体上面还有其他控件,当鼠标移到其他控件上面的时候,父类的鼠标移动事件就会识别不到了,此时需要用到HoverMove事件,需要先设置setAttribute(Qt::WA_Hover);

  • Qt封装的日期时间类QDateTime非常强大,可以在字符串和日期时间之间相互转换,也可以在(毫)秒数和日期时间之间相互转换,还可以在自T00:00:00.000经过的(毫)秒数和日期时间之间相互转换等。

  • 在使用QListQVector以及QByteArray等链表或者数组的过程中,如果只需要取值不需要赋值,建议使用const T &at(int i) const而不是[]操作符,因为前者的速度远超后者(常数时间复杂度)。

  • const;,因为canonicalFilePath这个函数会尽可能的解析路径,不会包含...或任何快捷方式/软链接,而且返回的是完整的绝对路径,而后两个函数不会解析的如此彻底。

    • 将所有源码文件(.h、.hpp、.c、.cpp、.qml等)的文本编码都改为UTF-8,最好不要带BOM
    • 不要直接在源码(C++和QML)中使用非英文半角字符(注释除外),非英文半角字符一定要用tr(QML:qsTr)函数包裹起来。如果实在不需要翻译,则用QStringLiteral包裹。
    • 编译器开启UTF-8支持。
  • 
    
  • 根据Qt的事件过滤器获取各种事件并进行相应的处理

  • 可以参考这个项目,虽然早就不维护了,但仍然有学习的价值。这个项目是GitHub上为数不多的适合Qt项目的Crash Handler框架了。

  • QDialog窗口默认会阻塞整个应用程序的执行,如果不想这样,可以进行以下设置:

  • 删除Qt对象时,强烈建议使用void QObject::deleteLater()而不是直接delete,因为deleteLater会选择在合适的时机进行释放,而delete会立即释放,很可能会导致程序出错崩溃。

  • 如果要批量删除Qt对象,或删除一个容器里包含的所有对象,可以用qDeleteAll

    
    
  • 读写文本数据时推荐使用QTextStream。这个类优化的很好,读写速度很快,比直接用QFile进行读写快得多。而且用这个类还能设置字符编码,还支持很多其他的功能,没有理由不用它。具体用法请查阅Qt官方手册。

    • 
       
      
  • 读写二进制数据时推荐使用QDataStream

    这个类是用来读写二进制数据流的,而二进制数据流的内容是不能被第三方软件读取的,因此其常见用途为读写软件独有的文档/数据格式。

    • 
      
    • 跨平台。此项目对程序的安装及升级程序没有任何要求。这个项目的代码也比较简短,可以根据自己的需求自行修改扩充。

    • 跨平台。此项目要求程序的安装及升级程序必须使用制作。

    • QWidgetQWindow都有此函数,返回的是被执行对象的窗口系统标识符(我自己翻译的,不知道正规叫法是什么,Windows平台上是叫窗口句柄)。在Windows平台上就是HWND,但要用reinterpret_cast转换一下才能用。这个函数的返回值有可能会在运行时发生改变,如果你的程序对此变化敏感,请注意自行处理QEvent::WinIdChange这个事件。

      QWindow用这个函数没什么需要注意的,但QWidget不同。QWidget很有可能是一个子控件(例如一个很复杂的窗口中的某个小部件),在这种情况下执行这个函数就会导致Qt为其创建一个窗口句柄,使其成为一个原生窗口。

    • 此函数为QWidget独有,当被执行对象为原生窗口(即一个独立的窗口,不是什么窗口内部的子控件)时,返回窗口句柄,当不是原生窗口时,返回当前对象所在的顶级窗口的句柄。

      注意不要储存这个函数的返回值,现用现取就可以了,因为这个函数的返回值可能会在运行时发生变化。

    • windowHandle()这个函数为QWidget独有,当QWidget是原生窗口时,它返回的是QWidget所绑定的QWindowQWidget都是显示在QWindow上的)的指针,当QWidget不是原生窗口时,返回空指针。所以,windowHandle()->winId()的作用就是,当QWidget为原生窗口时返回其窗口句柄,当不是原生窗口时返回空指针(当然在这个过程中,你要自己判断下windowHandle()的返回值是否为空)。

      同样不要存储这个函数的返回值,运行时会发生变化,现用现取即可。

    对比:这三种方法中的后两种其实都是差不多的,第一种和后两种最主要的区别是,看你要获取的句柄到底是窗口的句柄还是控件的句柄。后两种都是用来获取窗口句柄的,第一种当QWidget是一个控件的时候获取到的是这个控件的句柄,而不是它所在的窗口的句柄。而QWindow就是底层的窗口类,本身就是不能作为控件使用的,因此对QWindow执行winId()总是返回其窗口句柄。

  • 添加、删除、更新和获取环境变量

    
    
  • 使用QTimer::singleShot可以实现延时执行部分代码,在某些特定情况下特别好用,请留意。

    
     
    
  • 使用弱属性机制,可以很方便的实现许多意想不到的效果:

    
    
  • 获取类的元对象属性及其值(非弱属性)

  • 64-bit为例,且安装到默认位置),发布版文件为qwindows.dll,调试版文件为qwindowsd.dll,请确保您开发的Qt程序所在的文件夹下存在platforms(或plugins\platforms)文件夹且qwindows(d).dll位于其中,并注意32位和64位的DLL不能混用。另,使用等压缩或加壳程序处理过的QPA插件也经常无法正常加载,这点也要十分注意。其他平台的QPA插件也大同小异,与Windows平台相比,只是文件名和后缀名有所区别。

    注:所有Qt插件(plugins文件夹下的所有内容)都不要用任何第三方程序(例如UPX)进行处理,否则会导致Qt程序行为异常。

  • QTableView控件中,如果需要自定义的列按钮、复选框、下拉框等其他模式显示,可以采用自定义委托QItemDelegate来实现,如果需要禁用某列,则在自定义委托的重载createEditor函数返回0即可。自定义委托对应的控件在进入编辑状态的时候出现,如果想一直出现,则需要重载paint函数用drawPrimitive或者drawControl来绘制。

  • 在已知背景色的情况下,为了能够清晰的绘制文字,这个时候需要计算合适的文字颜色:

    
    
  • QVariant提供了toInttoRealtoBooltoStringtoList以及toMap等方法,可以方便的将QVariant转为各种具体的类型,如果遇到想要转换的类型没有类似的转换函数,可以用以下方法手动进行转换:

  • 注:Qt安装完成后会自带一个叫translations的文件夹,这里面存放着Qt自身的翻译,比如各种Widget。这个翻译是官方的,而且覆盖程度很高,大概八九成的地方都有对应的翻译。Qt Quick程序会自动加载其中的翻译,但Qt Widgets程序需要自行加载。

  • 如何获取此电脑计算机我的电脑)、以及回收站垃圾桶废纸篓)等系统程序的图标或某个具体的文件的图标

    • 
      

      注:使用QFileIconProvider获取本地文件的图标只有传QFileInfo这一个方法,没有第二种。

  • 创建临时文件或临时文件夹

    临时文件或文件夹在某些特殊场景下是非常有用的,比如软件下载更新包,可以先下载到一个临时文件夹中,下载完毕校验成功后再进行下一步的操作。为此,Qt提供了QTemporaryFileQTemporaryDir这两个类,它们都可以保证生成一个绝对独一无二的临时文件(夹),默认情况下它们所生成的临时文件(夹)会在其析构时删除,保证不会产生任何残留,但这个行为可以通过setAutoRemove这个函数修改。所生成的文件(夹)的路径也可以通过path这个函数获取。更多用法请自行查看文档。

  • 裁剪Qt,在尽量不影响性能的情况下,使编译得到的二进制文件最小:,通过编译前配置参数,来去掉尽可能多的无用特性。

  • 不同的QObject及其派生类的对象,在进行类型转换时,建议使用qobject_cast而不是dynamic_cast,因为前者不需要开启RTTI

    待转换的对象必须直接或间接继承自QObject,并且使用Q_OBJECT宏进行了声明。如果不符合以上条件,则返回空指针。

  • 应用程序在执行耗时的操作时,如何防止界面卡顿

    • 效果:界面不会完全卡住,但在配置不够高的机器上还是有所卡顿。

    • 
       
       
       
      

      效果:界面完全不会卡住,哪怕是在配置很低的机器上。

    • 效果:界面完全不会卡住,哪怕是在配置很低的机器上。

    • 效果:界面完全不会卡住,哪怕是在配置很低的机器上。

    总结:在执行耗时操作时,推荐使用Qt Concurrent模块实现多线程,不仅完全不会使界面卡住,还能以较少的代码实现较多较高级的功能,用起来十分方便舒心。

  • 监视文件(夹)的变化:请自行查阅QFileSystemWatcher的用法。

  • 
    

    注:如果需要修改已经提交的内容(例如代码审阅人提出了修改意见),可以在本地分支直接修改(切换到补丁所在的分支之后就不要再动Git了,直接在上次提交的基础上进行修改),然后使用git commit -a --amend修改上一次的提交(所有内容都改完了,再执行这一条命令即可,这条命令的意思是,当前所做的所有的改动,都是对上一次提交的改动,而不是创建一个新的提交),再重新推送到远端即可。这样会在JIRA上形成多个patch set。注意在执行git commit命令时一定不要忘了-a--amend这两个参数,-a这个参数的作用是把所有未跟踪的文件添加到跟踪列表,--amend参数的作用是指示Git此次操作是修改而不是创建提交。

  • 不要直接在构造函数里获取控件的尺寸和位置等信息,因为Qt的各种控件在被显示出来之前是不具备这些信息的,虽然能获取到具体的数字,但不一定准确。如果一定要获取类似的信息,一定要等它们显出出来再进行。

  • Qt中有个全局的焦点切换信号focusChanged,可以用它做自定义的输入法。Qt4中默认会安装输入法上下文,这个默认安装的输入法上下文会拦截两个信号,QEvent::RequestSoftwareInputPanelQEvent::CloseSoftwareInputPanel,以至于就算你安装了全局的事件过滤器也依然获取不到这两个信号,你只需要在main函数执行app.setInputContext(nullptr)即可,意思是设置输入法上下文为空。

  • 理论上串口和网络收发数据默认都是异步的,操作系统自动调度,完全不会卡住界面,网上那些说收发数据卡住界面主线程的都是瞎说的,真正耗时的是运算以及运算后的处理,而不是收发数据。在一些运算数据量很小的项目中,一般不建议动用线程去处理,线程调度是有开销的,不要什么东西都往线程里边扔,线程不是万能的。只有当真正需要进行一些很耗时的操作(比如多媒体编解码等)时,才需要移到线程处理。

  • 数据库处理一般建议在主线程中进行,如果非要在其他线程中操作,务必记得打开数据库也要在那个线程,即在哪个线程使用数据库就在哪个线程打开它,而不能在主线程打开数据库,在子线程执行sql,这样很可能出问题。

  • 新版的QTcpServer类在64位版本的Qt下很可能不会进入incomingConnection函数,那是因为Qt5对应的incomingConnection函数的参数类型变了,由之前的int改成了qintptr。改成qintptr有个好处,那就是在32位上是quint32而在64位上是quint64。如果在Qt5中继续把参数当int,在32位上不会出问题,但在64位上肯定会出问题,所以为了兼容Qt4和Qt5,必须分开处理:

  • 判断两个浮点数是否相等时,尽量使用Qt提供的qFuzzyCompare函数(头文件:QtGlobal),但不能对NaN(Not a Number,可以使用qIsNaN函数进行判断)或者无穷(可以使用qIsInf函数进行判断)这两类数字进行判断。注意不要用这个函数和常数0/0.0比较,这种情况下要改用qFuzzyIsNull函数。

  • 告知编译器,表达式expr的计算结果很有可能(但不一定)为true。此宏被用来改善编译器优化,但编译器不一定都接受此提示。
    告知编译器,表达式expr的计算结果很有可能(但不一定)为false。此宏被用来改善编译器优化,但编译器不一定都接受此提示。
    告知编译器,当前位置是任何情况下都不可能到达的(例如switch语句的某些分支)。
    告知编译器,参数name没有被使用。此宏被用来消除某些编译器警告。
    无限循环,等价于for(;;)
    告知编译器,表达式expr的计算结果一定为true。但当表达式expr的计算结果为false时,此宏的效果与Q_UNREACHABLE相同。此宏被用来改善编译器优化,但编译器不一定都接受此提示。
  • 如何像微软的Office套件那样,用户关机时暂时中断系统的关机进程,提示用户保存未保存的文档,处理完毕后再继续关机?

    注:更多更详细的用法请自行查看Qt文档中关于QSessionManager的部分。

  • Qt支持将QPushButtonQLineEdit等控件自动关联与它们相对应的on_控件名_信号(参数)这一类的槽函数,比如按钮openButton的点击信号会自动关联槽函数on_openButton_clicked()(如果找得到这个函数的实现的话)。

  • 如何获取程序正在使用的OpenGL类型(OpenGL或OpenGL ES)、版本、格式、制造商(英特尔、英伟达等)等信息:

    注:摘自Qt工具的源码。

  • 将文件(夹)移动到回收站/废纸篓,而不是彻底删除:QFile::moveToTrash,此API于Qt 5.15引入。

    • 
      
  • 开发Qt Quick插件时,如何将qml文件编译到库文件中,而不是直接暴露在外部

    • 将qml文件添加到qrc文件中,使其编译到最终的库文件中

  • <namespace>将所有Qt函数和类都移入一个指定的命名空间(默认是没有的,这个功能只有特殊场景才需要),因此如果你对Qt的类使用了前置声明,一定要用QT_BEGIN_NAMESPACEQT_END_NAMESPACE这两个宏进行包裹,否则在这种带命名空间的Qt上无法编译通过。

  • QObject是一个非常重型的类,初始化较慢,且实例化后占用内存较多,如果只是做一些简单的工作或完全不需要Qt的元对象系统,就不要继承自该类。虽然是在编写Qt程序,但一定不要无脑派生该类。

  • 善用qScopeGuard来执行各种“清理”操作。QScopeGuard:在当前代码块的生命周期结束前,执行指定的代码,但不可抛出异常。

  • QWidget无法在构造函数里获取其所在QWindow的指针,如果有什么工作必须要在窗口显示出来之前进行,可以在这个Widget的showEvent中操作,在这个事件里QWindow是能被获取到的。

  • 如果要保存某个QObject或其派生类的指针,不涉及指针所指向的对象的所有权,建议使用QPointer,因为它会在对象销毁后自动重置为空指针。其用法与正常指针一样,因此基本可以无缝迁移。

    
    
  • 默认情况下控件获取焦点以后会有虚边框,如果看着觉得碍眼不舒服可以去掉,设置样式即可:setStyleSheet("*{outline:0px;}");

  • 使用QLoggingCategory可以做到输出日志时连同日志分类一起输出(如果日志格式没有被更改),还能使用一定的规则对日志消息进行过滤。如果不使用这个类,单纯使用qDebug等函数进行输出,最大的缺点就是无法对日志消息进行过滤,要输出就全都输出,要屏蔽就全都屏蔽,不能针对某一类消息进行过滤。

    • 
      
    • 
      
    • 有三种方式对日志消息进行过滤:C++函数、INI配置文件和环境变量。通过调用静态函数QLoggingCategory::setFilterRules()可以设置过滤规则;INI配置文件位于[QLibraryInfo::DataPath]/qtlogging.ini[QStandardPaths::GenericConfigLocation]/QtProject/qtlogging.ini(后者优先级高于前者),文件的内容就是日志的过滤规则,和你使用函数时传递的参数一样,Qt程序会在启动时自动加载这个文件,你在这个文件里设置的规则会自动生效,如果你将规则写入到别的地方了,就只能手动加载了;环境变量的名字是QT_LOGGING_RULES,内容也是过滤规则。这三个方式的优先级是环境变量>C++ API>INI文件。如果你想知道你的程序是从哪里加载的规则,设置QT_LOGGING_DEBUG这个环境变量就能看到了。

      我这里只是简略的提了下,还有很多详细的内容没写,具体用法请自行查阅Qt手册。

  • 如何使qDebug等函数支持我自己的数据类型?

    • Qt支持编译时去掉日志功能以减小二进制文件的大小和提高程序的性能,所以要先用QT_NO_DEBUG_STREAM这个宏判断一下,否则这个代码在这种配置的Qt上会无法编译
    • QDebugStateSaver是用于在其对象销毁时还原QDebug的设置,如果你没有修改QDebug的格式,是不需要这个的,但如果不放心的话可以无脑带上,反正没坏处
  • 连接信号和槽函数而槽函数又是一个匿名函数时,有无槽函数父对象指针的区别

    
    

    从上面的代码可以明显看出,两个连接方式唯一的区别就是有没有槽函数父对象的指针,当然此处的槽函数是我们自己写的匿名函数。在槽函数的执行上,这两种写法没有任何区别,但对于指定了槽函数父对象的方式,Qt会在调用槽函数前首先检查其父对象是否已经销毁,如果已经销毁,会自动执行disconnect并忽略槽函数的执行。如果没有指定槽函数的父对象,会无视其父对象的生命周期,只要触发相关信号就会调用所绑定的槽函数。

  • 八年级下册数学第一章测试题及答案

      八年级即将升入初三,对于学习要记好公式,认真对待!以下是小编收集整理了八年级下册数学第一章测试题及答案,供大家参考借鉴,希望可以帮助到有需要的朋友。

      1.已知:两直线平行,内错角相等;已知:两直线平行,同位角相等;等量代换。

      ∴OB=OC(等角对等边).

      (2)在△ABD和△ACE中,

      ∴AB=AC,即△ABC是等腰三角形.

      5.解:在Rt△ABC中,

      ∵高BD,CE交于点O,

      由③知∠ABC=∠ACB,由①知∠BAM=∠CAM,又

      证明:由①知∠AOE=∠AOD,由②知∠BOE=∠COD,

      由③知∠BOC=∠OCB,

      7.已知:在△ABC中,AB=AC,求证:∠B与∠C都是锐角。

      证明:∵AB=AC,∴∠B=∠C.假设∠B与∠C都为直角或钝角,于是∠B+∠C≥180°,这与三角形内角和定理矛盾,因此∠B和∠C必为锐角.即等腰三角形的底角必为锐角.

      8.解:△AFD是直角三角形.理由如下:

      ∴DAE=∠E=55°(等边对等角).

      ∴△AFD是直角三角形。

    【八年级下册数学第一章测试题及答案】相关文章:

    我要回帖

    更多关于 如图,在△abc中,ab=ac,点d在ab上 的文章

     

    随机推荐