简述:
Qt 官网下载地址: http://download.qt.io/archive/qt/
1、关于 Qt触摸事件
需要确定两点:A . 设备支持touch事件(是触控设备)
B . 需要设置窗口属性:setAttribute ( QT::WA_AcceptTouchEvents ) ; // 接收touch消息
2、setMouseTrack ( );
要想实现 mouseMoveEvent ,则需要在构造函数中添加setMouseTrack (true) , 直接得到监听事件,若是 setMouseTrack (false) ,只有在鼠标按下才会有 mouseMoveEvent 监听事件响应。
3、Qt中OpenGL的简单介绍
Qt中的OpenGL主要是在QGLWidget类中完成的,而要使用QtOpenGL 模块,需要在项目文件 .pro 中添加代码:
QT += openglwin32:LIBS += -lOpengl32 \-lglu32 \-lglut
QGLWidget 类是一个用来渲染OpenGL图形的部件,提供了在Qt中显示OpenGL图形的功能。这个类使用起来很简单,只需要继承该类,然后像使用其他QWidget部件一样来使用它。QGLWidget提供了3个方便的纯虚函数,可以在子类中通过重新实现它们来执行典型的OpenGL任务:
initializeGL ( ) : 设置OpenGL渲染环境,定义显示列表。该函数只在第一次调用 resizeGL ( )或paintGL ( ) 前被自动调用一次。
resizeGL ( ) : 设置OpenGL的视口、投影等。每次部件改变大小时会自动调用该函数。
paintGL ( ) :渲染OpenGL场景。每当部件需要更新时会调用该函数。
也就是说,Qt中当创建并显示出一个QGLWidget子对象时,会自动依次调用initializeGL ( ) 、resizeGL ( ) 、 paintGL ( ),完成当前场景的绘制;而当某些情况发生时,会根据情况决定是否自动调用initializeGL ( ) 、resizeGL ( ) ,一旦调用了initializeGL ( ) 、resizeGL ( ) ,会紧跟着调用paintGL ( ) 对场景进行重新绘制。
4、renderText ( ): 在OpenGL 图形周围写字
头文件:qgl.h
函数原型:
x , y , z :显示文字的坐标位置;str : 要显示的字符串;fnt :显示文字的字体void renderText(int x, int y, const QString & str, const QFont & fnt = QFont()); void renderText(double x, double y, double z, const QString & str, const QFont & fnt = QFont());
5、获取系统屏幕分辨率
const QRect QDesktopWidget::screenGeometry(int screen = -1) const
其中的参数就是显示器的id,默认是-1,如果是多个显示器,则显示器编号依次为0(主显示器),1,2,3...( 这些编号和设置里看到的编号没有关系)
① 如图,这是目前的显示设置情况,其中标识为2的显示器是主显示器,1则是扩展显示器。而实际上,通过
QDesktopWidget * deskTop = QApplication::desktop(); int curMonitor = deskTop->screenNumber ( this ); // 参数是一个QWidget*
获得到的当前所在屏幕的编号来看,设置中标识为2的实际上是0,标识为1的实际是1。
② 当获取到显示器编号后,就可以通过下面语句来获取当前所在屏幕的分辨率
QRect rect = desktop->screenGeometry(curMonitor);
③ 这时rect.width 和rect.height 就是当前屏幕的分辨率了。而rect.x和rect.y是什么呢?回到上图,可以用上面的函数获取主(编号为2的)显示器rect.x和rect.y,会发现 rect.x=0,rect.y=0 。可见,整个显示器“坐标”是以主显示器左上角为(0,0)点的。在扩展(此处编号为1的)显示器获得到的 rect.x=-1366,rect.y=161说明这个就是那个扩展显示器左上角的坐标了。那么就可以通过这个来计算所需要的屏幕坐标了。
④ 示例:
m_settings->show(); m_settings->raise(); int screenBottom = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_settings)).bottom(); QPoint position = ui->settingsButton->mapToGlobal(QPoint(0, ui->settingsButton->height())); m_settings->move(position); QRect settingsRect = m_settings->geometry(); settingsRect.setHeight(680); if(settingsRect.bottom() > screenBottom ){ int diff = settingsRect.bottom() - screenBottom; settingsRect.setHeight(settingsRect.height() - diff); } m_settings->setGeometry(settingsRect);
6、保存图片
① 将当前场景渲染为像素图
可使用 renderPixmap() 将当前场景渲染为像素图。帧缓冲的内容可使用 grabFrameBuffer() 进行捕获。
renderPixmap() 和 grabFrameBuffer() 的主要差别就是使用 renderPixmap() 时不捕捉叠置。
QPixmap pixmap = ui->orthoDrawWidget->renderPixmap(0, 0, true);
② 初始化图片名为当前时间
QString defaulName = QString("/") + QDateTime::currentDateTime().toString("yyyy_MM_dd_HH_mm_ss_zzz") + ".png";
③ 打开文件保存对话框,并设置图片名
QString filename = QFileDialog::getSaveFileName( this, tr("Save snapshot"), QDir::currentPath() + defaulName, tr("PNG file (*.png)"));
④ 如果图片名不为空,保存图片
if (!filename.isNull()) { QFileInfo fi(filename); QDir::setCurrent(fi.absolutePath()); //设置应用程序的当前工作目录为fi.absolutePath() pixmap.save(filename); }
⑤ 由上,可得
void ViewerPlugin::orthoSnapshot() { //使用renderPixmap() 将当前场景渲染为像素图。 QPixmap pixmap = ui->orthoDrawWidget->renderPixmap(0, 0, true); QString defaulName = QString("/") + QDateTime::currentDateTime().toString("yyyy_MM_dd_HH_mm_ss_zzz") + ".png"; QString filename = QFileDialog::getSaveFileName( this, tr("Save snapshot"), QDir::currentPath() + defaulName, tr("PNG file (*.png)")); if (!filename.isNull()) { QFileInfo fi(filename); QDir::setCurrent(fi.absolutePath()); //设置应用程序的当前工作目录为fi.absolutePath() pixmap.save(filename); } }
7、virtual void print()const = 0;
(1)=0 说明它是纯虚函数
(2)const表明不能修改其数据成员
const和 =0 没有关系,要分开理解。
成员函数后面用 const 修饰,通俗的理解就是在这个函数内不能修改类的成员变量,除非那个成员变量是mutable 的。
=0 表示这个成员函数是纯虚函数,也就是它可以没有定义,只有接口,由它的继承类具体定义它的行为,当然,也可以给它定义缺省的函数体
一个类里如果包含=0 的纯虚函数,那么这个类就是一个抽象类,它不能具体实例化(不能创建它的对象),而只能由它去派生子类。
8、动态加载插件库
Qt 的插件系统中通过 QPluginLoader类来动态加载插件库。
A. QPluginLoader 在后台是通过 QLibraryPrivate类完成加载库操作的,这与 QLibrary 类是一样的;
B. 多个 QPluginLoader 的实例若加载同一个插件库,则其后台的库是同一个,即是说多个 QPluginLoader 的实例并不会导致同一个动态库被多次加载;
C. 在 QPluginLoader 对象被析构时,其加载的动态库也不会被卸载;
D. QPluginLoader 的 load 函数会在执行 instance时自动执行,一般不需要直接执行;
E. 卸载插件需要调用 unload 函数执行,但若有多个实例加载(load)了同一个插件库,那么只有在最后一个实例执行unload后才能将动态库卸载,前几个实例的 unload 方法都会返回 false ,动态库也不会被卸载。
void loadPlugin(CameraPluginStruct& p) { p.pluginLoader = new QPluginLoader(p.filePath); p.pluginLoader->load(); QObject* possiblePlugin = p.pluginLoader->instance(); //QPluginLoader.instance(); if(possiblePlugin) { // cast from QObject to correct type: p.plugin = qobjectcast<CameraPluginInterface>(possiblePlugin); } }
void unloadPlugin(CameraPluginStruct& p) { p.pluginLoader->unload(); // QPluginLoader.unload(); p.pluginLoader->~QPluginLoader(); p.pluginLoader = nullptr; p.plugin = nullptr; }
9、 QSortFilterProxyModel : 排序与过滤
QSortFilterProxyModel是用来排序和过滤的,不能单独使用,它只是一个“代理”,真正的数据需要QAbstractTableModel提供。
QSortFilterProxyModel *sorter = new QSortFilterProxyModel(this); sorter->setSourceModel(m_model); //设置sorter的源模型为m_model m_tableView->setModel(sorter); m_tableView->setSortingEnabled(true); //true,使用排序 sorter->setFilterKeyColumn(0); //设置过滤源模型内容的键的列号 sorter->setFilterRegExp(regExp); //设置过滤源模型的内容regExp
10、void QWidget::raise ()
把这个窗口部件升高到它的父窗口部件的栈的顶部。
如果在屏幕上有与这个窗口部件重叠的兄弟,这个窗口部件将在它后来的这些兄弟之前变的可视了。
11、 安装源码
在安装Qt 的时候有一个选项默认不打勾的,而这个默认不安装的选项就是 Source Components (源码),安装时打上勾就可以安装源码了。安装完后,打开目录 C:\Qt\Qt5.7.0\5.7\Src ,就可以看到源码了。
如 QDialog 源码位置:
12、提升的窗口部件
1)用 Qt Creator 新建一个自定义Widget,如类名自定义为 “ModeSwitcherWidget ”
2)在 Qt Creator 自带的设计师界面中,右键,选择菜单 “提升为...”或“提升的窗口部件”,弹出“提升的窗口部件”界面,在此界面可设置自定义的 Widget 为提升的窗口部件。
3)在 Qt Creator 自带的设计师界面中,选中要提升的普通 Widget ,右键,选择菜单 “提升为” → “自定义的控件”
4)如果想取消该控件的提升,右键,选择菜单 “取消 QWidget 的提升”即可
13、 Qt 运行文件的依赖库
1 > windows 系统下Qt 运行文件的依赖库寻找
系统:Windows 7
Qt构建套件:qt-opensource-windows-x86-mingw530-5.7.0.exe
Qt Creator版本:4.0.2
构建版本:release
A. 一般的应用程序,下面的dll就够了。其中platforms文件夹中是跟平台有关,这里只在windows平台运行,则这个文件夹下放 qwindows.dll就够了
B. QtWidgets Application + QtCreator自带的windeployqt 工具
新建一个文件夹“test”,将release版本的可执行文件“xxx.exe”放到“test”文件夹中,然后单击“开始菜单”—> “所有程序”—>“Qt 5.7.0” —>“Qt5.7”—>“MinGW 5.3.0 (32-bit)”—>“Qt 5.7 for Desktop (MinGW 5.3.0 32bit)”;
在命令窗口输入可执行文件“xxx.exe”路径,然后继续输入“windeployqt xxx.exe”,回车。即可将所有需要的dll动态库文件拷贝到test文件夹中。
C. Qt Quick Application + QtCreator自带的windeployqt 工具
同上(B),只是将使用 windeployqt 工具命令更改为:
windeployqt xxx.exe --qmldir C:\Qt\Qt5.7.0\5.7\mingw53_32\qml
注意:使用 windeployqt工具拷贝的动态库,有时候并不需要那么多动态库,这时候就可以手动删除一些;有时候拷贝的并不全面,即还是有缺失的,这就需要手动去Qt安装路径拷贝,比如 粒子系统、qtcharts图表、webengine等,还有自定义的库或第三方库,也是需要手动拷贝的。
2 > Ubuntu 系统下Qt 运行文件的依赖库寻找
系统:Ubuntu 14.04.5
Qt构建套件:qt-opensource-linux-x86-5.5.1.run
Qt Creator版本:3.5.1
构建版本:release
在Ubuntu下,寻找一个可执行文件运行时所依赖的库文件使用的是 ldd命令。
ldd命令 的作用是打印可执行文件依赖的共享库文件,它是 glibc 的一部分。
root@ubuntu:~# ldd --help
Usage: ldd [OPTION]... FILE...
--help print this help and exit
--version print version information and exit
-d, --data-relocs process data relocations
-r, --function-relocs process data and function relocations
-u, --unused print unused direct dependencies
-v, --verbose print all information
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/eglibc/+bugs>.
root@ubuntu:~#
ldd本身不是一个程序,而仅是一个shell脚本
root@ubuntu:~# which ldd
/usr/bin/ldd
root@ubuntu:~# ls -al /usr/bin/ldd
-rwxr-xr-x 1 root root 5424 May 26 2016 /usr/bin/ldd
root@ubuntu:~# file /usr/bin/ldd
/usr/bin/ldd: Bourne-Again shell script, ASCII text executable
root@ubuntu:~#
在终端输入“ldd + 运行程序”,按下“Enter”,便可查看运行程序的依赖库情况
注意:使用 ldd 命令查看依赖动态库也可能不全面,这就需要去QT的安装目录下手动拷贝(/opt/Qt5.5.1/5.5/gcc/lib,或/opt/Qt5.5.1/5.5/gcc/plugins),其中/opt/Qt5.5.1/5.5/gcc/lib文件一般是拷贝到/lib或者/usr/lib下,/opt/Qt5.5.1/5.5/gcc/plugins中文件与运行文件在同一级目录下,另外,还有自定义的库或第三方库,也是需要手动拷贝的。
14、Qt 动态库路径查找(Ubuntu)
在工程中使用 LIBS+=-Lxx 和 LIBS+=-lxx可以指定动态库和静态库链接文件和路径,但是在运行程序时,对动态库的可能查找不到。
可以使用ldd 命令进行测试验证,是否所有的动态库都已经定位成功,查看方法请看13
动态库路径查找方法优先级如下,:
1 > 编译目标代码时指定的动态库搜索路径; QMAKE_RPATHDIR+=xxx 例如QMAKE_RPATHDIR+=/usr/local/lib ,连接时将使用 -rpath,/usr/local/lib/
2 > 环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径;
3 > DT_RUNPATH 指定的动态库搜索路径(-Wl,--enable-new-dtags);
4 > 配置文档 /etc/ld.so.conf中指定的动态库搜索路径;
添加lib库路径方法如下:
在/etc/ld.so.conf.d加入文件xxx.conf,写入
/usr/lib/qt
同样,执行下列命令使其立即生效
sudo ldconfig
5 > 默认的动态库搜索路径 /lib ;
6> 默认的动态库搜索路径 /usr/lib 。
在上述1、2、4指定动态库搜索路径时,都可指定多个动态库搜索路径,其搜索的先后顺序是按指定路径的先后顺序搜索的。
15、QWidget 关闭时触发的事件
触发关闭事件实际上就是重写 closeEvent() 事件。
当使用者想要关闭窗口的时候,closeEvent()事件被发送给窗口。
//在头文件中加入 protected: void closeEvent(QCloseEvent*event);
然后,在cpp完成closeEvent事件的处理void DeviceDiscoverToolsPlugin::closeEvent(QCloseEvent *event) //此函数在QWidget关闭时执行 { QWidget::closeEvent(event); }
会持续更新...