工作中遇到的一些小问题,总结的小知识记录:C++/Qt
小知识7
- 编译FFMPEG遇到的问题
- CMakeLists.txt配置FFMPEG的依赖方式:
- x264在Windows下编译生成*.lib
- VS编译Qt工程时,遇到提示Change Qt Version的情况
- 在QtOsg的窗口上嵌入子窗口,存在残影的情况
- QWidget如何根据内容自适应窗口大小
编译FFMPEG遇到的问题
具体的编译方法就略了,可以参考:
https://blog.csdn.net/weixin_58320200/article/details/134010291
主要是调用的时候,因为忽略了一个细节,就导致遇到了依赖问题:
在cpp下引用FFMPEG的头文件,需要用extern添加头文件(在上面的引用文章中其实也提到了):
因为FFmpeg是一个用C语言编写的库,所以要告诉C++编译器以C语言的方式进行编译。
当C++程序调用C语言库时,如果直接包含C语言库的头文件,C++编译器会对库中的函数进行名称修饰,这会导致链接时找不到对应的函数名,因为链接器期望的是原始的C语言函数名。
CMakeLists.txt配置FFMPEG的依赖方式:
#依赖库
target_link_libraries(${PROJECT_NAME}
PRIVATE
Qt5::Core
Qt5::Gui
Qt5::Widgets
${OpenCV_LIBS}
${FFmpeg_DIR}/bin/avformat.lib
${FFmpeg_DIR}/bin/avcodec.lib
${FFmpeg_DIR}/bin/avdevice.lib
${FFmpeg_DIR}/bin/avfilter.lib
${FFmpeg_DIR}/bin/avutil.lib
${FFmpeg_DIR}/bin/postproc.lib
${FFmpeg_DIR}/bin/swresample.lib
${FFmpeg_DIR}/bin/swscale.lib
)
#头文件
target_include_directories(${PROJECT_NAME}
PRIVATE
${OpenCV_INCLUDE_DIRS}
${FFmpeg_DIR}/include
Src
)
x264在Windows下编译生成*.lib
在windows下,使用MSYS2的MINGW64编译。
- C:\msys64下的msys2_shell.cmd修改:
set MSYS2_PATH_TYPE=inherit的注释打开,为了能使用MSVC的cl.exe工具:
测试:
- 用mingw64执行x264的编译脚本:
- 生成结果,但lib下是libx264.dll.a,不是lib后缀,而且不能直接改,因为ffmpeg依赖时会有问题。
- 用MinGW的工程转出lib库
进入bin目录下,对libx264-164.dll进行操作,执行如下操作,先生成def,再生成lib:
pexports libx264-164.dll > libx264-164.def
lib /machine:ix86 /def:libx264-142.def
注意:x64的要执行 lib /machine:x64 /def:libx264-164.def
- bin目录下的生成结果,可以把lib拷入到lib目录,方便后面的ffmpeg编译:
- 编译完成ffmpeg后,查看ffmpeg是否关联了x264:
执行:ffmpeg -h encoder=libx264
VS编译Qt工程时,遇到提示Change Qt Version的情况
如图,在编译Qt工程时遇到如下情况,多数情况下是因为VS工程Check到其它机器上后,Qt的路径不匹配,需要手动切换Qt Version。
一般的方法,在解决方案资源管理器的根目录上,单击右键弹出菜单,选择“Change Solution’s Qt Version”,然后VS的Qt插件会自动build一次关联了Qt的工程。
如果还是没解决,就只能对指定的工程进行手动切换,在工程的根节点下(注意不是解决方案的根节点),选择“Qt Project Setting”,然后在弹出表格的“Version”行选择本机内的Qt版本:
*这种情况在VS+Qt方式,根据向导建立的工程下,会出现,如果使用CMakeLists.txt方式构建VS工程,不会出现,毕竟Qt环境在工程生成的时候就会关联。
在QtOsg的窗口上嵌入子窗口,存在残影的情况
如图为在一个Qt的Osg窗口上,嵌入了一个无边框的QDialog,里面的内容一改变,就导致出现残影的无法刷新(即使手动调用刷新也无法解决)
后来排查,主要是在setWindowFlags,直接把QDialog的属性给覆盖了,导致它就是个QWidge的属性,如果是QWidget嵌入则绘制机制会被影响:
错误的实现:
setWindowFlags(Qt::FramelessWindowHint); //不能这么调用
正确的实现:
setWindowFlags(windowFlags() | Qt::FramelessWindowHint); //保留QDialog窗口属性的前提下,去掉边框标题栏
setAttribute(Qt::WA_TranslucentBackground); //可支持半透明
QWidget如何根据内容自适应窗口大小
窗口内的控件设置显隐后,希望窗口大小能根据当前的内容自适应大小。
参考:https://blog.csdn.net/xiaopei_yan/article/details/78930650
- 方法一:比较“笨”的方法就是根据控件的显隐,计算当前显示的控件的大小,对窗口进行resize。
- 方法二:QWidget提供了adjustSize()的函数,可以根据当前窗口内显示的内容进行自适应调整。
如图为同一QWidget窗口,只是控件显隐和内容变了,在调用adjustSize()后会自适应内容大小: