愤怒的卤蛋 · 政府采购_漯河市人民政府· 2 月前 · |
仗义的斑马 · JPFA官宣召开义卖会资助病故的工藤壮人家属 ...· 5 月前 · |
年轻有为的茄子 · 重磅大奖震撼来袭!宁波喜获(2023)第37 ...· 10 月前 · |
留胡子的硬币 · 《求婚大作战》,张艺兴这棒球该不该打?_百科TA说· 1 年前 · |
微醺的大象 · 名单公布!党的二十大代表全部选出_思想学习_ ...· 1 年前 · |
前言 Windows上mingw32版本的openssl的编译是属于比较棘手的,OpenSSL本身不提供支持.。OpenSSL介绍 OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。 SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。Netscape公司在推出第一个Web浏览器的同时,提出了SSL协议标准。其目标是保证两个应用间通信的保密性和可靠性,可在服务器端和用户端同时实现支持。已经成为Internet上保密通讯的工业标准。 SSL能使用户/服务器应用之间的通信不被攻击者窃听,并且始终对服务器进行认证,还可选择对用户进行认证。SSL协议要求建立在可靠的传输层协议(TCP)之上。SSL协议的优势在于它是与应用层协议独立无关的,高层的应用层协议(例如:HTTP,FTP,TELNET等)能透明地建立于SSL协议之上。SSL协议在应用层协议通信之前就已经完成加密算法、通信密钥的协商及服务器认证工作。在此之后应用层协议所传送的数据都会被加密,从而保证通信的私密性。特点安全信道特性数据保密性 信息加密就是把明码的输入文件用加密算法转换成加密的文件以实现数据的保密。加密的过程需要用到密钥来加密数据然后再解密。没有了密钥,就无法解开加密的数据。数据加密之后,只有密钥要用一个安全的方法传送。加密过的数据可以公开地传送。数据完整性 加密也能保证数据的一致性。例如:消息验证码(MAC),能够校验用户提供的加密信息,接收者可以用MAC来校验加密数据,保证数据在传输过程中没有被篡改过。安全验证 加密的另外一个用途是用来作为个人的标识,用户的密钥可以作为他的安全验证的标识。SSL是利用公开密钥的加密技术(RSA)来作为用户端与服务器端在传送机密资料时的加密通讯协定。 OpenSSL包含一个命令行工具用来完成OpenSSL库中的所有功能,更好的是,它可能已经安装到你的系统中了。 OpenSSL是一个强大的安全套接字层密码库,Apache使用它加密HTTPS,OpenSSH使用它加密SSH,但是,你不应该只将其作为一个库来使用,它还是一个多用途的、跨平台的密码工具。开源特点 Eric A. Young和Tim J. Hudson自1995年开始编写后来具有巨大影响的OpenSSL软件包,这是一个没有太多限制的开放源代码的软件包。Eric A. Young 和Tim J. Hudson是加拿大人,后来由于写OpenSSL功成名就之后就到大公司里赚大钱去了。1998年,OpenSSL项目组接管了OpenSSL的开发工作,并推出了OpenSSL的0.9.1版,到目前为止,OpenSSL的算法已经非常完善,对SSL2.0、SSL3.0以及TLS1.0都支持。 OpenSSL采用C语言作为开发语言,这使得OpenSSL具有优秀的跨平台性能,这对于广大技术人员来说是一件非常美妙的事情,可以在不同的平台使用同样熟悉的东西。OpenSSL支持Linux、Windows、BSD、Mac、VMS等平台,这使得OpenSSL具有广泛的适用性。但习惯C语言总比使用C++重新写一个跟OpenSSL相同功能的软件包轻松不少。功能基本功能 OpenSSL整个软件包大概可以分成三个主要的功能部分:SSL协议库、应用程序以及密码算法库。OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。 作为一个基于密码学的安全开发包,OpenSSL提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。辅助功能 BIO机制是OpenSSL提供的一种高层IO接口,该接口封装了几乎所有类型的IO接口,如内存访问、文件访问以及Socket等。这使得代码的重用性大幅度提高,OpenSSL提供API的复杂性也降低了很多。 OpenSSL对于随机数的生成和管理也提供了一整套的解决方法和支持API函数。随机数的好坏是决定一个密钥是否安全的重要前提。 OpenSSL还提供了其它的一些辅助功能,如从口令生成密钥的API,证书签发和管理中的配置文件机制等等。如果你有足够的耐心,将会在深入使用OpenSSL的过程慢慢发现很多这样的小功能,让你不断有新的惊喜。算法密钥证书管理 密钥和证书管理是PKI的一个重要组成部分,OpenSSL为之提供了丰富的功能,支持多种标准。 首先,OpenSSL实现了ASN.1的证书和密钥相关标准,提供了对证书、公钥、私钥、证书请求以及CRL等数据对象的DER、PEM和BASE64的编解码功能。OpenSSL提供了产生各种公开密钥对和对称密钥的方法、函数和应用程序,同时提供了对公钥和私钥的DER编解码功能。并实现了私钥的PKCS#12和PKCS#8的编解码功能。OpenSSL在标准中提供了对私钥的加密保护功能,使得密钥可以安全地进行存储和分发。 在此基础上,OpenSSL实现了对证书的X.509标准编解码、PKCS#12格式的编解码以及PKCS#7的编解码功能。并提供了一种文本数据库,支持证书的管理功能,包括证书密钥产生、请求产生、证书签发、吊销和验证等功能。 事实上,OpenSSL提供的CA应用程序就是一个小型的证书管理中心(CA),实现了证书签发的整个流程和证书管理的大部分机制。 OpenSSL实现了SSL协议的SSLv2和SSLv3,支持了其中绝大部分算法协议。 OpenSSL也实现了TLSv1.0,TLS是SSLv3的标准化版,虽然区别不大,但毕竟有很多细节不尽相同。 虽然已经有众多的软件实现了OpenSSL的功能,但是OpenSSL里面实现的SSL协议能够让我们对SSL协议有一个更加清楚的认识,因为至少存在两点:一是OpenSSL实现的SSL协议是开放源代码的,我们可以追究SSL协议实现的每一个细节;二是OpenSSL实现的SSL协议是纯粹的SSL协议,没有跟其它协议(如HTTP)协议结合在一起,澄清了SSL协议的本来面目。对称加密 OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种常用的分组密码加密模式。其中,AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。非对称加密 OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用于密钥交换。RSA算法既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也可以用于数据加密。DSA算法则一般只用于数字签名。信息摘要 OpenSSL实现了5种信息摘要算法,分别是MD2、MD5、MDC2、SHA(SHA1)和RIPEMD。SHA算法事实上包括了SHA和SHA1两种信息摘要算法。此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1。下载OpenSSL 官网:http://distfiles.macports.org/openssl/ CSDN:https://download.csdn.net/download/qq21497936/11537079 QQ群:1047134658(点击“文件”搜索“openssl”,群内与博文同步更新)编译OpenSSL安装windows下linux编译环境msys 将qt的mingw和本机的perl拷贝到msys文件夹下,然后添加路径 配置OpenSSL 配置安装路径 此处卡了一个多小时,各种找原因,原来是需要使用msys而不是msys2 修改Makefile 在最上层Makefile找到变量PERL 直接修改如下图: 继续mingw32-make.exe 漫长的等待后,继续报错 仔细看是应用的问题,链接库失败可能是,但是我们需要的 查看编译出的库添加配置参数 其实测试程序编译缺少库是路径包含问题,多次尝试,还是需要config的时候指定下路径./config --prefix=/usr/local --openssldir=/usr/local/openssl编译mingw32-make.exe install -j4 编译成功,编译过程和安装过程都很漫长,估计得二三十分钟 顺利编译,此时为了方便提取库修改配置如下./config --prefix=/home/yang/complie/install \ --openssldir=/home/yang/complie/install/openssl 试几次,有可能会出现错误,多线程导致一些前后依赖的错误mingw32-make.exe install -j4 议最后执行一次:mingw32-make.exe install 成功后如下: 可以测试以下:Mingw32-make.exe test 时间也是非常长。Install文件结构打包 编译出来的是静态库(注意:笔者重头再来一遍,配置时加了shared参数也还是静态库)。 入坑入坑一:Perl调用失败 解决方法 修改顶层Makefile的Perl。 入坑二:配置时操作系统类型错误 解决方法由msys2更换为msys1.0。入坑三:编译时,找不到库定义 解决方法 配置时,需要加2个参数。
前言 西门子PLC、台达PLC、法兰克机床等等多年以前玩得比较多,有tcp/ip通讯也有modbus通讯,modbus又分为网络,485,232等。 医疗项目,焊接机器人项目,工控机床项目,数控项目,物联网项目用的挺多的,将关键的通信技术抽离出来,单独弄成工具。需求 与各种其他行业仪器通讯软件开发的通讯核心模块,modbus功能模块,制作成调试工具,可满足一般情况的调试。 1.支持通过串口232,485端口进行通讯; 2.支持设置打开端口的参数; 3.支持写入bool,int,dInt,real,dReal参数类型数据; 4.支持读取bool,int,dInt,real,dReal参数类型数据; 5.增加10种主题风格切换(仅用于预选择主题风格);Demo 工具下载地址 CSDN(0积分下载):https://download.csdn.net/download/qq21497936/19236703 QQ群:1047134658(点击“文件”搜索“plcModbus ”,群内与博文同步更新)十种主题风格切换 相关头文件源码PlcModbusMasterWidget.h#ifndef PLCMODBUSMASTERWIDGET_H #define PLCMODBUSMASTERWIDGET_H #include <QWidget> #include <QThread> #include <QDateTime> #include <QElapsedTimer> #include <QHash> #include <QFile> #include <QMessageBox> #include <QAbstractButton> #include "ModbusManager.h" namespace Ui { class PlcModbusMasterWidget; class PlcModbusMasterWidget : public QWidget Q_OBJECT public: explicit PlcModbusMasterWidget(QWidget *parent = 0); ~PlcModbusMasterWidget(); protected slots: void slot_opened(bool opened); void slot_readBitsResult(bool result, int startAddr, QList<bool> listBool); void slot_readIntsResult(bool result, int startAddr, QList<int> listInt); void slot_readDIntsResult(bool result, int startAddr, QList<int> listInt); void slot_readRealsResult(bool result, int startAddr, QList<float> listFloat); void slot_readDRealsResult(bool result, int startAddr, QList<double> listDouble); void slot_writeBitsResult(bool result, int startAddr, QList<bool> listBool); void slot_writeIntsResult(bool result, int startAddr, QList<int> listInt); void slot_writeDIntsResult(bool result, int startAddr, QList<int> listInt); void slot_writeRealsResult(bool result, int startAddr, QList<float> listFloat); void slot_writeDRealsResult(bool result, int startAddr, QList<double> listDouble); private slots: void on_comboBox_writeType_currentIndexChanged(int index); void on_lineEdit_readStartAddr_textChanged(const QString &arg1); void on_lineEdit_writeStartAddr_textChanged(const QString &arg1); void on_lineEdit_readStartAddrHex_textChanged(const QString &arg1); void on_lineEdit_writeStartAddrHex_textChanged(const QString &arg1); protected slots: void slot_buttonClicked(int index); private slots: void on_pushButton_open_clicked(); void on_pushButton_close_clicked(); void on_pushButton_read_clicked(); void on_pushButton_write_clicked(); void on_pushButton_clearM_clicked(); private: Ui::PlcModbusMasterWidget *ui; QThread *_pModbusManagerThread; QElapsedTimer _elapsedTimer; QHash<int, QString> _hashInt2Str; #endif // PLCMODBUSMASTERWIDGET_H ModbusManager.h#ifndef MODBUSMANAGER_H #define MODBUSMANAGER_H #include <QObject> #include <QMutex> class ModbusManager : public QObject Q_OBJECT private: explicit ModbusManager(QObject *parent = 0); public: bool testEnvAndRtu(); public: static ModbusManager *getInstance(); public: void setPortName(const QString &portName); void setBaud(int baud); void setParity(char parity); void setDataBit(int dataBit); void setStopBit(int stopBit); void setTimeOutMs(int timeOutMs); void setSlaveAddr(int slaveAddr); public: QString getPortName() const; int getBaud() const; char getParity() const; int getDataBit() const; int getStopBit() const; int getTimeOutMs() const; int getSlaveAddr() const; signals: void signal_opened(bool opened); void signal_readBitsResult(bool result, int startAddr, QList<bool> listBool); void signal_readIntsResult(bool result, int startAddr, QList<int> listInt); void signal_readDIntsResult(bool result, int startAddr, QList<int> listInt); void signal_readRealsResult(bool result, int startAddr, QList<float> listFloat); void signal_readDRealsResult(bool result, int startAddr, QList<double> listDouble); void signal_writeBitsResult(bool result, int startAddr, QList<bool> listBool); void signal_writeIntsResult(bool result, int startAddr, QList<int> listInt); void signal_writeDIntsResult(bool result, int startAddr, QList<int> listInt); void signal_writeRealsResult(bool result, int startAddr, QList<float> listFloat); void signal_writeDRealsResult(bool result, int startAddr, QList<double> listDouble); public slots: void slot_start(); void slot_stop(); void slot_open(); void slot_close(); void slot_readBits(int startAddr, int size); void slot_readInts(int startAddr, int size); void slot_readDInts(int startAddr, int size); void slot_readReals(int startAddr, int size); void slot_readDReals(int startAddr, int size); void slot_writeBits(int startAddr, QList<bool> listBool); void slot_writeInts(int startAddr, QList<int> listInt); void slot_writeDInts(int startAddr, QList<int> listInt); void slot_writeReals(int startAddr, QList<float> listFloat); void slot_writeDReals(int startAddr, QList<double> listDouble); private: static ModbusManager *_pInstance; static QMutex _mutex; private: QString _portName; int _baud; char _parity; int _dataBit; int _stopBit; int _timeOutMs; int _slaveAddr; private: bool _running; bool _opened; #endif // MODBUSMANAGER_H
前言 stm32系列是最常用的单片机之一,不同的版本对应除了引脚、外设、频率、容量等’不同之外,其开发的方法是一样的。 本章讲解使用GPIO引脚功能驱动LED灯和接收Key按钮输入。STM32系列GPIO驱动LED灯 先来笔者根据自己使用的开发板的电路来使用GPIO进行LED操作,下图是笔者使用的开发板LED灯的电路图: 引脚PD6接LED1,PD12接LED2,PD13接LED3,电阻是限流电阻(计算方式高电平减去LED1的压降,然后除以LED能流过的电流)。 复制模版文件,更改名字为LEDtest1,启动软件Keil4,打开改名后的工程LEDtest1。 在工程目录下新建文件夹Dev,在Dev下新建文件夹LED,在LED下新建led.c和led.h文件,然后将路径以及文件部署进去: 部署成功后,我们工程如下: 然后开始编写程序,mian.c,led.c, led.h,编写好后的程序内容如下: 程序主要逻辑如下:打开LED1,延迟,打开LED2,延迟,打开LED3,延迟,关闭LED1 LED2 LED3,延迟,回头循环开始。LED的工程代码在CSDN下载 CSDN下载地址:https://download.csdn.net/detail/qq21497936/7998805 QQ群免费下载:1047134658(点击“文件”搜索“LEDtest1”,群内与博文同步更新)STM32系列GPIO检测按键KEY现在我们来使用GPIO进行按键操作,按键最为常用的输入,大多数以及笔者接触到的经验人士都是建议笔者采用轮询(查询)方式。下图是笔者开发板的按键部分的电路图: 从电路图分析PE0,PE1,PE2,PE3,PE4这5个引脚未按键时是带有上拉电阻的高电平,按键时有2个10K的电阻进行分压,为1.65V查看芯片电平的电气特性,你会发现低于高电平最低的电压,输入尽管有电压但仍然是低电平,PC13则只有上拉电阻,至于为什么会这样笔者暂时也不太清楚,那么我们复制LEDtest1的工程,改名为KEYtest1,然后继续开始按键编写,还是按照流程来,在Dev文件夹下建立KEY文件夹,在KEY文件夹下建立key.h,key.c两个文件都部署进工程,路径包括进去。 我们继续来使用帮助文档进行参考,版本是V3.5(若未指明V3.4则是V3.5,建议使用文档的时候两个版本的都备好),打开下面这个源文件 我们想象一下,与LEDtest1的GPIO配置为输出,那么按键要配置成输入,配置成什么输入呢(大家可以参考八种IO模式),这里我们为初学者考虑,尽量只依靠帮助文档,所以我们继续使用帮助文档来编写,配置成输入也有一个初始化,于是在源代码中我们查找,看下图 00067行是对按钮进行初始化,我们点击这个函数跳转到源代码 再点击255查看源代码 00257大家都知道,00258则是配置中断的详细信息(怎么样才产生中断),00259则是将中断与中断向量联系起来(可以配置优先级和中断响应函数),我们不使用中断不管后面中断这两行,继续往下走 00265这是配置成浮空输入,我们想这应该是我们想要的(不管对错,暂时先这样),继续往下走 00316这个读输入数据的位,我们点开,以转到它的说明 这样我们知道它主要是用来判断哪个端口的哪个引脚现在的值,输入的值不是0就是1,可以写检测代码了,继续写代码,写完的代码如下: 调试运行成功。并且笔者在GPIO的模式上,配置了上拉,下拉,浮空输入,都运行正常,包括UESR按键也正常。
需求 常常在Qt中需要引入windows函数。方法步骤一:引入windows的api头文件:#include <windows.h>步骤二: 引入windows的dll文件user32.dll 在pro中添加:LIBS += -luser32步骤三:添加windows代码查找窗户口HWND hDesktop, hTask; hDesktop = ::FindWindow(L"ProgMan",NULL); hTask = ::FindWindow(L"Shell_TrayWnd",NULL); // 隐藏任务栏/桌面 ::ShowWindow(hTask,SW_HIDE); // 隐藏桌面 ::ShowWindow(hDesktop,SW_HIDE);显示任务栏/桌面HWND hDesktop, hTask; hDesktop=FindWindow(L"ProgMan",NULL); hTask=FindWindow(L"Shell_TrayWnd",NULL); // 显示任务栏 ::ShowWindow(hTask,SW_SHOW); // 显示桌面 ::ShowWindow(hDesktop,SW_SHOW);
前言 本文章开始讲解如何定制使用Qt开发安装界面的Nsis安装包只制作原理。注意点 Qt用于做界面,逻辑可以先做,但是按钮的逻辑在 NSIS插件源码中将会是ui.调用,所以逻辑也会需要移植过去。插件工程布局介绍 整体工程采用的是插件形式 Qt程序的入口 其实就是类似于dll调用,将Qt的调用放入到NSIS插件里面(笔者:msvc2017x32版本): Qt程序与NSIS的交互:Qt调用NSIS 在Nsis中需要关联插件中(nsis插件代码)的函数. $0~$9 和 R 0 R0~R0 R9 是 NSIS 中内置的变量,不用声明直接使用。 $0是回调好函数,临时存储地址:Qt程序与NSIS的交互:NSIS设置Qt 插件中的NSISAPI函数,将安装路径设置到Qt中: Qt程序与NSIS的交互:NSIS获取Qt设置的安装路径 Qt程序与NSIS的交互:NSIS通过 Qt参数执行不同函数 在Qt部分的代码中查看到执行该事件 在插件代码中查看到预定义的事件代码 在NSIS脚本中查看到该关键字 (补充说明:以 $ 开头的还有一些内置的表示路径或句柄等变量或常量,比如 H W N D P A R E N T 、 HWNDPARENT、HWNDPARENT、PROGRAMFILES、I N S T D I R 、 INSTDIR、INSTDIR、EXEDIR、$WINDIR 等。)。Demo安装过程 开始菜单的最近安装 开始菜单对应文件夹 桌面快捷方式
前言 Qt使用一些压缩解压功能,探讨过libzip库,zlib库,libzip库比较原始,还有其他库,都比较基础,而在基础库之上,又有高级封装库,Qt中的QuaZIP是一个很好的选择。 本文主要详解QuaZIP。QuzZip介绍 QuaZIP是Gilles Vollant的ZIP / UNZIP软件包的简单C ++包装,可用于访问ZIP档案。依赖库:zlib库 Qt 4无论如何都依赖于zlib,但是您将需要zlib标头来编译QuaZIP。使用Qt5有时,您还需要zlib库(例如,在Windows上)。支持平台 QuaZIP当前已在以下平台上进行了测试:linux-g ++(Ubuntu 11.10,Qt 4.7.4)freebsd-g ++(Qt 4.0.0hpux-acc(HP-UX 11.11)hpux-g ++(HP-UX 11.11)win32-g ++(MinGW)win32-msvc2010(MS VS 2010 Express,Qt 4.8.4)win32-msvc2010(Qt Creator,Qt 5.0.1)win32-msvc2012(Qt Creator,Qt 5.2.0)目标平台:windows Qt5.9.3 msvc2015x86编译zlip 参考文章《zlib开发笔记(一):zlib库介绍、编译和工程模板》。下载QuaZIP 官方:http://quazip.sourceforge.net QQ群下载地址:1047134658(点击“文件”搜索“quazip”,群内与博文同步更新)编译QuaZIP库步骤一:下载解压 步骤二:CMake配置configure 步骤三:修改Qt版本 步骤四:添加zlib库 步骤五:CMake生成 工程 步骤六:使用Qtcreator打开quazip源码pro文件 上图加入zlib库的路径,然后编译。模块化 Demo#include <QApplication> #include "QuaZibManager.h" #include <QDebug> #define LOG qDebug()<<__FILE__<<__LINE__ int main(int argc, char *argv[]) QApplication a(argc, argv); QuaZibManager quaZibManager; QStringList list = quaZibManager.getZipFileList("testFile.zip"); for(int index = 0; index < list.size(); index++) LOG << list.at(index); return a.exec(); }Demo结果 工程模板 quaZipDemo_v1.0.0_基础模板_基础环境.rar
前言 经常见的错误,今天又遇到,记录下。问题 CMake编译出出现错误“Could not find compiler set in environment variable RC:”。 如下图: 解决方法 直接修改CMakeList.txt:# add by yang set(CMAKE_RC_COMPILER "Ninja") 如下图:
前言 Nsis可以使用duilib也可以使用qt界面,笔者主要qt,本文章梳理nsis+qt制作安装包的基本流程。下载Nsis-Ui-Plugin插件 Github地址:https://github.com/sway913/NSIS-UI-Plugin QQ群下载地址:1047134658(点击“群文件”搜索“nsis”,群内与博文同步更新)预先准备 Qt+VS的编译环境,建议VS2015x86或者VS2017x86,一定要是32位版本的,默认就是32位,不支持64位的,后续编译nsis插件尝试过64位版本,卡了挺久,解决了蛮多问题,但是没有成功,不死磕了。 编译环境:Qt5.13.1的msvc2017x86版本 + vs2017。 以上配环境对于老手来说也是有点费时间的,请自己百度,此处非本文重点。编译Nsis-Ui-Plugun步骤一:打开工程 步骤二:编译出现“”Qt version xxxxxx” 设置一下,如下图: 步骤三:再次编译 以上是编译过程,编译完成了。步骤四:确认编译出的插件 使用Nsis插件步骤一:添加软件环境变量 两个环境变量,一个是NSIS_DIR,一个是QTDIR。 安装的Nsis或者绿色的都行,如下图(笔者对软件重新打包整理了一整套文档流程): 步骤二:将编译的插件的release版本插件拷贝 将编译出来的relase插件拷贝到软件的Plugins/x86-unicode下,此处备份一下最原始的,每次使用时就copy一份吧。 (PS:用的是插件提供的qt版本的脚本,名字肯定不能改变,脚本中必定有对应的)。步骤三:启动软件 步骤四:打开脚本 (可以看看脚本,有些东西的学习还是有必要的,比如应用名称什么的可以与与Qt进行交互信息达到通过Qt来控制nsis脚本实现最终各种安装目的)。步骤五:开始编译脚本 然后,加载脚本 步骤六:运行提供的Demo安装包 步骤七:检查是否安装成功 部署发布的应用 经测试,脚本只会安装卸载,修改应用名称和生成快捷方式,具体的文件copy等其他功能并未实现,所以需要读者自己用脚本实现了。
前言 做产品时,定制的自定义安装界面常有的,使用NSIS + Qt可以完美的定制基于QT的安装界面,先从纯NSIS开始,制作常规的安装包。应用程序的发布方式 应用程序发布的时候,具备以下两种方式:静态编译:把相关联的库一并引入可执行程序,虽然发布简单,编译出来只有一个exe文件。(特别注意:编译时,其依赖的库也需要使用静态包)。动态编译:把相关联的库以dll的形式提供(linux下是.so)引入,不被包含进可执行程序,发布不方便,但可执行程序较小。预先准备工具Qt应用需要先打包,使用windeployqt,建议打包后到无环境的对应系统的虚拟机上尝试。具体直接略,不会的请百度。 Windows下安装与卸载安装 在windows下,很多程序运行起来,会有一系列安装,勾选用户协议,自定义的安装界面,安装之后对应的路径放置应用的程序文件,创建开始菜单文件夹,放置桌面快捷方式,任务栏也可能有固定图标, 以上情况,安装包就需要单独定制了,如Qt的安装包,其他产品的安装包: 以上Qt的界面确实不太漂亮,漂亮的界面是需要美工做主题的,怀疑Qt公司没有ui设计参与。 还有很多其他安装界面: 卸载 卸载界面也可以定制,当然会增加一定的工作量,如下图: NSIS软件 Nsis其实是使用一种脚本语言了,学习成本肯定是不低的。 采用NSIS + QT 制作安装程序实际上就是使用QT制作安装程序,而NSIS仅仅将制作的安装程序打包成一个exe。下载 下载地址:https://nsis.sourceforge.io/Download安装 NSIS使用向导生成安装包 可勾选用户协议,可选择安装路径,并且在开始菜单和桌面创建图标。步骤一:启用应用,打开脚本编辑器 一般需要用到的就是“编译NSI脚本”和“脚本编辑器(VNISEdit)”。 步骤二:新建向导脚本(自带内置) 使用向导基本进行建立,可满足常规的一些应用安装过程: 生成了脚本: 保存为脚本: 至此,可以关闭脚本编辑器了(注意:最好留着,后边边调试脚本边编译测试)。步骤三:编译NISI脚本 切到主界面,打开NSI脚本编译器,对脚本进行编译: 加载脚本: 加载之中(copy文件等操作): 加载完成: 步骤四:测试安装程序 向导生成的安装过程: 步骤五:测试成功 步骤六:测试卸载 (注意:图标出来了,这个地方前面需要再调试,因为前面的图标没有出,读者自己调试吧,挺费时间的)。
前言 视频监控、人脸识别等应用中经常使用到摄像头,当前占据主流视频监控摄像头就是海康和大华两家,都可通过自家的sdk或者是onvif方式使用和控制摄像头。 本文章讲解海康的sdk方式。海康 海康(海康威视)是以视频为核心的智能物联网解决方案和大数据服务提供商,在视频行业是当前实打实的老大哥,当然还有大华,其他不多做介绍。海康设备网络SDK下载 下载地址:https://www.hikvision.com/cn/download_61.html 在ubuntu16.04 x86_64上开发,下载SDK_Linux64版本,可查看详细描述,右上角下载: 点击下载: 解压后: 海康威视SDK自带QtDemo,不过是qt4.7版本的,笔者使用qt5版本。海康SDK概述与使用流程初始化SDK 海康sdk有其固有的使用流程,如下图: 初始化SDK(NET_DVR_Init) 对整个网络SDK系统的初始化,内存预分配等。设置连接超时时间(NET_DVR_SetConnectTime)可选 设置SDK中的网络连接超时时间,不调用则使用默认值。异常回调函数(NET_DVR_SetDVRMessage或NET_DVR_SetExceptionCallBack_V30) sdk中大部分模块的功能是异步异常,海康提供此接口用于接收预览、报警、回放、透明通道和语音对讲等模块发生异常信息。用户可以在初始化 SDK 后就设置该回调函数,在应用层对各个模块异常消息的接收和处理。从解析服务器获得设备的 IP 地址(NET_DVR_GetDVRIPByResolveSvr_EX) 该接口提供一种在仅知道设备名称(或 DDNS 域名)或者序列号的情况下,从解析服务器获得设备 IP 地址的方法。如:当前设备是通过拨号上网方式获取到动态 IP 地址,而运行了我公司 IPServer 软件的服务器即为解析服务器或者设备注册到我公司 DDNS 服务器上,我们可以通过此接口输入服务器的地址、设备的名称或序列号等信息查询该设备的 IP 地址。(注意:由此看来不能达到没有任何配置的情况下,直接使用该函数搜索到局域网内的所有摄像头信息)。用户注册设备(NET_DVR_Login_V30) 实现用户的注册功能,注册成功后,返回的用户 ID 作为其他功能操作的唯一标识, SDK 允许最大注册用户数为 512 个。就设备而言, V3.0 以上版本支持的设备允许有 32 个注册用户名,而且同时最多允许 128 个用户注册; V3.0 以下版本支持的设备允许有 16 个注册用户名,而且同时最多允许 128 个用户注册。 登录后才可进行功能其他功能的调用(除了报警模块不需要登录)。释放SDK(NET_DVR_Cleanup) 不再使用sdk后,释放其使用的资源。SDK功能模块 预览模块 从设备取实时码流,解码显示以及播放控制等功能,同时支持软解码和解码卡解码。回放和下载模块 可以通过按时间和按文件名的方式远程回放或者下载设备的录像文件,后续可以进行解码或者存储。同时还支持断点续传功能(需要设备支持)。参数配置模块 设置和获取设备的参数,主要包括设备参数、网络参数、通道压缩参数、串口参数、报警参数、异常参数、交易信息和用户配置等参数信息。远程设备维护模块 实现关闭设备、重启设备、恢复默认值、远程硬盘格式化、远程升级和配置文件导入/导出等维护工作。语音对讲转发模块 语音对讲转发模块:实现和设备的语音数据对讲和语音数据获取,音频编码格式可以指定。报警模块 报警模块:处理设备上传的各种报警信号。报警分为“布防”和“监听”两种方式,在采用监听方式并且不 需要获取用户 ID 的情况下,报警模块可以无需进行“用户注册”操作步骤。透明通道模块 透明通道模块:透明通道是将 IP 数据报文解析后直接发送到串行口的一种技术。实际上起到了延伸串行设备控制距离的作用。可利用 IP 网络控制多种串行设备,如控制解码器、矩阵、报警主机、门禁、仪器仪表等串行设备,对用户来说,只看到点对点传输,无须关心网络传输过程,所以称为串口透明通道。SDK提供485和232串口作为透明通道功能,其中要将 232 串口作为透明通道使用,首先必须在232串口的配置信息(NET_DVR_RS232CFG)中将工作模式选为透明通道,这样232串口才可作为透明通道使用。云台控制模块 云台控制模块:实现对云台的基本操作、预置点、巡航、轨迹和透明云台的控制。SDK将云台控制分为两种模式:一种是通过图像预览返回的句柄进行控制;另一种是无预览限制,通过用户注册ID号进行云台控制。IP通道概念与相关说明模拟输入 DVR 视频输入接模拟摄像机,其通道称为模拟通道; 混合型 DVR、 NVR 等设备支持 IPC 接入,通道称IP 通道(或者数字通道),配置相关参数时需调用 IP 接入配置参数来进行资源的获取和重新分配。模拟通道个数 客户端通过注册设备(NET_DVR_Login_V30)返回的设备信息 NET_DVR_DEVICEINFO_V30 获取模拟通道个数(byChanNum)、模拟通道起始通道号(byStartChan)和设备支持的最大 IP 通道数(byIPChanNum + byHighDChanNum * 256)、数字通道起始通道号(byStartDChan)。通道号 从 byStartChan 到 byStartChan + byChanNum - 1 对应为模拟通道的通道号,IP 通道的通道号为 byStartDChan到 byStartDChan + (byIPChanNum + byHighDChanNum * 256) - 1。 DVR 只有模拟通道, NVR 只有 IP 通道,混合型 DVR 同时支持模拟通道和 IP 通道。单设备的多IP通道 如果设备支持 IP 通道个数大于 0,则可以通过远程参数配置接口 NET_DVR_GetDVRConfig(配置命令:NET_DVR_GET_IPPARACFG_V40)可以获取得到设备详细的 IP 资源信息(NET_DVR_IPPARACFG_V40),包括模拟通道是否禁用(byAnalogChanEnable)、 IP 通道个数(dwDChanNum)、 IP 通道起始通道号(dwStartDChan)、 IP 通道取流模式、 IP 通道有效状态和在线状态等。通过远程参数配置接口NET_DVR_SetDVRConfig(配置命令: NET_DVR_SET_IPPARACFG_V40)可对设备进行 IP 资源配置,包括添加、修改、删除 IP 通道等。报警 混合型 DVR 或 NVR 的 IP 报警输入和报警输出的通道是在音视频 IP 通道资源分配好后,由设备自动分配的。 如果要对 IP 报警参数进行配置,首先通过命令 NET_DVR_GET_IPALARMINCFG_V40 和NET_DVR_GET_IPALARMOUTCFG_V40 获取 IP 报警输入资源(NET_DVR_IPALARMINCFG_V40) 和 IP 报警输出资源(NET_DVR_IPALARMOUTCFG_V40)。 然后通过命令 NET_DVR_SET_ALARMINCFG_V40 可以配置报警数相关参数(NET_DVR_ALARMINCFG_V40),包括报警输入名称、报警器类型、布防时间、联动方式等,通过命令 NET_DVR_SET_ALARMOUTCFG_V30 可以配置报警输出相关参数(NET_DVR_ALARMOUTCFG_V30),比如报警输出名称、布防时间、输出报警延时等。 相关接口:NET_DVR_GetDVRConfig、 NET_DVR_SetDVRConfig。
前话 Qt中的拽拖操作详细介绍。Demo图片拽拖 控件拽拖 窗口拽拖 拽托框架(高级开发) 拖放(Drag and Drop) 拖放提供了一种简单的可视机制,用户可以使用它在应用程序之间和内部传输信息。拖放的功能类似于剪贴板的剪切和粘贴机制。 本文档描述了基本的拖放机制,并概述了在自定义控件中启用该机制的方法。许多qt的控件也支持拖放操作,例如项目视图和图形视图框架,以及为qt小部件和qt quick编辑控件。有关项目视图和图形视图的详细信息,请参见使用项目视图和图形视图框架的拖放。拖放类 这些类处理拖放和必要的mime类型编码和解码。 配置 QStyleHints对象提供了一些与拖放操作相关的属性:QStyleHints::startDragTime():描述在开始拖动之前,用户必须在对象上按住鼠标按钮的时间量(毫秒)。QStyleHints::StartDragDistance():表示在移动被解释为拖动之前,按住鼠标按钮时用户必须移动鼠标的距离。QStyleHints::StartDragVelocity():表示用户移动鼠标开始拖动的速度(以像素/秒为单位)。值为0表示没有这样的限制。 如果在控件中提供拖放支持,这些数量将提供与基础窗口系统兼容的合理默认值,供您使用。在Qt Quick种的拖放 文档的其余部分主要关注如何在C++中实现拖放。要在Qt快速场景中使用拖放,请阅读Qt Quick拖放、DragEvent和DropArea项的文档,以及Qt快速拖放示例。拖曳(Dragging) 要开始拖动,请创建一个QDrag对象,并调用其exec()函数。在大多数应用程序中,只有在按下鼠标按钮并移动光标一定距离后,才能开始拖放操作。但是,启用小部件拖动最简单方法是重新实现小部件的mousePressEvent(),并启动拖放操作: 尽管用户可能需要一些时间来完成拖动操作,但就应用程序而言,exec()函数是一个带有多个值之一的阻塞函数。这些说明操作是如何结束的,下面将详细介绍。 注意,exec()函数不会阻塞主事件循环。 对于需要区分鼠标单击和拖动的小部件,重新实现小部件的mousePressEvent()函数以记录拖动的开始位置是很有用的: 稍后,在mouseMoveEvent()中,我们可以确定是否应该开始拖动,并构造一个拖动对象来处理该操作: 这种特殊的方法使用QPoint::manhattanlength()函数粗略估计鼠标单击位置和当前光标位置之间的距离。此函数以精度换取速度,通常适用于此目的。放下(Dropping) 要能够接收小部件上丢弃的媒体,请为小部件调用setAcceptDrops(true),并重新实现dragEnterEvent()和dropEvent()事件处理程序函数。例如,以下代码启用了QWidget子类的构造函数中的Drop事件,从而可以有效地实现Drop事件处理程序: dragEnterEvent()通常用于通知qt小部件接受的数据类型。如果要在DragMoveEvent()和dropEvent()的重新实现中接收QDragMoveEvent或QDropEvent,则必须重新实现此函数。报错 下面的代码显示如何重新实现DragEnterEvent(),以告诉拖放系统我们只能处理纯文本: dropEvent()用于解包丢弃的数据,并以适合您的应用程序的方式对其进行处理。 在以下代码中,事件中提供的文本将传递给QTextBrowser,QComboBox将填充用于描述数据的mime类型列表: 在这种情况下,我们接受建议的操作,而不检查它是什么。在实际应用程序中,可能需要从dropEvent()函数返回,而不接受建议的操作,或者在操作不相关的情况下处理数据。例如,如果我们不支持到应用程序中外部源的链接,我们可以选择忽略Qt::LinkAction操作。覆盖提议的行动 也可以忽略提议的操作,并对数据执行其他操作。为此,我们将在调用accept()之前使用Qt::dropAction中的首选操作调用事件对象的setDropAction()。这样可以确保使用替换删除操作而不是建议的操作。对于更复杂的应用程序,重新实现dragMoveEvent()和dragLeaveEvent()将使小部件的某些部分对放置事件敏感,并使您能够更好地控制应用程序中的拖放。复杂小部件的子类化 某些标准Qt小部件为拖放提供了自己的支持。在对这些小部件进行子类化时,除了DragCenterEvent()和DropEvent()之外,可能还需要重新实现DragMoveEvent(),以防止基类提供默认的拖放处理,并处理您感兴趣的任何特殊情况。拖放操作 在最简单的情况下,拖放操作的目标将接收正在拖动的数据的副本,源将决定是否删除原始数据。这由CopyAction操作描述。目标还可以选择处理其他操作,特别是MoveAction和LinkAction操作。如果源调用QDrag::exec(),并返回MoveAction,则如果源选择删除任何原始数据,则该源将负责删除。不应删除源小部件创建的QMimeData和QDrag对象-它们将被Qt销毁。 目标负责获取在拖放操作中发送的数据的所有权;这通常通过保留对数据的引用来实现。 如果目标理解LinkAction操作,它应该存储自己对原始信息的引用;源不需要对数据执行任何进一步的处理。拖放操作的最常见用法是在同一个小部件中执行移动;有关此功能的详细信息,请参阅有关拖放操作的部分。 拖动操作的另一个主要用途是在使用引用类型(如text/uri-list)时,其中拖动的数据实际上是对文件或对象的引用。添加新的拖放类型 拖放不限于文本和图像。任何类型的信息都可以在拖放操作中传输。要在应用程序之间拖动信息, 应用程序必须能够相互指示可以接受哪些数据格式以及可以生成哪些数据格式,这是通过使用mime类型实现的。 由源构造的QDrag对象包含一个用于表示数据的mime类型列表(从最合适的到最不合适的顺序排列),drop目标使用其中一个来访问数据。对于常见的数据类型,便利函数处理透明使用的mime类型,但是对于自定义数据类型,必须显式地声明它们。 要对QDrag便利功能未涵盖的信息类型执行拖放操作,第一步也是最重要的一步是查找适当的现有格式:Internet分配号码管理局(IANA)在信息科学研究所(ISI)提供了MIME媒体类型的分层列表。使用标准的mime类型可以最大限度地提高应用程序与其他软件现在和将来的互操作性。要支持其他媒体类型,只需使用setData()函数设置QMimeData对象中的数据,提供完整的mime类型和以适当格式包含数据的QByteArray。以下代码从标签中获取QPixmap,并将其存储为QMimeData对象中的可移植网络图形(PNG)文件: 对于这种情况,我们可以简单地使用setImageData()来提供各种格式的图像数据: 在这种情况下,QByteArray方法仍然很有用,因为它可以更好地控制QMimeData对象中存储的数据量。请注意,在项视图中使用的自定义数据类型必须声明为元对象,并且必须实现它们的流运算符。放下动作 在剪贴板模型中,用户可以剪切或复制源信息,然后粘贴它。同样,在拖放模型中,用户可以拖动信息的副本,也可以将信息本身拖动到新位置(移动信息)。拖放模型对于程序员来说还有一个额外的复杂之处:在操作完成之前,程序不知道用户是否想要剪切或复制信息。在应用程序之间拖动信息时,这通常没有什么区别,但在应用程序中,检查使用了哪个放置操作是很重要的。 可以为一个小部件重新实现mouseMoveEvent(),并通过可能的拖放操作组合启动拖放操作。例如,可能希望确保拖动始终移动小部件中的对象: 如果信息被放到另一个应用程序中,exec()函数返回的操作可能默认为copyAction,但是如果信息被放到同一个应用程序中的另一个小部件中,我们可能会获得不同的drop操作。可以在小部件的dragMoveEvent()函数中筛选建议的放置操作。但是,可以接受DragEnterEvent()中所有建议的操作,并让用户稍后决定要接受哪个操作: 当小部件中发生放置时,将调用DropEvent()处理程序函数,我们可以依次处理每个可能的操作。首先,我们在同一个小部件中处理拖放操作: 在这种情况下,拒绝处理移动操作。接受的每种类型的跌落动作都会进行相应的检查和处理: 注意,在上面的代码中检查了单独的放置操作。如上所述,在覆盖建议的操作部分,有时需要覆盖建议的删除操作,并从可能的删除操作中选择不同的操作。为此,需要检查事件的possibleActions()提供的值中是否存在每个操作,使用setDropAction()设置Drop操作,并调用accept()。矩形下落 小部件的dragMoveEvent()可用于通过仅在光标位于这些区域内时接受建议的放置操作来限制小部件的某些部分的放置。例如,当光标位于子小部件(DropFrame)上时,以下代码接受任何建议的放置操作: 如果您需要在拖放操作期间提供视觉反馈、滚动窗口或任何适当的操作,也可以使用DragMoveEvent()。剪切板 应用程序还可以通过将数据放在剪贴板上进行通信。要访问这个,您需要从QApplication对象获取一个QClipboard对象。 QMimedata类用于表示在剪贴板中传输的数据。要将数据放在剪贴板上,可以使用setText()、setImage()和setPixmap()方便函数来处理常见的数据类型。这些函数与在QMimedata类中找到的函数类似,只是它们还带有一个控制数据存储位置的附加参数:如果指定了剪贴板,则数据将放置在剪贴板上;如果指定了选择,则数据将放置在鼠标选择中(仅在x11上)。默认情况下,数据放在剪贴板上。例如,我们可以使用以下代码将QLineEdit的内容复制到剪贴板: 具有不同mime类型的数据也可以放在剪贴板上。构造一个qmimedata对象,并使用setData()函数按照前面部分描述的方式设置数据;然后可以使用setmimedata()函数将该对象放到剪贴板上。QClipboard类可以通过其dataChanged()信号通知应用程序它所包含的数据的更改。例如,我们可以通过将此信号连接到小部件中的插槽来监视剪贴板: 连接到此信号的插槽可以使用可用于表示该信号的MIME类型之一读取剪贴板上的数据: selectionChanged()信号可用于x11以监视鼠标选择。与其他应用程序互操作 在x11上,使用公共XDND协议,而在Windows Qt上使用OLE标准,而Qt for MacOS使用Cocoa拖动管理器。在x11, XDND使用MIME,因此不需要翻译。无论平台如何,QT API都是相同的。在Windows上,支持MIME的应用程序可以使用MIME类型的剪贴板格式名称进行通信。一些Windows应用程序已经为其剪贴板格式使用了MIME命名约定。 用于转换专用剪贴板格式的自定义类可以通过在Windows上重新实现QwinMime或在MacOS上重新实现QMacPasteboardMime来注册。
前言 本文章讲解libmodbus。libModbus介绍 libmodbus是一个免费软件库,可根据Modbus协议发送/接收数据。该库用C编写,并支持RTU(串行)和TCP(以太网)通信。编译:平台windows + Qt5.9.3 + mingw32步骤一:下载 https://github.com/stephane/libmodbus QQ群下载地址:1047134658(点击“文件”搜索“modbus”,群内与博文同步更新)步骤二:使用msys编译,配置好环境 步骤三:命令行引入mingw32环境变量export PATH=$PATH:/mingw530_32/bin步骤四:配置configurecd /home/21497/compile/modbus tar xvf libmodbus-3.1.6.tar.gz cd libmodbus-3.1.6 ./configure --prefix=/home/21497/compile/modbus/libmodbus-3.1.6/install 错误,识别平台失败,如下图: ./configure --prefix=/home/21497/compile/modbus/libmodbus-3.1.6/install -build=x86 是在mysy使用linux环境编译x86构架下的,如下图: 步骤五:编译makemake -j16 再单线程确认一下 步骤六:安装make installmake install 会出错,缺一些文件夹,手动自己建文件夹即可。 步骤七:读者请稍微核对下文件 模块化 Demobool ModbusManager::testEnvAndRtu() LOG << LIBMODBUS_VERSION_STRING; // 步骤一:创建modbus RTU modbus_t *pModbus = 0; pModbus = modbus_new_rtu("com5", 115200, 'E', if(!pModbus) LOG << "Failed to modbus_new_rtu"; return false; LOG << "Succeed to modbus_new_rtu"; // 步骤二: 485 RTU 模式 modbus_rtu_set_serial_mode(pModbus, MODBUS_RTU_RS485); // 步骤三: 设置从机站号 1 modbus_set_slave(pModbus, 1); // 步骤四:设置超时时间 100 ms modbus_set_response_timeout(pModbus, 0, 100 * 1000); // 步骤五: 连接 (注意:经过测试,只是485和232只是打开串口,并未交互) int ret = modbus_connect(pModbus); if(ret) LOG << "Failed to modbus_connect, ret =" << ret; return false; LOG << "Succeed to modbus_connect, ret =" << ret; // 步骤六:读取线圈 uint8_t buffer8t[10] = {0x00}; ret = modbus_read_bits(pModbus, 25, 10, buffer8t); if(ret <= 0) LOG << "Failed to modbus_read_registers, ret =" << ret; return false; LOG << "Succeed to modbus_read_registers, ret =" << ret; // 步骤七:打印返回 for(int index = 0; index < 10; index++) LOG << QString("%1").arg(buffer8t[index]); // 步骤八:读取寄存器 uint16_t buffer16t[10] = {0x00}; ret = modbus_read_registers(pModbus, 95, 10, buffer16t); if(ret <= 0) LOG << "Failed to modbus_read_registers, ret =" << ret; return false; LOG << "Succeed to modbus_read_registers, ret =" << ret; // 步骤九:打印返回 for(int index = 0; index < 10; index++) LOG << QString("%1").arg(buffer16t[index]); // 步骤十:读取寄存器 memset(buffer16t, 0, 10); ret = modbus_read_input_registers(pModbus, 100, 1, buffer16t); if(ret <= 0) LOG << "Failed to modbus_read_registers, ret =" << ret; return false; LOG << "Succeed to modbus_read_input_registers, ret =" << ret; // 步骤十一:打印返回 for(int index = 0; index < 10; index++) LOG << QString("%1").arg(buffer16t[index]); return true; }Demo演示 工程模板 modbusDemo_v1.0.0_基础模板_读取线圈_读取寄存器简单测试.rar
前言 西门西PLC、台达触摸屏、法兰克机床等等多年以前玩得比较多,改造机床、维修机床、给机床编程等等,没事还能扯个零件啥的,之前也没总结过,有时间就重新整理下。 本章后面以西门1200实物为例,下载一个基本程序。 相关博客 《案例分享:Qt西门子PLC调试模拟工具(包含PLC上位机通讯,PLC服务器,读写Byte、Int、DInt、Real)(持续更新,当前v1.5.0)》 《西门子PLC开发笔记(一):PLC介绍,西门子S1200系列接线、编程、下载和仿真》 《台达PLC开发笔记(一):台达PLC连接介绍,分别使用485、网口与台达PLC建立连接》PLC 玩得比较多的就是西门PLC,单个模块就是3K起,一个24V电源也是3K,不是土豪真心玩不起。国产机床用的比较多的就是三菱PLC、台达触摸屏这些,技术过硬,主要也是便宜点,兼容性也强。PLC的发展历程 在工业生产过程中,大量的开关量顺序控制,它按照逻辑条件进行顺序动作,并按照逻辑关系进行连锁保护动作的控制,及大量离散量的数据采集。传统上,这些功能是通过气动或电气控制系统来实现的。1968年美国GM(通用汽车)公司提出取代继电气控制装置的要求,第二年,美国数字公司研制出了基于集成电路和电子技术的控制装置,首次采用程序化的手段应用于电气控制,这就是第一代可编程序控制器,称Programmable Controller(PC)。 个人计算机(简称PC)发展起来后,为了方便,也为了反映可编程控制器的功能特点,可编程序控制器定名为Programmable Logic Controller(PLC)。 上世纪80年代至90年代中期,是PLC发展最快的时期,年增长率一直保持为30~40%。在这时期,PLC在处理模拟量能力、数字运算能力、人机接口能力和网络能力得到大幅度提高,PLC逐渐进入过程控制领域,在某些应用上取代了在过程控制领域处于统治地位的DCS系统。 PLC具有通用性强、使用方便、适应面广、可靠性高、抗干扰能力强、编程简单等特点。PLC在工业自动化控制特别是顺序控制中的地位,在可预见的将来,是无法取代的。PLC的构成 从结构上分,PLC分为固定式和组合式(模块式)两种。固定式PLC包括CPU板、I/O板、显示面板、内存块、电源等,这些元素组合成一个不可拆卸的整体。模块式PLC包括CPU模块、I/O模块、内存、电源模块、底板或机架,这些模块可以按照一定规则组合配置。CPU的构成 CPU是PLC的核心,起神经中枢的作用,每套PLC至少有一个CPU,它按PLC的系统程序赋予的功能接收并存贮用户程序和数据,用扫描的方式采集由现场输入装置送来的状态或数据,并存入规定的寄存器中,同时,诊断电源和PLC内部电路的工作状态和编程过程中的语法错误等。进入运行后,从用户程序存贮器中逐条读取指令,经分析后再按指令规定的任务产生相应的控制信号,去指挥有关的控制电路。 CPU主要由运算器、控制器、寄存器及实现它们之间联系的数据、控制及状态总线构成,CPU单元还包括外围芯片、总线接口及有关电路。内存主要用于存储程序及数据,是PLC不可缺少的组成单元。 在使用者看来,不必要详细分析CPU的内部电路,但对各部分的工作机制还是应有足够的理解。CPU的控制器控制CPU工作,由它读取指令、解释指令及执行指令。但工作节奏由震荡信号控制。运算器用于进行数字或逻辑运算,在控制器指挥下工作。寄存器参与运算,并存储运算的中间结果,它也是在控制器指挥下工作。 CPU速度和内存容量是PLC的重要参数,它们决定着PLC的工作速度,IO数量及软件容量等,因此限制着控制规模。I/O模块 PLC与电气回路的接口,是通过输入输出部分(I/O)完成的。I/O模块集成了PLC的I/O电路,其输入暂存器反映输入信号状态,输出点反映输出锁存器状态。输入模块将电信号变换成数字信号进入PLC系统,输出模块相反。I/O分为开关量输入(DI),开关量输出(DO),模拟量输入(AI),模拟量输出(AO)等模块。常用的I/O分类如下:开关量:按电压水平分,有220VAC、110VAC、24VDC,按隔离方式分,有继电器隔离和晶体管隔离。模拟量:按信号类型分,有电流型(4-20mA,0-20mA)、电压型(0-10V,0-5V,-10-10V)等,按精度分,有12bit,14bit,16bit等。除了上述通用IO外,还有特殊IO模块,如热电阻、热电偶、脉冲等模块。按I/O点数确定模块规格及数量,I/O模块可多可少,但其最大数受CPU所能管理的基本配置的能力,即受最大的底板或机架槽数限制。电源模块 PLC电源用于为PLC各模块的集成电路提供工作电源。同时,有的还为输入电路提供24V的工作电源。电源输入类型有:交流电源(220VAC或110VAC),直流电源(常用的为24VDC)。底板或机架 大多数模块式PLC使用底板或机架,其作用是:电气上,实现各模块间的联系,使CPU能访问底板上的所有模块,机械上,实现各模块间的连接,使各模块构成一个整体。PLC系统的其它设备 编程设备:编程器是PLC开发应用、监测运行、检查维护不可缺少的器件,用于编程、对系统作一些设定、监控PLC及PLC所控制的系统的工作状况,但它不直接参与现场控制运行。小编程器PLC一般有手持型编程器,目前一般由计算机(运行编程软件)充当编程器。也就是我们系统的上位机。 人机界面:最简单的人机界面是指示灯和按钮,目前液晶屏(或触摸屏)式的一体式操作员终端应用越来越广泛,由计算机(运行组态软件)充当人机界面非常普及。PLC的通信联网 依靠先进的工业网络技术可以迅速有效地收集、传送生产和管理数据。因此,网络在自动化系统集成工程中的重要性越来越显著,甚至有人提出"网络就是控制器"的观点说法。 PLC具有通信联网的功能,它使PLC与PLC之间、PLC与上位计算机以及其他智能设备之间能够交换信息,形成一个统一的整体,实现分散集中控制。多数PLC具有RS-232接口,还有一些内置有支持各自通信协议的接口。PLC的通信现在主要采用通过多点接口(MPI)的数据通讯、PROFIBUS 或工业以太网进行联网。硬件设备西门子电源(220VAC转24VDC) 西门子S1200 接线 L与N就无所谓,220VAC正负无所谓。 PLC下有网口,接入到PC机局域网内。S7-1200PLC编程软件下载安装软件 编程电脑用普通的网线即可。 安装的是: Step7是必选的,其他看着吧,去掉wincc,这是触摸屏组态的,笔者只是需要连接和编程PLC。 时间会突然小于1分钟,提示重启,弄了好多次,发现不是正常重启,要删除注册表项:计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager 以上项的PendingFileRemameOpeaations键值(注意:是重启后,立马打开注册表,安装程序运行的时候回自己建立,所以一直刷注册表,等出现了该项,就立马删除!!!),通过以上操作,就真正开始安装了。 安装完成后,如下图: 设备连接 西门子PLC下面有2个网口,将网口连接到PC机同一网段即可。 经过后面论证,2个网口插哪一个都是一样的,可能是西门子为了接设备方便,多机串联,省路由器。开始运行查找设备 (注意:双网口,插左边的网口扫描) (注意:双网口,插右边的网口扫描) 查看设备并连接设备 点击后发现,PLC没有设置自己的地址,反倒是把上位机PC的ip地址添加了PLC网段的了(此时,PC以太网设置上面还是显示自动获取),如下图: S7-1200项目测试编程新建项目 添加设备 编程添加DB块下载到设备 (注意:开始下载失败,是因为组态部件问题,需要清空组态,不然显示组态少了部件,无法正常运行,且error灯一直闪)S7-PLC仿真软件 安装完成后如下图,必选现状STEP 7 V15. 接下来,读者可以自己创仿真项目了。
前话 使用到Qt的视图框架。Qt视图框架介绍简介 图形视图框架(The Graphic View Framework)用于管理和与大量定制的二维图形项目交互,以及用于可视化项目的视图小部件,支持缩放和旋转。 该框架包括一个事件传播体系结构,允许对场景中的项目进行精确的双精度交互。项目可以处理按键事件、鼠标按下、移动、释放和双击事件,还可以跟踪鼠标移动。 图形视图使用BSP(Binary Space Partitioning,即二进制空间分区)树提供非常快读得项目发现,因此,它可以实时现实大型场景,即使有数百万个项目。 图形视图提供了一种基于项目得模型视图变成方法,多个视图可以观察单个场景,并且场景包含不同几何图形的项目。场景(The Scene) QGraphicsScene提供了图形视图场景,场景有如下职责:为管理大量项目(图元项目)提供快速界面;(实测同一个区域不能重叠多了,绘制会卡顿)将事件传播到每个项;管理项目状态,如选择和焦点处理;提供未转换的渲染功能;主要用于打印; 该场景用作QGraphicsItem对象的容器。通过调用QGraphicsItem::additem() 将项添加到场景中,然后通过调用多个项发现函数之一来检索项。QGraphicsItem::items()及其重载返回由点、矩形、多边形或常规矢量路径包含或与之相交的所有项。QGraphicsItem::itemAt()返回特定点的最上面的项。所有项目发现功能都按降序堆叠顺序返回项目(即第一个返回的项目是最上面的,最后一个项目是最下面的)。QGraphicsScene scene; QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)) QTransform transform;; QGraphicsItem *item = scene.itemAt(50, 50, transform); // item == rect QGraphicsScene的事件传播体系结构安排将场景事件传递到项目,并管理项目之间的传播。如果场景在某个位置接收到鼠标按下事件,则场景将事件传递到该位置的任何项目。 QGraphicsScene还管理某些项状态,例如项选择和焦点。可以通过调用QGraphicsScene::setSelectionArea(),传递任意形状来选择场景中的项目。该功函数还可用作QGraphicsView中橡皮擦的选择区域。要获取所有当前选定项的列表,请调用QGraphicscene::selecteditems()。QGraphicsScene处理的另一个状态是项是否具有键盘输入焦点。可以通过调用QGraphicScene::setFocusItem()或 QGraphicsItem::setFocus()对项设置焦点,也可以通过调用QGraphicscene::focusItem()获取当前焦点项。 最后,QGraphicScene允许您通过QGraphicScene::render()函数将部分场景渲染到绘制设备中。可以“打印”部分了解更多有关此内容的信息。视图(The View) QGraphicsView提供了视图小部件,它可以可视化场景的内容。可以将多个视图附加到同一场景中,以便在同一数据集中提供多个视口。视图小部件是一个滚动区域,并提供滚动条用于在大型场景中导航。要启用OpenGL支持,可以通过调用QGraphicsView::setViewport()将QGLWidget设置为视区。QGraphicsScene scene; myPopulateScene(&scene); QGraphicsView view(&scene); view.show(); 在将事件发送到可视化场景之前,视图从键盘和鼠标接收输入事件,并将其转换为场景事件(在适当的情况下将使用的坐标转换为场景坐标)。 用转换矩阵QGraphicsView::transform(),视图可以转换场景的坐标系。这允许高级导航功能,如缩放和旋转。为了方便起见,qgraphicsView还提供了在视图和场景坐标之间转换的函数:QGraphicsView::mapToScene()和 QGraphicsView::mapFromScene()。 项目(The Item):图形元素QGraphicsItem是场景中图形项的基类。图形视图为典型形状提供了几个标准项,例如矩形(QGraphicsRectItem)、椭圆(QGraphicsEllipsItem)和文本项(QGraphicsTextItem),但在编写自定义项时,最强大的QGraphicsItem功能可用。除此之外,QGraphicsItem还支持以下功能:鼠标按下、移动、释放和双击事件,以及鼠标悬停事件、滚轮事件和上下文菜单事件;键盘输入焦点和按键事件;拖放;分组,通过父子关系,通过QGraphicsItemGroup;碰撞检测; 项目位于本地坐标系中,与QGraphicsView类似,它还提供许多功能,用于在项目和场景之间以及从项目到项目之间映射坐标。此外,与QGraphicsView一样,它可以使用矩阵:QGraphicsItem::Transform()转换其坐标系。这对于旋转和缩放单个项目很有用。 项可以包含其他项(子项)。父项的转换由其所有子项继承。但是,不管一个项的累积转换如何,它的所有函数(例如,QGraphicsItem::contains()、QGraphicsItem::boundingRect()、QGraphicsItem::collectsWith() 仍在本地坐标中操作。 QGraphicsItem支持通过QGraphicsItem::shape()函数和QGraphicsItem::collipswith() 进行冲突检测,这两个函数都是虚拟函数。通过从QGraphicsItem::shape() 中返回项目的形状作为本地坐标QPaineterPath,QGraphicsItem将为您处理所有冲突检测。但是,如果您希望提供自己的碰撞检测,则可以重新实现QGraphicsItem::CollipsWith()。 Qt图形视图框架中的类 这些类为创建交互式应用程序提供了一个框架。 图形视图坐标系 图形视图基于笛卡尔坐标系;场景中项目的位置和几何图形由两组数字表示:X坐标和Y坐标。使用未转换视图观察场景时,场景中的一个单元由屏幕上的一个像素表示。 注意:由于图形视图使用qt坐标系,因此不支持倒Y轴坐标系(Y向上增长)。 图形视图中有三个有效的坐标系**:项目坐标、场景坐标和视图坐标**。为了简化实现,图形视图提供了方便的功能,允许您在三个坐标系之间进行映射。 渲染时,图形视图的场景坐标对应于QPainer的逻辑坐标,视图坐标与设备坐标相同。后续会说明逻辑坐标和设备坐标之间的关系。 项目坐标 项目在自己的本地坐标系中。它们的坐标通常以中心点(0,0)为中心,这也是所有变换的中心。项目坐标系中的几何基元通常称为项目点、项目线或项目矩形。 在创建自定义项时,只需要担心项坐标;QGraphicsScene和QGraphicsView将为您执行所有转换。这使得实现自定义项非常容易。例如,如果收到一个鼠标按下或拖动输入事件,则事件位置在项目坐标中给出。QGraphicsItem::contains()虚函数,如果某个点在项中,则返回true,否则返回false,在项坐标中接受一个点参数。类似地,项的边界矩形和形状位于项坐标中。 在项目的位置是项目中心点在其父坐标系中的坐标;有时称为父坐标。在这个意义上,场景被视为所有无父项的“父项”。顶层项目的位置在场景坐标中。 子坐标是相对于父坐标的。如果子坐标未转换,则子坐标和父坐标之间的差异与父坐标中项目之间的距离相同。例如:如果未转换的子项精确定位在其父项的中心点,则两个项的坐标系将相同。但是,如果子对象的位置是(10,0),子对象的(0,10)点将对应于其父对象的(10,10)点。 因为项的位置和转换是相对于父项的,所以子项的坐标不受父项的转换的影响,尽管父项的转换隐式转换子项。在上面的例子中,即使父对象被旋转和缩放,子对象的(0,10)点仍然对应于父对象的(10,10)点。但是,相对于场景,子对象将遵循父对象的变换和位置。如果缩放父对象(2x,2x),子对象的位置将位于场景坐标(20,0),其(10,0)点将对应于场景上的点(40,0)。 由于QGraphicsItem::pos()是少数例外之一,因此QGraphicsItem的函数在项坐标中操作,而不考虑项或其任何父项的转换。例如,项目的边界矩形(即QGraphicsItem::boundingRect())总是在项目坐标中给出。场景坐标 场景表示其所有项的基础坐标系。场景坐标系描述了每个顶层项目的位置,也构成了从视图传递到场景的所有场景事件的基础。场景中的每个项目都有一个场景位置和边界矩形(QGraphicsItem::scenePos()和 QGraphicsItem::sceneBoundingRect()),除了其本地项pos和边界矩形之外。场景位置描述了项目在场景坐标中的位置,其场景边界矩形构成了QGraphicsScene如何确定场景的哪些区域已更改的基础。场景中的更改通过QGraphicsScene::changed()信号进行通信,参数是场景矩形的列表。视图坐标 视图坐标是小部件的坐标。视图坐标中的每个单元对应一个像素。这个坐标系的特殊之处在于它相对于小部件或视区,并且不受观察到的场景的影响。QGraphicsView的视区的左上角始终是(0,0),右下角始终是(视区宽度,视区高度)。所有鼠标事件和拖放事件最初都作为视图坐标接收,您需要将这些坐标映射到场景,以便与项目交互。坐标映射 在处理场景中的项目时,通常可以将坐标和任意形状从场景映射到项目、从项目映射到项目或从视图映射到场景。例如,在QGraphicsView的视区中单击鼠标时,可以通过调用QGraphicsView::mapToScene(),然后调用QGraphicsScene::ItemAt()来询问场景光标下的项目。如果要知道某个项在视区中的位置,可以对该项调用QGraphicsItem::MapToScene(),然后在视图上调用QGraphicsView::MapFromSecene()。最后,如果要查找视图椭圆中的项目,可以将QPaineterPath传递给mapToScene(),然后将映射的路径传递给QGraphicScene::items()。 通过调用QGraphicsItem::MapToScene()和QGraphicsItem::mapFromScene(),可以将坐标和形状映射到项的场景或从中映射。还可以通过调用QGraphicsItem::mapTopParent()和qgraphicsItem::mapFromParent()映射到项的父项,或者通过调用QGraphicsItem::MapToItem()和QGraphicsItem::mapFromItem()在项之间映射。所有映射函数都可以映射点、矩形、多边形和路径。 视图中有相同的映射函数,可用于映射到场景或从场景映射到场景。QGraphicsView::mapFromSecene()和QGraphicsView::mapToScene()。要从视图映射到项目,首先映射到场景,然后从场景映射到项目。关键特征缩放和旋转 QGraphicsView支持与QPainer通过QGraphicsView::setMatrix()进行的相同的仿射转换。通过对视图应用转换,您可以轻松地添加对常见导航功能(如缩放和旋转)的支持。以下是如何在QGraphicsView子类中实现缩放和旋转插槽的示例:class View : public QGraphicsView Q_OBJECT public slots: void zoomIn() { scale(1.2, 1.2); } void zoomOut() { scale(1 / 1.2, 1 / 1.2); } void rotateLeft() { rotate(-10); } void rotateRight() { rotate(10); } }; 槽函数可以连接到启用自动重复的QToolButtons。 转换视图时,QGraphicsView保持视图中心对齐。 有关如何实现基本缩放功能的代码,后续会有示例描述。项目组 通过使一个项目成为另一个项目的子项目,您可以实现项目分组最基本的特性:项目将一起移动所有转换都从父项目传播到子项目。 此外,QGraphicsItemGroup是一个特殊的项,它将子事件处理与用于向组中添加和删除项的有用接口结合在一起。将项添加到QGraphicsItemGroup将保留该项的原始位置和转换,而通常重新设置项将导致子项相对于其新父项重新定位自身。为了方便起见,可以通过调用QGraphicScene::CreateItemGroup()通过场景创建QGraphicsItemGroups。小部件和布局Qt4.4通过QGraphicsWidget引入了对几何和布局感知项的支持。这个特殊的基项类似于QWidget,但与QWidget不同,它不是从QPaintDevice继承的,而是从QGraphicsItem继承的。这允许您编写带有事件、信号和槽、大小提示和策略的完整小部件,还可以通过QGraphicsLinearLayout和QGraphicsGridLayout在布局中管理小部件的几何图形。QGraphicsWidget 基于QGraphicsItem的功能和精简的占地面积,QGraphicsWidget提供了两个方面的最佳功能:QWidget的额外功能,例如样式、字体、调色板、布局方向及其几何图形,以及QGraphicsItem的分辨率独立性和转换支持。因为图形视图使用实坐标而不是整数,所以QGraphicsWidget的几何函数也在QRectF和QPointF上运行。这也适用于框架矩形、边距和间距。例如,对于QGraphicsWidget,指定内容页边距(0.5、0.5、0.5、0.5)并不少见。您可以创建子窗口和“顶级”窗口;在某些情况下,您现在可以为高级MDI应用程序使用图形视图。 一些QWidget的属性是受支持的,包括窗口标志和属性,但不是全部。参考QGraphicsWidget的类文档,以全面了解什么是受支持的,什么是不受支持的。例如,可以通过将Qt::window标志传递给QGraphicsWidget的构造函数来创建装饰窗口,但图形视图当前不支持MacOs上常见的Qt::Sheet和Qt:: Drawer标志。QGraphicsLayout QGraphicsLayout是专门为QGraphicsWidget设计的第二代布局框架的一部分。它的API与QLayout非常相似。您可以在QGraphicsLinearLayout和QGraphicsGridLayout中管理小部件和子布局。您还可以通过自己对QGraphicsLayout子类化来轻松地编写自己的布局,或者通过编写QGraphicsLayoutItem的适配器子类,将自己的QGraphicsItem项添加到布局中。嵌入式小部件支持 图形视图为在场景中嵌入任何小部件提供无缝支持。您可以嵌入简单的小部件,如QLineEdit或QPushButton,复杂的小部件,如QTabWidget,甚至完整的主窗口。要将小部件嵌入到场景中,只需调用QGraphicScene::AddWidget(),或创建QGraphicsProxyWidget实例手动嵌入小部件。 通过QGraphicsProxyWidget,图形视图能够深入集成客户端小部件的功能,包括其光标、工具提示、鼠标、平板电脑和键盘事件、子小部件、动画、弹出窗口(如QComboBox或QCompeter),以及小部件的输入焦点和激活。QGraphicsProxyWidget甚至集成了嵌入式小部件的选项卡顺序,这样您就可以在嵌入式小部件中插入和取出选项卡。甚至可以将新的QGraphicsView嵌入到场景中,以提供复杂的嵌套场景。 当转换嵌入的小部件时,图形视图确保小部件独立地转换分辨率,允许字体和样式在放大时保持清晰。(请注意,分辨率独立性的效果取决于样式。)性能浮点指令 为了准确、快速地对项目应用转换和效果,在假设用户的硬件能够为浮点指令提供合理性能的前提下,构建了图形视图。 许多工作站和台式计算机都配备了适当的硬件来加速这种计算,但是一些嵌入式设备可能只提供库来处理数学运算或模拟软件中的浮点指令。 因此,某些类型的影响在某些设备上可能比预期的慢。可以通过在其他区域进行优化来补偿这种性能损失;例如,使用OpenGL渲染场景。但是,如果这些优化还依赖于浮点硬件的存在,那么它们本身可能会导致性能降低。
问题 使用QOpenGLWidget窗口崩溃。问题源码#include <QApplication> #include <QWidget> #include <QOpenGLWidget> int main(int argc, char *argv[]) QApplication a(argc, argv); QOpenGLWidget w; w.show(); return a.exec(); }解决 添加设置opengl版本的源码,修改后源码如下:#include <QApplication> #include <QWidget> #include <QOpenGLWidget> int main(int argc, char *argv[]) QApplication a(argc, argv); QSurfaceFormat format; // format.setDepthBufferSize(24); // format.setStencilBufferSize(8); format.setVersion(4, 3); // 关键是这一句,设置opengl版本号 // format.setProfile(QSurfaceFormat::CoreProfile); QSurfaceFormat::setDefaultFormat(format); QOpenGLWidget w; w.show(); return a.exec(); }测试成功
需求 开发基于osg的三维点云引擎模块。 1.基于x,y,z坐标轴。 2.可设置原点,设置缩放比例。 3.可设置y轴和z轴单位。 4.三轴中,XY为2D图的水平、竖直方向;Z轴,对应高度图中的double型高度。 5.引擎中心可设置。 6.可设置引擎中心点,可以拽拖绕中心点旋转模型。 7.可以单独以引擎中心点绕X,Y,Z轴旋转,拽拖时旋转. 8.可以组合XY,XZ,YZ轴旋转,拽拖时旋转。 9.根据输入的bmp图片以及建模的txt高度文件,呈现点云。 10.可复位坐标系,可清除导入的点云。 11.点云成面功能。 12.可动态调整中心点和相机视口点坐标。附赠功能: 13.支持导入图片,随机高度进行点云模拟。 14.支持导入cvs点云文件(当前仅解析点)。体验下载地址 CSDN免积分下载地址:https://download.csdn.net/download/qq21497936/16388051 QQ群下载地址:1047134658(点击“文件”搜索“osg3D”,群内与博文同步更新)Demo v2.1.0(2021年04月09日补充) Demo v2.0.0 头文件源码#ifndef OSGWIDGET_H #define OSGWIDGET_H #include <QWidget> #include "OsgViewerWidget.h" #include "MyManipulator.h" class AnimationPathCameraMainpulator; namespace Ui { class OsgWidget; class OsgWidget : public QWidget Q_OBJECT public: explicit OsgWidget(QWidget *parent = 0); ~OsgWidget(); public: bool getFixXAxis() const; // 获取X轴固定状态 bool getFixYAxis() const; // 获取Y轴固定状态 bool getFixZAxis() const; // 获取Z轴固定状态 void getCenter(double &x, double &y, double &z); // 获取引擎中心点坐标 void getPersonPoint(double &x, double &y, double &z); // 获取初始化人眼的角度(看向引擎中心点) public: void setFixXAxis(bool fixXAxis); // 设置固定X轴 void setFixYAxis(bool fixYAxis); // 设置固定Y轴 void setFixZAxis(bool fixZAxis); // 设置固定Z轴 void setCenter(double x, double y, double z); // 设置引擎中心点坐标 void setPersonPoint(double x, double y, double z); public: bool loadFile(QString imageFile, int minZ, int maxZ); bool loadFile(QString imageFile, float z); bool loadFile(QString imageFile, QString cloudZFile, bool bSurface = false); bool loadFile(QString cvsFile, QColor color); void clear(); void resetCoordinate(); protected: void initOsg(); // osg初始化 void loadNode(osg::ref_ptr<osg::Node> pNode); // 加载场景根节点 protected: osg::ref_ptr<osg::Node> create3DPointCloud(); // 创建总场景 osg::ref_ptr<osg::Node> createAxisAndGrid(); // 创建坐标轴和线格 osg::ref_ptr<osg::Node> createTickLabel(); // 创建坐标轴的tickLabel和单位 osg::ref_ptr<osg::Node> createCloud(std::vector<osg::Vec3> &vectorVec3Vectex, std::vector<osg::Vec4> &vectorVec4VectexColor); // 创建点云 osg::ref_ptr<osg::Node> createCloudSurface(std::vector<osg::Vec3> &vectorVec3Vectex, std::vector<osg::Vec4> &vectorVec4VectexColor); // 创建点云面 protected: void resizeEvent(QResizeEvent *event); void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); void mouseDoubleClickEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void wheelEvent(QWheelEvent* event); private: Ui::OsgWidget *ui; private: OsgViewerWidget *_pViewer; // osg场景嵌入Qt核心类 osg::ref_ptr<osg::MatrixTransform> _pRoot; // osg场景根节点 private: float _xDistance; // x轴单个tick间距 int _xTickNumber; // x轴tick数(例如:5的时候,是6个,0~5) float _yDistance; // y轴单个tick间距 int _yTickNumber; // y轴tick数(例如:5的时候,是6个,0~5) float _zDistance; // z轴单个tick间距 int _zTickNumber; // z轴tick数(例如:5的时候,是6个,0~5) QString _zUnit; // z轴单位 float _zTickLabelOffset; // z轴坐标偏移 QString _yUnit; // y轴单位 float _zTickUnitLabelOffset; // z轴坐标偏移 QColor _gridColor; // 轴颜色 QColor _labelColor; // 轴tickLabel的颜色 osg::ref_ptr<osg::Node> _pNode; // 模型 osg::ref_ptr<MyManipulator> _pManipulator; // 自定义漫游器 osg::Vec3d _eyeVect3D; // 原始坐标,用于复位原始视角 osg::Vec3d _centerVect3D; // 原始坐标,用于复位原始视角 osg::Vec3d _upVect3D; // 原始坐标,用于复位原始视角 #endif // OSGWIDGET_H
需求 云服务器类似于一台具备公网ip和端口的独立电脑,若需要当作服务器收集梳理数据的话,需要开放对外端口。本篇文章基于阿里云服务器。Demo (2021年04月03日补充websocket云端json设备数据查询与采集)相关博客 《Qt开发技术:QWebSocket客户端、服务端介绍与开发》 《Qt开发技术:mqtt介绍、QtMqtt编译和开发环境搭建》 《项目实战:Qt并发服务器通讯,受同一时刻最大线程数限制(笔者本本同一时刻600多)》 《项目实战:Qt多人聊天室程序(在线、离线、离线信息再次登录后发送等)》操作步骤步骤一:登录 步骤二:选择需要配置的云服务器 步骤三:配置安全组规则 步骤四(关键步骤):添加端口 注意端口类型,授权对象 然后可以用websocket测试用例进行测试,测试工具免费下载,请查看博文:《Qt开发技术:QWebSocket客户端、服务端介绍与开发》或者直接下载测试。
问题1 一直C#工程使用System.Console.WriteLine有输出,突然今天没有了。 可使用问题1解决方法也可以直接查看问题2解决方法,建议选择合适的。问题1解决方法 绕开,没必要死磕,更换为System.Diagnostics.Debug.WriteLine(...) (注意:有可能还是不输出,那么就不是这个问题了,需要修改配置,看问题2)问题2 按照问题1处理后,还是没有输出,那么考虑是工程本身的问题。问题2解决 去掉勾选后,System.Console.WriteLine正常打印了,如下图:
错误D:\qtProject\sabaDemo\sabaDemo\modules\sabaManager\SabaManager.cpp:8: error: C2039: “shared_ptr”: 不是“std”的成员 引入C++11后还是不行。解决 请引入C++11后包含头文件#include <memory>
前言 Saba模型加载器,demo使用的glfw和dx11,所以需要自己手动创建框架,现在要内嵌入Qt中,本章先接力编译saba。Saba简介 一个开源的3D模型加载器。 编译saba之前需要先编译bullet和glfw,未提供的请自行百度。 编译Bullet库步骤一:下载解压 Github:https://github.com/bulletphysics/bullet3 CSDN粉丝免积分下载:https://download.csdn.net/download/qq21497936/16083901 QQ群:1047134658(点击“文件”搜索“bullet”,群内与博文同步更新) 步骤二:CMake配置 配置要调按下图调整下: 步骤三:CMake生成工程 步骤四:VS2015 WIN64编译 步骤五:vs2015win64 releae版本和debug版本分别编译 步骤六:生成的库截图出来以便后续需要 编译Saba库步骤一:下载解压 Github:https://github.com/benikabocha/saba 粉丝免积分下载:https://download.csdn.net/download/qq21497936/16083902 QQ群:1047134658(点击“文件”搜索“saba”,群内与博文同步更新)步骤二:CMake配置 缺少Bullet库,添加后继续: 去掉这个,不然会卡glfw处,如下图: 步骤三:生成工程 步骤四:VS2015 WIN64编译 经过论证是版本问题,需要规定一下版本,bullet3-3.06,所以更改版本后,红胖子又重新走一遍。步骤五:编译成功 命令行测试 读者可以自己找个模型。simple_mmd_viewer_glfw.exe -model kizunaai/kizunaai.pcm 模块化(2021年04月03日补充) 测试运行(2021年04月03日补充) 工程模板(2021年04月03日补充) sabaDemo_v1.0.0_基础模板_saba环境配好.rar
需求 做嵌入式设备,需求九宫格图片资源浏览器: 1.设置根目录; 2.可拖动; 3.可设置列数与行数; 4.点击文件夹可以进入文件夹; 5.点击图片可以浏览图片; 6.支持触摸屏上下拽拖浏览; 7.支持长安出现类似手机更多的操作,用于选择多个图片项做其他操作; 8.可设置文件排序规则,如大小,更新时间,创建时间等等;Demo 下载体验地址 CSDN粉丝免积分下载:https://download.csdn.net/download/qq21497936/15993722 QQ群:1047134658(点击“文件”搜索“browser”,群内与博文同步更新)头文件源码 v1.5.1 #ifndef MULTIMEDIABROSWERWIDGET_H #define MULTIMEDIABROSWERWIDGET_H #include <QWidget> #include <QDir> #include <QElapsedTimer> #include <QTimer> #include <QLine> #ifdef designer #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include <QtDesigner/QDesignerExportWidget> #else #include <QtUiPlugin/QDesignerExportWidget> #endif class QDESIGNER_WIDGET_EXPORT MultimediaBroswerWidget : public QWidget #else class MultimediaBroswerWidget : public QWidget #endif Q_OBJECT public: enum SORT_TYPE { SORT_TYPE_FILE_NAME_ASC = 0x00, // 文件名升序(默认) SORT_TYPE_FILE_NAME_DES, // 文件名降序序 SORT_TYPE_MODIFY_TIME_ASC, // 文件修改时间升序 SORT_TYPE_MODIFY_TIME_DES, // 文件修改时间降序 SORT_TYPE_SIZE_ASC, // 文件大小升序 SORT_TYPE_SIZE_DES // 文件大小降序 public: explicit MultimediaBroswerWidget(QWidget *parent = 0); public: QString getRootDirPath() const; // 获取当前设置的根目录路径 QString getCurrentDirPath() const; // 获取当前所在的目录路径 QStringList getNameFilters() const; // 获取文件名过滤列表 QPixmap getBackgroundPixmap() const; // 获取背景图片 QPixmap getSelectedPixmap() const; // 获取选择状态的按钮图片 QPixmap getUnSelectedPixmap() const; // 获取非选择状态的按钮图片 QRect getSelectRect() const; // 获取选择按钮的区域 int getSelectRightMargin() const; // 获取选择按钮的右边间距 int getSelectBottomMargin() const; // 获取选择按钮的底部边距 bool getLongPressed() const; // 获取是否是长按选择后的多选状态 bool getSelectAll() const; // 获取是否全选 SORT_TYPE getSortType() const; // 获取分类规则 QPixmap getFolderPixmap() const; // 获取文件夹图标 QPixmap getFolderBackgroundPixmap() const; // 获取文件夹时的九宫格背景 bool getCanInOutDir() const; // 获取是否可以进入子文件夹 bool getInPicture() const; // 是否当前是放大图片的 int getRows() const; // 获取显示行数 int getCols() const; // 获取显示列数 QList<QString> getListFile() const; // 获取当前目录下的所有多媒体文件 QList<QString> getSelectFiles() const; // 获取当前选择的所有文件列表 int getTopMargin() const; // 获取上边框 int getRightMargin() const; // 获取右边框 int getBottomMargin() const; // 获取下边框 int getLeftMargin() const; // 获取左边框 int getHorizalSpace() const; // 获取水平间隔 int getVerticalSpace() const; // 获取垂直间隔 public: void setRootDirPath(const QString &dirPath); // 设置预览文件夹路径 void setCurrentDirPath(const QString &currentDirPath); // 设置当前文件夹路径 void setNameFilters(const QStringList &nameFilters); // 设置文件名过滤 void setBackgroundPixmap(const QPixmap &backgroundPixmap); // 设置背景图片 void setSelectedPixmap(const QPixmap &selectedPixmap); // 设置选择状态图片 void setUnSelectedPixmap(const QPixmap &unSelectedPixmap); // 设置未选择状态的图片 void setSelectRect(const QRect &selectRect); // 设置未选择状态图片 void setSelectRightMargin(int selectRightMargin); // 设置选择按钮的右边间距 void setSelectBottomMargin(int selectBottomMargin); // 设置选择按钮的底部间距 void setLongPressed(bool longPressed); // 设置长按选择后的多选状态 void selectAll(bool selected = true); // 设置进入选择状态,并设置是否全选 void setSortType(const SORT_TYPE &sortType); // 设置分类规则 void setFolderPixmap(const QPixmap &folderPixmap); // 设置文件夹图标 void setFolderBackgroundPixmap(const QPixmap &folderBackgroundPixmap); // 获取文件夹时的九宫格背景 void setCanInOutDir(bool canInOutDir); // 设置是否可以进入下一级返回上一级文件夹( // false的时候不显示子文件夹) void setRows(int rows); // 设置显示行数 void setCols(int value); // 设置显示列数 void setTopMargin(int topMargin); // 设置上边框 void setRightMargin(int rightMargin); // 设置右边框 void setBottomMargin(int bottomMargin); // 设置下边框 void setLeftMargin(int leftMargin); // 设置左边框 void setMargin(int topMargin, int rightMargin, int bottomMargin, int leftMargin); // 设置边框 void setHorizalSpace(int horizalSpace); // 设置水平间隔 void setVerticalSpace(int verticalSpace); // 设置垂直间隔 void setInPicture(bool inPicture); // 是否当前是放大图片的 public: void reload(); // 重新加载缓存 void keyLeft(); void keyRight(); void keyOk(); protected: void updateRects(); // 更新位置 void updateSlider(); // 更新滑动栏 protected slots: void slot_timerOut(); // 长按超时 protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); protected: void drawBackground(QPainter *painter); void drawPixmaps(QPainter *painter); void drawSlider(QPainter *painter); void drawCurrentPixmap(QPainter *painter); private: QDir _dir; // 目录 QPixmap _backgroundPixmap; // 背景图片 QPixmap _unSelectedPixmap; // 未选中的图片 QPixmap _selectedPixmap; // 选中时的图片 QPixmap _folderPixmap; // 文件夹图片 QPixmap _folderBackgroundPixmap; // 文件夹九宫格项的背景 QFont _fontFolder; // 文件夹字体 QStringList _nameFilters; // 文件名过滤 QString _dirPath; // 目录路径 QString _rootDirPath; // 目录根路径 SORT_TYPE _sortType; // 排序种类 QList<QFileInfo> _listFileInfo; // 可读取的多媒体文件目录 QList<QPixmap> _listPixmap; // 多媒体文件预览缓存 QList<bool> _listSelected; // 是否选中文件 QRect _selectRect; // 选择框大小 int _selectRightMargin; // 选择框与图片右边的间距 int _selectBottomMargin; // 选择框与图片底边的间距 int _rows; // 显示行数 int _cols; // 显示列数 int _topMargin; // 上边界 int _rightMargin; // 右边界 int _bottomMargin; // 下边界 int _leftMargin; // 左边界 int _horizalSpace; // 水平间隔 int _verticalSpace; // 垂直间隔 int _sliderWidth; // 滑块宽度 QRect _sliderHandleRect; // 滑块矩形 QRect _sliderRect; // 滑动条矩形 int _logicalTop; // 逻辑顶部 int _logicalBottom; // 逻辑底部 int _logicalHeight; // 逻辑底部 int _sliderFreeSpace; // 滑块余量 bool _sliderPressed; // 滑块按下 private: float _pixmapWidth; // 辅助变量,图像宽度 float _pixmapHeight; // 辅助变量,图像高度 QList<QRect> _listRect; // 多媒体 int _originY; // 竖向位置 bool _pressed; // 标记是否按下鼠标 bool _isMoved; // 标记是否按下鼠标后移动 QPoint _lastPoint; // 记录最近一次拖动的鼠标位置 bool _longPressed; // 标记是否在长按状态 bool _longPressedFirst; // 标记是否刚进入长安状态 QTimer _timer; // 用于计时长按操作 bool _canInOutDir; // 是否允许进入下一级返回上以及 bool _inPicture; // 是否当前是放大图片的 int _inPictureIndex; QPixmap _inPicturePixmap; #endif // MULTIMEDIABROSWERWIDGET_H
需求 1.创建原始数据项目,项目下可以创建产品,产品自动创建四个阶段,阶段可以导入各自数据格式的原始文件; 2.创建原始数据项目和产品的时候,参数配置文件、成功配置文件、成功数据也会创建对应的项目和产品; 3.树形图,支持创建项目、修改项目、删除项目; 4.树形图,项目下,支持创建产品、修改产品删除产品; 5.树形图,产品下,自动产生四个阶段,支持创建新的阶段,修改原有阶段,删除某个阶段; 6.大批量导出单个项目产品阶段的文件,并动态显示导入过程;’ 7.可对原始数据进行二维图的数据分布分析,并可动态调整文件和文件对应的参数; 8.可对成功数据进行多文件综合分析,包含各文件和各文件下的解析格式,生成对应的关联关系; 9.在使用二维图、散点图、正态分布图进行分析时,支持区域缩放,支持显示隐藏,支持截图保存,支持导出当前正在显示的二维图原始数据(隐藏的点和行数据不导出) 10.使用sqlite3数据库; 11.支持各windows版本和国产银河麒麟系统; 12.其他复杂数据处理逻辑、小功能;Demo 头文件源码#ifndef DATAANALYSISWIDGET_H #define DATAANALYSISWIDGET_H #include <QWidget> #include <QButtonGroup> #include <QFileDialog> #include <QTreeWidgetItem> #include <QStringListModel> #include "DatabaseManager.h" #include "TreeWidget.h" #include "MyMessageBox.h" #include "TreeWidgetDialog.h" #include "PreDataDialog.h" #include <QPoint> class MainWindow; namespace Ui { class DataAnalysisWidget; class DataAnalysisWidget : public QWidget Q_OBJECT public: explicit DataAnalysisWidget(QWidget *parent = 0); ~DataAnalysisWidget(); public: void setMainWindow(MainWindow *pMainWindow); protected: void initData(); // 初始化数据 void loadConfig(); // 加载配置文件 void saveConfig(); // 存储配置文件 protected slots: // 按钮选择槽函数 void slot_buttonHeaderToggled(QAbstractButton *pAbstractButton, bool pressed); // 顶部按键 void slot_buttonToggled(QAbstractButton *pAbstractButton, bool pressed); // 右侧按键:数据类型 protected slots: // 项目管理树视图 void slot_contextMenu_trigger(QString text, QTreeWidgetItem *pTreeWidgetItem, QString path); // 树状视图选择 void slot_itemClicked(QTreeWidgetItem *pTreeWidgetItem, int count, QString path); // 树状视图点击 protected slots: // 原始数据树选择视图 void slot_itemCheckedClicked(QTreeWidgetItem *pTreeWidgetItem, int count, QString path); // 原始数据选择视图 protected slots: // 表视图 void slot_deleteFile(QStringList strList); // 删除文件表 void slot_exportFile(QString file); // 导出文件 void slot_exportFile(QStringList fileList); // 导出所有文件 void slot_preData(); // 数据预处理 void slot_packageAnalysis(); // 包络数据分析 protected slots: // 成功数据,散点图和正态分布图 void slot_chartTypeChanged(QString text); // 包络数据分析:切换散点图/正态分布图 void slot_listViewItemClicked(QModelIndex modelIndex); // 包络数据分析:点击选择列 protected: void createProject(QString text, QTreeWidgetItem *pTreeWidgetItem); // 创建项目 void modifyProject(QString text, QTreeWidgetItem *pTreeWidgetItem); // 修改项目 void deleteProject(QString text, QTreeWidgetItem *pTreeWidgetItem); // 删除项目 void createProduct(QString text, QTreeWidgetItem *pTreeWidgetItem); // 创建产品 void modifyProduct(QString text, QTreeWidgetItem *pTreeWidgetItem); // 修改产品 void deleteProduct(QString text, QTreeWidgetItem *pTreeWidgetItem); // 删除产品 void createStage(QString text, QTreeWidgetItem *pTreeWidgetItem); // 创建阶段 void modifyStage(QString text, QTreeWidgetItem *pTreeWidgetItem); // 修改阶段 void deleteStage(QString text, QTreeWidgetItem *pTreeWidgetItem); // 删除阶段 void deleteFile(QString text, QTreeWidgetItem *pTreeWidgetItem); // 删除文件 void importOriginData(QString text, QTreeWidgetItem *pTreeWidgetItem); // 导入原始数据(其他几个数据也同用此函数) void exportOriginData(QString text, QString file); // 导出原始数据(其他几个数据也同用此函数) void exportOriginData(QString text, QStringList fileList); // 导出原始数据(其他几个数据也同用此函数),右键表导出所有 void updatePieChartFiles(QTreeWidgetItem *pTreeWidgetItem, int count); // 更新饼图 void updateTableAutoColumnContent(QTreeWidgetItem *pTreeWidgetItem); // 更新自动列的table protected: void intoPreData(QStringList strList = QStringList()); // 切换至预处理 void updatePreData(QString project, QString product, QString stage, QString file); bool intoAnalysisData(); // 切换至包络数据分析 bool updateAnalysisData(QString project, QString product, QString stage); // 更新分析数据 protected: void loadProject(); // 加载项目(根据选择的按钮判断) void loadProject(int index); // 加载指定项目(0,1,2,3) void updateTree(); // 更新树视图 void updateTable(); // 更新表格 void updatePieChart(); // 更新饼图 void updateTableAutoColumn(); // 更新表格动态列 protected: void debugProject(); // 调试工程 protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); private slots: void on_pushButton_export_clicked(); // 导入按钮 void on_pushButton_import_clicked(); // 导出按钮 void on_checkBox_firstAsAixsX_clicked(bool checked); // 第一列是否作为X轴 void on_pushButton_succeeDataPath_clicked(); // 成功数据路径切换按钮 void on_pushButton_preDealPath_clicked(); // private slots: void on_pushButton_exit_clicked(); // 退出 void on_pushButton_hide_clicked(); // 隐藏 void on_pushButton_min_clicked(); // 最小化按钮 void on_pushButton_max_clicked(); // 最大化按钮 void on_pushButton_search_clicked(); // 搜索按钮 void on_pushButton_clear_clicked(); // 清空按钮 private: Ui::DataAnalysisWidget *ui; QButtonGroup _buttonGroup; QButtonGroup _buttonGroupHeader; DatabaseManager _databaseManager; // 数据库管理类 QList<Project> _listProject; // 项目信息数据结构 QList<FileInfo> _listFileInfo; // 文件信息数据结构 QList<FilePieChart> _listFilePieChart; // 饼图数据结构 QString _content; // 辅助变量 TreeWidget *_pTreeWidget; // 树状空间 QDialog *_pDialog; // 树状对话框 QPoint _originPoint; // 辅助变量 QPoint _lastPoint; // 辅助变量 bool _leftButtonPressed; // 辅助变量 QString _lastDir; // 记录最后一次打开目录 int _msgWidth; // 消息对话框宽度 int _msgHeight; // 消息对话框高度 MyMessageBox *_pMyMessageBox; // 全局消息对话框(用于加载数据) QString _cfgFile; // 配置文件路径 MainWindow *_pMainWindow; // MainWindow窗口指针 #endif // DATAANALYSISWIDGET_H
前言 基本都是使用QtCreator开发,使用vs进行一下开发,记录从QtCreator换成VS所遇到的注意的坑。VS装对应的Qt版本助手配置Qt版本 VS装番茄助手 这里要注意,装了多个版本的VS,只识别最后一个版本,装的是VS2017的,识别只有VS2015,番茄助手选的是VS2017支持的版本。 代码头文件和源文件切换 先按ctrl不松开,然后按K不松开,然后按O即可。 Ctrl + K + OQt的ui设计器 当点击ui文件打不开的时候,是使用默认的打开有问题,需要手动添加一下,如下图: 更新了界面ui未生效的时候 建议每次修改后,编译一次,然后项目右键重新扫描解决方案 关于自动生成cpp代码 先写头文件代码,用番茄助手生成对应的cpp代码 关于信号与槽 VS上不是很方便,需要自己写槽函数后,使用connect关联 关于添加Qt模块 注意:切换版本其配置都会变化,模块需要重新配置 关于打包 还是使用mingw32的方式,只是命令行用msvc对应的版本 注意,打包后请自己运行一次,防止缺少库
需求 百度开源飞桨PaddleOCR编译成32位版本,以使windows的32位机器可以使用paddleOCR。注意paddleOCR编译时需要paddle的库和头文件,所以要编译paddle库。paddle库分为paddle和paddle-lite版本paddle提供c++、python等多种调用方式,前提你得编译安装成功尝试paddleOCR2.0版本编译,配置paddle和paddle-lite的各自新版本和老版本1.0,还有其他几个版本都尝试过,都无法顺利编译通过paddle较老的版本0,8往直前的版本都下载不到了paddle较老的版本1.0版本,编译的时候double与float转换问题,cmd问题等很多问题,经查验是老版本与新的系统cpu等有兼容问题 以上是这几个库的编译,而且非常费时间,反复编译单个都超过5次以上,无法成功 也尝试过python2.7 32位 和 python3.8 32位搭建运行环境,缺paddle库无法成功(其官方技术人员其实已经明确回复,windows上CPU不支持32位的) 附上各种图: 其他 编译paddle库时,有很多依赖库,如gflags、openBLAS、opencv等等诸多库,第一级又依赖库(可理解为二级),笔者有自己的开源库大集合,编译老手,比较熟悉,源码都改不动,实在无能为力,附上网上能百度到的相关文章,如下: 结论 建议想采用paddleOCR32位的,可以转为tesseract,opencv等,不要死磕。
前言 开发Activex控件,以供其他应用程序调用,本篇章讲解C#调用Activex控件,不限于Qt开发的Activex控件。 Wpf要调用Activex控件,必要先用C#对Activex控件进行包装,然后提供给Wpf调用。Demo C#调用Activex方法步骤一:注册activex控件 运行之前先要注册,使用Qt下自带的idc注册一下。idc -regserver activeHelloWorldDemo.dll 步骤二:确认activeQt控件的clsid 查看一下,打开注册表并搜索一下,确认clsid,如下图: "2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"步骤三:创建c#项目,引入com的dll 将注册的dll引入到项目中,如下图: 步骤四:代码中使用控件 步骤五:编写代码private void button1_Click(object sender, EventArgs e) activeHelloWorldDemoLib.activeHelloWorldDemo dlg = new activeHelloWorldDemoLib.activeHelloWorldDemo(); dlg.show(); }源码using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace trainSimulationDemo public partial class Form1 : Form public Form1() InitializeComponent(); private void Form1_Load(object sender, EventArgs e) private void button1_Click(object sender, EventArgs e) activeHelloWorldDemoLib.activeHelloWorldDemo dlg = new activeHelloWorldDemoLib.activeHelloWorldDemo(); dlg.show();
前言 开发Activex控件,以供其他应用程序调用,本篇章讲解Qt调用Activex控件,不限于Qt开发的Activex控件。Demo QAxWidget概述 QAxWidget类是包装ActiveX控件的QWidget。 QAxWidget可以实例化为空对象,带有它应该包装的ActiveX控件的名称,或者带有指向ActiveX控件的现有接口指针。ActiveX控件的属性、方法和事件仅使用QAxBase支持的数据类型,可以作为Qt属性、插槽和信号使用。基类QAxBase提供了一个API,可以通过IUnknown指针直接访问ActiveX。 QAxWidget是一个QWidget,通常可以这样使用,例如,它可以组织在一个widget层次结构和布局中,或者充当一个事件过滤器。支持标准小部件属性,例如enabled,但它依赖于ActiveX控件来实现对环境属性(例如palete或font)的支持。QAxWidget试图提供必要的提示。 但是,不能重新实现特定于Qt的事件处理程序,如mousePressEvent或keyPressEvent,并期望可靠地调用它们。嵌入式控件完全覆盖QAxWidget,通常处理用户界面本身。使用特定于控件的API(即侦听控件的信号),或使用标准COM技术,如window过程子类化。 QAxWidget还从QAxBase继承了大部分与ActiveX相关的功能,特别是dynamicCall()和querySubObject()。 警告:可以将QAxWidget子类化,但不能在子类中使用Q_OBJECT宏(生成的moc文件将不会编译),因此无法添加更多信号、插槽或属性。这种限制是由于运行时生成的元对象信息造成的。要解决此问题,请将QAxWidget聚合为QObject子类的成员。Qt调用Activex方法步骤一:注册activex控件 运行之前先要注册,使用Qt下自带的idc注册一下。idc -regserver activeHelloWorldDemo.dll 步骤二:确认activeQt控件的clsid 查看一下,打开注册表并搜索一下,确认clsid,如下图: "2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"步骤三:使用QAxWidget调用QAxWidget *pAxWidget = new QAxWidget(); pAxWidget->resize(400, 320); pAxWidget->setControl("2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"); pAxWidget->show();源码#include <QApplication> #include <QAxWidget> int main(int argc, char *argv[]) QApplication a(argc, argv); QAxWidget *pAxWidget = new QAxWidget(); pAxWidget->resize(400, 320); pAxWidget->setControl("2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"); pAxWidget->show(); return a.exec();
前言 OSG研究之后,做地理GIS显示了地球:《项目实战:Qt+OSG教育学科工具之地理三维星球》,这一文章是基于OSG做的,而基于OsgEarth是可以进一步对地球进行深度操作,所以本篇开启OsgEarth系列。OsgEarth编译过程简介 OsgEarth的编译,是基于Osg和OsgEarth结合在一起的,先要编译Osg,然后编译OsgEarth。OsgEarth的依赖库较多,分为上、中、下三篇,然后单独有一篇如何将编译好的osgEarth集成到Qt中。目标:Qt5.15.x + VS2019 x64版本演示Demo Demo基于Qt5.15.2 + vs2019 x64 + osg3.6.3 + osgEarth3.1。 演示环境Demo下载地址:https://download.csdn.net/download/qq21497936/14984791编译Osg 3.6.3 使用Osg3.4.0版本编译,可参照:《OSG开发笔记(一):OSG介绍、编译》 下面进入本次目标版本的编译。步骤一:下载解压 选择osg版本为3.6.3,因为搭配3.4.0存在一些函数未定义,所以是osgEarth应该是不兼容osg3.4.x了。 (注意:以下以3.4演示,3.6的读者自己改下) osg官网:http://www.openscenegraph.org/ (备注:博主QQ群提供文件下载,博客首页有扫码加群)步骤二:CMake配置 步骤三:CMake生成工程 步骤四:打开工程编译 步骤五:编程成功 编译Debug x64版本和Relase x64版本。 编译Curl 7.65.3步骤一:下载解压 (备注:博主QQ群提供文件下载,博客首页有扫码加群)步骤二:CMake配置 步骤三:CMake生成工程 步骤四:打开工程编译 步骤五:编译成功
需求 QLineEdit作为编号输入,只能输入数字、字母和数字。原理 实用setInputMask做限制。代码// 限制只能输入最长12位的编码(包含数字、字母和字符) ui->lineEdit->setInputMask(QString("%1;_").arg("", 12, QChar('X')));拓展 大写是必须要输入,小写是可以不输入
前言 Qt要与百度地图交互,百度地图提供的JS,那么交互就是Qt与JS交互,本章Qt向JS交互发送指令。Demo Qt控制JS Qt控制JS相对界面,直接使用QWebEnginePage的runJavaScript接口即可,函数接口如下:void runJavaScript(const QString& scriptSource); void runJavaScript(const QString& scriptSource, quint32 worldId); void runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback); void runJavaScript(const QString& scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback);参数一:执行的js脚本内容其他参数请自行查看。百度地图API设置中心点和缩放等级 示例var map = new BMap.Map("allmap"); var point = new BMap.Point(116.331398,39.897445); map.centerAndZoom(point,12);定位当前所在的城市 LocalCity定位类 LocalCityOptions该类使用回调函数传回结果 LocalCityResult定位结果的结果类描述 示例function myFun(result){ var cityName = result.name; map.setCenter(cityName); alert("当前定位城市:"+cityName); var myCity = new BMap.LocalCity(); myCity.get(myFun); 设置地图缩放等级 核心类Map 示例map.setZoom(13)定位指定的城市 核心类Map 示例map.setCenter(“长沙市”)Demo关键代码void BaiDuMapWidget::locateCurrentPos() _pWebEnginePage->runJavaScript(QSTRING("var geolocation = new BMap.Geolocation();" "geolocation.enableSDKLocation();" "geolocation.getCurrentPosition(function(r){" " if(this.getStatus() == BMAP_STATUS_SUCCESS){" " var mk = new BMap.Marker(r.point);" " map.addOverlay(mk);" " map.panTo(r.point);" " alert('%1'+r.point.lng+','+r.point.lat);" " }" " else {" " alert('%2'+this.getStatus());" " }" "});").arg(QSTRING("您的位置")).arg(QSTRING("定位失败,错误码:"))); void BaiDuMapWidget::locateProvince(QString province) _pWebEnginePage->runJavaScript(QSTRING("map.setZoom(9);" "map.setCenter('%1')").arg(province)); void BaiDuMapWidget::locateCity(QString city) _pWebEnginePage->runJavaScript(QSTRING("map.setZoom(13);" "map.setCenter('%1')").arg(city)); }工程模板:v1.1.0 mapDemo_v1.1.0_基础模板_定位本地_定位省份_定位城市.rar CSDN下载地址:https://download.csdn.net/download/qq21497936/85460773入坑入坑一:中文乱码问题问题 解决 一开始输入的,从原头就需要加入QString::fromLocal8bit,如下图: 入坑二:百度地图获取浏览器本地定位超时(暂未解决)问题 入坑三:调用一些函数无效原因 Js是脚本语言,当调用时,前面有错误后面的就不会执行。解决 找到未起作用的地方,看是否真的调用到了,使用alert弹出框查看。
目录自研产品:自主研发的产品和产品解决方案(体验Demo可下载)合作案例专栏:案例分享(体验Demo可下载,仅jia方同意公开的案例,只shang业定制)开发专栏:项目实战Qt开发专栏:开发技术Qt开发专栏:三方库开发技术Qt开发专栏:实用技巧Qt开发专栏:各种问题解决Qt开发专栏:qss样式表笔记大全Qt开发专栏:概念Qt开发专栏:qml开发海思开发专栏瑞芯微开发专栏树莓派开发专栏OSG、OSGEARTH三维开发专栏OpenCV开发专栏OpenGL开发专栏FFmpeg、SDL和流媒体开发专栏Onvif开发专栏Rock Pi开发专栏Linux实用技巧国产麒麟系统相关开发硬件相关开发单片机相关开发数据库相关开发程序员PS技能其他(编程相关)其他(非编程相关)自研产品:自主研发的产品和产品解决方案(体验Demo可下载)《产品分享:Qt+Arm基于RV1126平台的内窥镜软硬整套解决方案(实时影像、冻结、拍照、录像、背光调整、硬件光源调整,其他产品也可使用该平台,如视频监控,物联网产品等等)》《产品分享:Qt视频播放器(不依赖系统编解码),当前版本v1.1.2》《产品分享:Qt数学函数公式学科工具,当前版本v1.0.0》《产品分享:Qt+OSG教育学科工具之地理三维星球,当前版本v3.2.0》合作案例专栏:案例分享(体验Demo可下载,仅jia方同意公开的案例,只shang业定制)《案例分享:Qt+RV1126+PLC医疗血浆采集仪(中英文输入、西门子PLC、数据库存储,各种数据统计,数值监测,电子秤操作,记录查询,全局报警等等)》《案例分享:Qt高频fpga采集数据压力位移速度加速度分析系统(通道配置、电压转换、采样频率、通道补偿、定时采集、距离采集,导出exce、自动XY轴、隐藏XY轴、隐藏显示通道,文件回放等等)》《案例分享:Qt政务标签设计器,标签排版软件定制与打印》《案例分享:Qt西门子机床人机界面以及数据看板定制(西门子通讯,mysql数据库,生产信息,参数信息,信息化看板,权限控制,播放器,二维图表,参数调试界面)》《案例分享:Qt modbus485调试工具(读写Byte、Int、DInt、Real、DReal)(当前v1.3.0)》《案例分享:某品牌音响系列协议调试工具(搜寻主机,查询通道,基本控制API,云音乐API,语言节目API等,可增删改指令)》《案例分享:Qt出版社书籍配套U盘资源播放器软件定制(脚本关联播放器与资源文件,播放器,兼容win7,win10和mac)》《案例分享:Qt便携式致病菌快速检测仪(账号管理、实验过程、二维图表、历史数据、通讯管理、实验报告、中英文等等)》《案例分享:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)》《案例分享:Qt九宫格图片资源浏览器(支持window、linux、兼容各国产系统,支持子文件夹,多选,全选,图片预览,行数与列数设置等)》《案例分享:Qt+C#轨道交通行业高性能高流畅度模拟火车移动图像控件》《案例分享:Qt数据分析处理平台(兼容各国产麒麟系统)(文件域字符串解析,上万文件批量导入,折线图、散点图,正态分布图分析处理导出等)》《案例分享:Qt + 树莓派3B+ 智能笔筒系统》《案例分享:Qt中英文输入软键盘(支持Qt4、Qt5、触摸和键鼠混合输入等)》《案例分享:Qt多段Y轴折线图框架(双Y轴段折线、支持拽拖、浮动游标显示X值各段Y值、支持大量实时显示下位机数据)》《案例分享:Qt+Arm+Fpga医疗肾镜(又名内窥镜)(实时影像、冻结、拍照、白平衡、九宫格、录像、背光调整、硬件光源调整、光源手动自动调整、物理按键)》《案例分享:Qt管道焊接参数条码打印系统(条码打印机TSC 244 Pro、打印条码、打印中文、打印字符、多张连续打印)》《案例分享:Qt+iMax6生命探测仪(探测障碍物、静止目标、动态目标、生命目标、探测半径、探测前方雷达显示、动态目标轨迹显示、探测热力图、探测过程存储与回放)》《案例分享:Qt多通道数据采集系统(通道配置、电压转换、采样频率、通道补偿值、定时采集、导出excel和图表、自动XY轴、隐藏XY轴、实时隐藏显示通道)》《案例分享:Qt西门子PLC调试模拟工具(包含PLC上位机通讯,PLC服务器,读写Byte、Int、DInt、Real)(持续更新,当前v1.5.0)》《案例分享:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)》《案例分享:医疗流式细胞术数据文件(.fcs)导出excel表工具》《案例分享:Qt+Android模拟操作器(模拟操作app,打开,点击,输入,获取验证码等等)》《案例分享:Qt流水线图像显示控件(列刷新、1ms一次、缩放、拽拖、拽拖预览、性能优化、支持OpenGL GPU加速)》《案例分享:Qt内窥镜相机录像程序(打开摄像头、支持多种摄像头、分辨率调整、翻转、旋转、亮度调整、拍照、录像、回放图片、回放录像)》《案例分享:Qt手机模拟器拉伸旋转框架》《案例分享:Qt用于服务器多图像拼接存在误差的标定工具(像素误差校准)》《案例分享:Qt的PPT播放器》《案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo》开发专栏:项目实战《项目实战:Qt+OpenCV大家来找茬(Qt抓图,穿透应用,识别左右图区别,框选区别,微调位置)》《项目实战:Qt球机控制工具 v1.0.0(球机运动八个方向以及运动速度,设置运动到指定角度,查询当前水平和垂直角度)》《项目实战:Qt文件改名工具 v1.2.0(支持递归检索,搜索:模糊匹配,前缀匹配,后缀匹配;重命名:模糊替换,前缀追加,后缀追加)》《项目实战:Qt+OSG三维2D文字实时效果查看工具》《项目实战:C#上位机+arduino下位机+控制点亮LED灯》《项目实战:Qt+OpenCV激光射击游(识别激光、识别圆)》《项目实战:Qt+ffmpeg摄像头检测工具》《项目实战:Qt+OpenCV图像处理与识别算法平台(持续更新,当前v1.7.0)》《项目实战:Qt编译Qt库以及使用C#调用Qt库,并实现C#集成Qt的tcp客户端》《项目实战:Qt+OpenCV视频播放器(支持播放器操作,如暂停、恢复、停止、时间、进度条拽托等)》《项目实战:Qt+OpenCV操作摄像头拍照、调节参数和视频录制》《项目实战:Qt+Sql server英汉汉英电子词典》《项目实战:Qt并发服务器通讯,受同一时刻最大线程数限制(笔者本本同一时刻600多)》《项目实战:Qt多人聊天室程序(在线、离线、离线信息再次登录后发送等)》《项目实战:Qt给指定手机发送短信(点对点、群发等等)》《项目实战:Qt贝塞尔曲线拽托顶点实时显示工具》Qt开发专栏:开发技术《Qt开发技术:图形视图框架(一)基本介绍》《Qt开发技术:图形视图框架(二)场景QGraphicsScene、QGraphicsItem与QGraphicsView详解》《Qt开发技术:Qt拽拖开发(一)拽托框架详解及Demo》《Qt开发Activex笔记(一):环境搭建、基础开发流程和演示Demo》《Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件》《Qt开发Activex笔记(三):C#调用Qt开发的Activex控件》《Qt开发技术:QCharts(一)QCharts基本介绍以及图表框架详解》《Qt开发技术:QCharts(二)QCharts折线图介绍、Demo以及代码详解》《Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解》《Qt开发技术:QCharts(四)QCharts面积图介绍、Demo以及代码详解》《Qt开发技术:Qt富文本(一)富文本介绍、文档结构》《Qt开发技术:Qt富文本(二)Qt文本光标操作、文档布局、富文本编辑、处理和Demo》《Qt开发技术:Qt富文本(三)Qt支持的HTML子集(查询手册)以及涉及的类》《Qt开发技术:QtSVG介绍、使用和Demo》《Qt开发技术:Qt绘图系统(一)绘图系统介绍》《Qt开发技术:Qt绘图系统(二)QPainter详解》《Qt开发技术:Qt的动态静态插件框架介绍和Demo》《Qt开发技术:QWebSocket客户端、服务端介绍与开发》《Qt开发技术:mqtt介绍、QtMqtt编译和开发环境搭建》《Qt开发技术:QDBus介绍、编译与Demo》Qt开发专栏:三方库开发技术《QCustomPlot开发笔记(一):QCustomPlot简介、下载以及基础绘图》《QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法》《Qt开发笔记之QCustomPlot:QCustomPlot介绍、编译与使用》《libx264开发笔记(一):libx264介绍、海思平台移植编译》《mp4v2开发笔记(一): mp4v2库介绍,mp4v2在ubuntu上交叉编译移植到海思Hi35xx平台》《libmatio开发笔记(一):matlab文件操作libmatio库介绍,编译和基础Demo》《Matlab+Qt开发笔记(一):matlab搭建Qt开发matlib环境以及Demo测试》《Matlab+Qt开发笔记(二):Qt打开mat文件显示读取的数据》《Hdf5开发笔记(一):hdf5介绍,在windows上编译msvc2015x64版本》《Qt+MPlayer音乐播放器开发笔记(一):ubuntu上编译MPlayer以及Demo演示》《Qt+MPlayer音乐播放器开发笔记(二):交叉编译MPlayer以及部署到开发板播放演示》《Qt+腾讯IM开发笔记(一):腾讯IM介绍、使用和Qt集成腾讯IM-SDK的工程模板Demo》《Qt开发笔记:OpenSSL库介绍、windows上mingw32版本的OpenSSL编译模块化》《Qt三方库开发技术(一):QuaZIP介绍、编译和使用》《海康摄像SDK开发笔记(一):海康威视网络摄像头SDK介绍与模块功能》《LlibModbus库开发笔记(一):libmodbus库介绍、编译和基础工程模板》《saba开发笔记(一):saba介绍、编译使用以及测试》《地图开发笔记(一):百度地图介绍、使用和Qt内嵌地图Demo》 《地图开发笔记(二):Qt与百度地图js交互的基础-Qt向Js发送指令定位各大省份与城市》《libzip开发笔记(一):libzip库介绍、编译和工程模板》《zlib开发笔记(一):zlib库介绍、编译和工程模板》《zlib开发笔记(二):zlib库介绍、ubuntu平台编译和工程模板》《zlib开发笔记(三):zlib库介绍、在ubuntu上进行arm平台交叉编译》《zlib开发笔记(四):zlib库介绍、编译windows vs2015x64版本和工程模板》《xml开发笔记(一):tinyXml2库介绍、编译和工程模板》《Gif开发笔记(一):gif介绍、编译和工程模板》《Qt混合Python开发技术:Python介绍、混合过程和Demo》《Qt三方库开发技术:QXlsx介绍、编译和使用》《Qt三方库开发技术:log4Qt介绍、编译和使用》《Qt三方库开发技术:二维码生成、识别以及条码识别》《Qt三方库开发技术:Qt应用内部打开PDF文件》《Qt开发笔记之编码x264码流并封装mp4(一):x264介绍、windows平台x264库编译》《Qt开发笔记之编码x264码流并封装mp4(二):windows平台x264添加mp4支持,gpac库的介绍与编译》《Qt开发笔记之编码x264码流并封装mp4(三):Qt使用x264库对.yuv文件编码为.h264文件》《Qt开发笔记之编码x264码流并封装mp4(四):mp4v2库的介绍和windows平台编译》《Qt开发笔记之编码h264码流并封装mp4(五):ubuntu平台编译x264》《Qt开发笔记之编码h264码流并封装mp4(六):ubuntu平台编译mp4v2并封装mp4》《Qt开发笔记之Qwt(一):Qwt介绍、编译与Demo》《Qt开发笔记之Qwt(二):Qwt仪表盘的基本使用》《JRtplib开发笔记(一):JRtplib简介、JThread库编译》《JRtplib开发笔记(二):JRtplib库编译、示例演示》《JRtplib开发笔记(三):JRtplib库编程使用说明》《JRtplib开发笔记(四):JRtplib的VS开发环境搭建以及Demo》《Jpeglib开发笔记(一):JpegLib库介绍、windows编译和Demo》《Jpeglib开发笔记(二):JpegLib编译(ubutnu)和Demo》《手写识别(zinnia)开发笔记(一):Zinnia介绍、编译、使用以及Demo》《Qt开发笔记(一):Qt+FFmpeg开发环境搭建以及工程模板》《Qt开发笔记之线性代数:线性代数矩阵以及Eigen库的介绍、编译和使用》Qt开发专栏:实用技巧《Qt实用技巧:QtCreator编辑区关闭右侧不必要的警告提示》《Qt实用技巧:Qt中添加对windows api的支持,显示/隐藏任务栏和桌面(解决无法找到windows api)》《Qt实用技巧:Qt中添加对C++11标准的支持(两种方式)》《Qt实用技巧:Qt从QtCreator更换为VS开发Qt所需要注意的坑》《Qt实用技巧:实用掩码限制QLineEdit只能输入规定长度的数字、字母和字符》《Qt实用技巧:VS2017编写纯C库以及使用Qt调用C库方法》《Qt实用技巧:QLineEdit限制只能输入Ip地址,且一直显示ip地址分段的“.”》《Qt实用技巧:将QWidget作为输入窗口,接收键盘消息、输入法并且控制输入法悬浮工具栏位置控制》《Qt实用技巧:在Qt中获取屏幕的绝对坐标》《Qt实用技巧:软件演示版永久提示框》《Qt实用技巧:QPainterPath绘图路径(多次画同样的图形集合)》《Qt实用技巧:代码中QIcon缩放(QPixmap的手动放大和QIcon自动缩小)》《Qt实用技巧:在Qt Gui程序中嵌入qml界面(可动态覆盖整个窗口)》《Qt实用技巧:界面切换使用Dialog全屏切换》《Qt实用技巧:使用QMediaPlayer播放mp4文件》《Qt实用技巧:实现窗口透明的五种方法》《Qt实用技巧:组合图形的比例变换》《Qt实用技巧:截屏功能的实现》《Qt实用技巧:自定义窗口标题栏》《Qt实用技巧:设置应用程序exe的图标》《Qt实用技巧:测试80*1080p拼接后显示刷新帧率》《Qt实用技巧:Qt连接SQL Server数据库(需要配置ODBC)》《Qt实用技巧:80显示超大显示拼接(十台服务器,每台八路摄像头)方案和Demo》《Qt实用技巧:仅去掉标题栏,保持对话框边框》《Qt实用技巧:设计模式之单例模式,唯一实例类通用模板》《Qt实用技巧:QCreator使用git(gitHub)管理项目代码笔记》《Qt实用技巧:使用Qt加载超大图片的耗时测试》《Qt实用技巧:ubuntu发布程序打包流程(解决插件xcb加载失败) 》《Qt实用技巧:使QWidget作为模态对话框显示》《Qt实用技巧:图形视图框架中图元将矩形边界改为不规则边界(用于选取和碰撞)》《Qt实用技巧:实现不规则窗口的鼠标消息穿透,包括穿透到桌面和穿透到父窗口》《Qt实用技巧:使用非透明窗体鼠标穿透到桌面的设置方法》《Qt实用技巧:Qt窗口置顶》《Qt实用技巧:QString、LPCWSTR、std::string之间的转换(持续补充)》《Qt实用技巧:win将ffmpeg、opengl、osg等各种库封装成qt模块,运行需要dll,增加自动拷贝运行库到exe目录执行脚本》《Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作》《Qt实用技巧:QWidget中QPushButton成为可点击的图标(实现全透明,不论点击与否都只显示Icon)》《Qt实用技巧:使用QMediaPlayer和Windows自带组件播放swf、rmvb、mpg、mp4等视频文件》《Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗》《Qt实用技巧:对QPushButton(等类似透明有黑色背景的QWidget实现透明/半透明的方法》《Qt实用技巧:Qt设计器中QIcon的缩放(qss的放大和QIcon自动缩小(无法自动放大))》Qt开发专栏:各种问题解决《关于 麒麟系统开发错误“fatal error: GL/gl.h: No such file or directory“ 的解决方法》《关于 国产麒麟系统编译Qt项目是报错:error: cannot find -lGL 的解决方法》《关于 海思平台sample的demo中添加ffmpeg静态库(.a)报错误undefined reference toavpriv_pix_fmt_hps_avi等错误 的解决方法》《关于 编译软件时报错“xdo.c:29:34: fatal error: X11/extensions/XTest.h:”错误 的解决方法》《关于 CentOS8出现“Error: Failed to download metadata for repo ‘AppStream‘: xxxx” 的解决方法》《关于 在海思3559AV100上使用QProcess和QStorageInfo获取磁盘总大小和可用大小失败 的解决方法》《关于 Qt5.15.x以及相关版本使用QtCreator代码自动补全较慢 的解决方法》《关于 屏蔽Qt未使用变量报警错误 的解决方法》《关于 Qt在线安装速度较慢 的解决方法》《关于 虚拟机交叉编译目标机程序,使用filezilla的ftp方式传输到板子上没问题,后来同样环境传入应用运行宕机 的解决方法》《关于 Qt在海思平台使用脚本和文件控制GPIO口写入高低无效 的解决方法》《关于 海思Hi3559安装好sdk和编译器后运行编译器出现“bash: ...aarch64-himix100-linux-c++: No such file or directory” 的解决方法》《关于 Qt部署在RV1126的arm-linux系统上使用QImage缩放,drawXXXX缩放无效问题 的解决方法》《关于 Qt部署在RV1126的arm-linu系统上使用QCursor::pos()获取鼠标坐标始终为0 的解决方法》《关于 CMake编译出出现错误“Could not find compiler set in environment variable RC:” 的解决方法》《关于 Qt使用MSVC版本编译出现“QMAKE_MSC_VER” 的解决方法》《关于 Qt使用QOpenGLWidget运行时崩溃 的解决方法》《关于 C#使用Console.WriteLine调试没有命令行输出 的解决方法》《关于 error: C2039: “shared_ptr”: 不是“std”的成员 的解决方法》《关于 CMake“cmake is not able to compile a simple test program”错误 的解决方法》《关于 fatal error LNK1158: 无法运行“rc.exe” 的解决方法》《关于 QtCreator中写Qt程序遇到printf不输出问题 的解决方法》《关于 QLineEdit设置QDoubleValidator设置范围无效问题 的解决方法》《关于 编译QT项目时报错:error: cannot find -lGL 的解决方法》《关于 编译qt项目时报错:error: cannot find -lGLESv2 的解决方法》《关于 QT_BEGIN_NAMESPACE宏的作用》《关于 QMainwindow设置布局layout失败 的解决方法》《关于 qt程序退出出现“已停止工作”程序奔溃问题 的解决方法》《关于 qt中文乱码问题 的详解》《关于 ubuntu上qt5.9.3使用openssl出现“openssl unsupport platform” 的解决方法》《关于 libQt5xxx:对‘Qxxxx::xxxx()@Qt5’未定义的引用错误 的解决方法》《关于 Chrome插件安装时程序包无效:"CRX_HEADER_INVALID" 的解决方法》《关于 Qt编译环境从Qt5迁移到Qt4遇到Qt::FramelessWindowHint失效 的解决方法》《关于 QMessageBox定制大小重写showEvent失败的 解决方法》《关于 GraphicsScene场景中触发事件使用event->pos()获取坐标为0 的解决方法》《关于 QtForMac开发 ui界面设置最小宽度和高度无效 的解决方法》《关于 操作COM组件的RGB属性只能传递一个int表达COM三色属性rgb 的解决方法》《关于 Qt信号与槽连接时出现无法识别信号问题 的解决方法》《关于 Qt设置置顶窗口,透明部分显示黑色底色(已设置透明窗口) 的解决方法》《关于 加载图片"Corrupt JPEG data: premature end of data segment" 的解决方法》《关于 QGLWidget和QOpengGLWidget透明相关问题 的问题》《关于 Qt场景QGraphicsScene中,添加QWidget窗口,QWidget窗口无法捕捉mouseReleaseEvent松开消息 的解决方法》《关于 Qt在win上“启动程序失败,路径或者权限错误"无法运行的16位程序 的解决方法》《关于 QtCreartor编写纯C++程序调用不到C++某些标准库和枚举以及运行错误 的解决方法》《关于 error: comparison between ... 'QPushButton*' and 'QAbstractButton*' lacks... 的解决方法》《关于 QWidget无法使用stylesheet设置自身backgound-color(背景色)和border-image(背景图片) 的解决方法》《关于 QNetworkManager出现“QSslSocket: cannot call unresolved function SSLv23_client_method“ 的解决方法》《关于 Qt编译时使用msvc编译器报错“Error: cannot open ...main.obj.10836.32.jom for write” 的解决方法》《关于 QWidget+Qml程序打包到ubuntu时,程序与系统库版本不同,编译时添加并依赖自带库 的方法》《关于 Qt图形视图框架自绘图元放到左边和上边之外,部分在内进行拉伸后,拉伸多余的区域无法碰撞 的解决方法》《关于 ubuntu18.04无法通过常用命令安装gcc 的解决方法》《关于 ubuntu18.04使用git pull报错(没有权限) 的解决方法》《关于 vm虚拟机ubuntu18.04网络图标不见且无法连接网络 的解决方法》Qt开发专栏:qss样式表笔记大全《qss样式表笔记大全(一):qss名词解析(包含相关示例)》《qss样式表笔记大全(二):可设置样式的窗口部件列表(上)(包含相关示例)》《qss样式表笔记大全(三):可设置样式的窗口部件列表(中)(包含相关示例)》《qss样式表笔记大全(四):可设置样式的窗口部件列表(下)(包含相关示例)》Qt开发专栏:概念《QWidget与HWND的互相转换》《Qt疑难杂症:无法QVideoWidget播放器上浮控件》《QT三大绘图类:QPixmap/QImage/QPicture》《Qt开发笔记:QGLWidget、QOpenGLWidget详解及区别》《JSON与XML的区别比较》Qt开发专栏:qml开发《qml开发笔记(一):界面元素初探》《qml开发笔记(二):可视化元素基类Item详解(上半场anchors等等)》《qml开发笔记(三):可视化元素基类Item详解(下半场)》《qml开发笔记(四):可视化元素Rectangle、Image》《qml开发笔记(附表一):qml可识别的color表:颜色--名称--RGB》《qml开发笔记(五): 可视化元素BorderImage、AnimatedImage、AnimatedSprite、SpriteSequence》《qml开发笔记(六):可视化元素Text、Window》《qml开发笔记(七):输入元素鼠标输入MouseArea和键盘输入Keys》《关于 qml开发中使用Image元素切换图片闪黑屏 的解决方法》《Qml实用技巧:将样式style从对象中独立出来,可使多个按钮加载同一个样式》《Qml实用技巧:在可视元素之前半透明覆盖一个可视元素,阻止鼠标透(界面)传(防止点击到被遮挡的按钮)》《关于 qml从ubuntu开发迁移到目标机(定制ubuntu)上stackview无法显示(显示白屏)的解决方法》《关于 QWidget+Qml程序部署到linux时,'module"QtQuick”is not installed' 的解决方法》海思开发专栏《Hi3516开发笔记(一):海思HI3516DV300芯片介绍,入手开发板以及Demo测试》《Hi3516开发笔记(二):Hi3516虚拟机基础环境搭建之串口调试、网络连接以及sftp文件传输》《Hi3516开发笔记(三):Hi3516虚拟机基础环境搭建之交叉编译环境境搭建以及开机启动脚本分析》《Hi3516开发笔记(四):Hi3516虚拟机编译uboot、kernel、roofts和userdata以及分区表》《Hi3516开发笔记(五):通过HiTools使用网口将uboot、kernel、roofts和userdata按照分区表烧写镜像》《Hi3516开发笔记(六):通过HiTools使用USB/串口将uboot、kernel、roofts和userdata按照分区表烧写镜像》《Hi3516开发笔记(七):Hi3516虚拟机交叉开发环境搭建之交叉编译Qt》《Hi3516开发笔记(八):Hi3516虚拟机交叉开发环境搭建之配置QtCreator开发交叉编译环境》《Hi3516开发笔记(九):在QtCreator开发环境中引入海思sdk的bsp包,运行显示Qt界面》敬请期待...瑞芯微开发专栏《RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍》《RK3568开发笔记(二):入手RK3568开发板的套件介绍、底板介绍和外设测试》《RK3568开发笔记(三):RK3568虚拟机基础环境搭建之更新源、安装网络工具、串口调试、网络连接、文件传输、安装vscode和samba共享服务》树莓派开发专栏《树莓派开发笔记(一):入手树莓派3b,成功运行树莓派系统》《树莓派开发笔记(二):树莓派Qt编译和宿主机Qt交叉编译》《树莓派开发笔记(三):更便捷的开发,windows下和ubuntu下远程桌面至树莓派》《树莓派开发笔记(四):更便捷的开发,qt远程运行(主机qt开发一键远程运行到目标机上)》《树莓派开发笔记(五):GPIO引脚介绍和GPIO的输入输出使用(驱动LED灯、检测按键输入)》《树莓派开发笔记(六):GPIO口的UART的使用(串口通讯)》《树莓派开发笔记(七):GPIO口的SPI使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度)》《树莓派开发笔记(八):GPIO口的I2C使用(BME280三合一传感器:测量温度、湿度、气压、海拔高度)》《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)》《树莓派开发笔记(十):Qt读取ADC模拟量电压(ADS1115读取电压模拟量)》《树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)》《树莓派开发笔记(十二):入手研华ADVANTECH工控树莓派UNO-220套件(一):介绍和运行系统》《树莓派开发笔记(十三):入手研华ADVANTECH工控树莓派UNO-220套件(二):安装rtc等驱动》《树莓派开发笔记(十四):入手研华ADVANTECH工控树莓派UNO-220套件(三):使用研华自带系统测试rtc、gpio、232和485套件接口》《树莓派开发笔记(十五):树莓派4B+从源码编译安装mysql数据库》《关于 树莓派系统sudo ifconfig wlan0 up时,报错:Operation not possible due to RF-kill 的解决方法》 持续补充中…OSG、OSGEARTH三维开发专栏《项目实战:Qt+OSG三维点云引擎(支持原点,缩放,单独轴或者组合多轴拽拖旋转,支持导入点云文件)》《项目实战:Qt+OSG三维2D文字实时效果查看工具》《项目实战:Qt+OSG教育学科工具之地理三维星球》《OSG开发笔记(一):OSG介绍、编译》《OSG开发笔记(二):OSG帮助文档编译》《OSG开发笔记(三):OSG使用osgQt嵌入Qt应用程序》《OSG开发笔记(四):OSG不使用osgQt重写类嵌入Qt应用程序》《OSG开发笔记(五):OSG场景理解与基础类概述》《OSG开发笔记(六):OSG内存管理》《OSG开发笔记(七):OSG复现OpenGL入门示例和OSG坐标系》《OSG开发笔记(八):OSG模型文件存储与读取》《OSG开发笔记(九):OSG模型的基本操作之添加/删除、显示/隐藏、开关节点开/关》《OSG开发笔记(十):OSG模型的变换之平移、旋转和缩放》《OSG开发笔记(十一):OSG渲染状态与2D纹理映射》《OSG开发笔记(十二):OSG基本几何图形、内置几何类型》《OSG开发笔记(十三):OSG三维纹理映射(体渲染)》《OSG开发笔记(十四):OSG交互》《OSG开发笔记(十五):OSG光照》《OSG开发笔记(十六):OSG视口、相机和视点》《OSG开发笔记(十七):OSG中的相机移动》《OSG开发笔记(十八):OSG鼠标拾取pick、拽托球体以及多光源》《OSG开发笔记(十九):OSG文字显示》《OSG开发笔记(二十):OSG使用HUD显示文字》《OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式》《OSG开发笔记(二十二):OSG场景背景》《OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪》《OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头》《OSG开发笔记(二十五):OSG漫游之CS移动、碰撞检测与跳跃》《OSG开发笔记(二十六):OSG漫游之上下楼梯》《OSG开发笔记(二十七):OSG路径漫游之录制播放固定路径动画》《OSG开发笔记(二十八):OSG模型固定路径动画》《OsgEarth开发笔记(一):Osg3.6.3+OsgEarth3.1+vs2019x64开发环境搭建(上)》《OsgEarth开发笔记(二):Osg3.6.3+OsgEarth3.1+vs2019x64开发环境搭建(中)》《OsgEarth开发笔记(三):Osg3.6.3+OsgEarth3.1+vs2019x64开发环境搭建(下)》《OsgEarth开发笔记(四):Qt5.15.2在QtCreator集成Osg3.6.3+OsgEarth3.1+OsgQt的vs2019x64版本开发环境搭建》 持续补充中…OpenCV开发专栏《项目实战:Qt+OpenCV激光射击游戏(识别激光、识别圆)》《项目实战:Qt+OpenCV视频播放器(支持播放器操作,如暂停、恢复、停止、时间、进度条拽托等)》《项目实战:Qt+OpenCV操作摄像头拍照、调节参数和视频录制》《OpenCV开发笔记(〇):使用mingw530_32编译openCV3.4.1源码,搭建Qt5.9.3的openCV开发环境》《OpenCV开发笔记(一):OpenCV介绍、编译》《OpenCV开发笔记(二):cvui交互界面》《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》《OpenCV开发笔记(四):OpenCV图片和视频数据的读取与存储》《OpenCV开发笔记(五):OpenCV读取与操作摄像头》《OpenCV开发笔记(六):OpenCV基础数据结构、颜色转换函数和颜色空间》《OpenCV开发笔记(七):OpenCV基础图形绘制》《OpenCV开发笔记(八):OpenCV常用操作之计时、缩放、旋转、镜像》《OpenCV开发笔记(九):OpenCV区域图像(ROI)和整体、局部图像混合》《OpenCV开发笔记(十):OpenCV图像颜色通道分离和图像颜色多通道混合》《OpenCV开发笔记(十一):OpenCV编译支持Gpu(cuda) 加速开发之win-qt-mingw32编译》《OpenCV开发笔记(十二):OpenCV编译支持Gpu(cuda) 加速开发之win-qt-msvc2015编译(opencv3.4.0、cuda9.0、VS2015)》《OpenCV开发笔记(十三):OpenCV图像对比度、亮度的调整》《OpenCV开发笔记(十四):算法基础之线性滤波-方框滤波》《OpenCV开发笔记(十五):算法基础之线性滤波-均值滤波》《OpenCV开发笔记(十六):算法基础之线性滤波-高斯滤波》《OpenCV开发笔记(十七):算法基础之线性滤波对比-方框、均值、高斯滤波》《OpenCV开发笔记(十八):算法基础之非线性滤波-中值滤波》《OpenCV开发笔记(十九):算法基础之非线性滤波-双边滤波》《OpenCV开发笔记(二十):算法基础之非线性滤波对比-中值、双边滤波》《OpenCV开发笔记(二十一):算法基础之形态学滤波-膨胀》《OpenCV开发笔记(二十二):算法基础之形态学滤波-腐蚀》《OpenCV开发笔记(二十三):算法基础之形态学滤波-开运算》《OpenCV开发笔记(二十四):算法基础之形态学滤波-闭运算》《OpenCV开发笔记(二十五):算法基础之形态学滤波-形态学梯度》《OpenCV开发笔记(二十六):算法基础之形态学滤波-顶帽(礼帽)》《OpenCV开发笔记(二十七):算法基础之形态学滤波-黑帽》《OpenCV开发笔记(二十八):带你学习图像识别之阈值化》《OpenCV开发笔记(二十九):带你学习图像识别之自适应阈值》《OpenCV开发笔记(三十):带你学习图像识别之经典OTSU算法阈值化》《OpenCV开发笔记(三十一):红胖子8分钟带你深入了解双阈值化(图文并貌+浅显易懂+程序源码)》《OpenCV开发笔记(三十二):红胖子8分钟带你深入了解半阈值化(图文并貌+浅显易懂+程序源码)》《OpenCV开发笔记(三十三):红胖子8分钟带你深入了解漫水填充算法(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(三十四):红胖子带你傻瓜式编译Qt+openCV3.4.1+opencv_contrib(全网最浅显易懂)》《OpenCV开发笔记(三十五):红胖子8分钟带你深入了解ximgproc扩展模块中的自适应流行滤波器(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(三十六):红胖子8分钟带你深入了解缩放与图像金字塔(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(三十七):红胖子8分钟带你深入了解边缘检测和Canny算子边缘检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(三十八):红胖子8分钟带你深入了解高阶的Canny算子边缘检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(三十九):红胖子8分钟带你深入了解sobel算子边缘检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十):红胖子8分钟带你深入了解Laplacian(拉普拉斯)算子边缘检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十一):红胖子8分钟带你深入了解scharr滤波器算子边缘检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十二):红胖子8分钟带你深入了解标准霍夫线变换(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十三):红胖子8分钟带你深入了解累计概率霍夫线变换(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十四):红胖子8分钟带你深入了解霍夫圆变换(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十五):红胖子8分钟带你深入了解重映射(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十六):红胖子8分钟带你深入了解仿射变化(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十七):红胖子8分钟带你深入了解直方图(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十八):红胖子8分钟带你深入了解直方图均衡化(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(四十九):红胖子8分钟带你深入了解轮廓识别(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十):红胖子8分钟带你深入了解轮廓凸包(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十一):红胖子8分钟带你深入了解透视变换(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十二):红胖子8分钟带你深入了解直方图对比匹配(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十三):红胖子8分钟带你深入了解模板匹配识别(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十四):红胖子8分钟带你深入了解Haar级联分类器进行人脸检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十五):红胖子8分钟带你深入了解Haar、LBP特征以及级联分类器识别过程(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十八):红胖子8分钟带你深入了解图像的矩(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭算法(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十):红胖子8分钟带你深入了解Harris角点检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十一):红胖子8分钟带你深入了解Shi-Tomasi角点检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十二):红胖子8分钟带你深入了解亚像素角点检测(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十三):红胖子8分钟带你深入了解SIFT特征点(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十五):红胖子8分钟带你深入了解ORB特征点(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十六):红胖子8分钟带你总结形态学操作-膨胀、腐蚀、开运算、闭运算、梯度、顶帽、黑帽(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十七):红胖子8分钟带你深入了解特征点暴力匹配(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十八):红胖子8分钟带你使用特征点Flann最邻近差值匹配识别(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(六十九):红胖子8分钟带你使用传统方法识别已知物体(图文并茂+浅显易懂+程序源码)》《OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4》《OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练》《OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体》《OpenCV开发笔记(七十三):红胖子8分钟带你使用opencv+dnn+yolov3识别物体》《OpenCV开发笔记(七十四):OpenCV3.4.1+ffmpeg3.4.8交叉编译移植到海思平台Hi35xx平台》《深度学习:图像识别(匹配)方法|室内定位|论文与方法整理》持续补充中…OpenGL开发专栏《OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用》《OpenGL学习笔记(二):OpenGL语法、渲染管线以及具体实现过程详解》《OpenGL学习笔记(三):了解管线、VAO、VBO的关系,介绍Qt如何使用OpenGL》《OpenGL学习笔记(四):了解OpenGL、OpenGL的操作模式、特性和基本使用步骤》《OpenGL学习笔记(五):创建OpenGL工程模板前的所有准备工作》《OpenGL学习笔记(六):创建第一个VS2015 OpenGL工程模板(与平台无关)》《OpenGL学习笔记(七):创建第一个Qt5.9.3 OpenGL工程模版(与平台无关)》《OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形》《OpenGL学习笔记(九):索引缓冲器(EBO /IBE)的理解与使用,引入线框/填充模式》《OpenGL学习笔记(十):深入学习和理解着色器》《OpenGL学习笔记(十一):封装自己的着色器类》《OpenGL学习笔记(十二):纹理的使用》《OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结》持续补充中…FFmpeg、SDL和流媒体开发专栏《项目实战:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)》《项目实战:Qt+Ffmpeg+OpenCV相机程序(打开摄像头、支持多种摄像头、分辨率调整、翻转、旋转、亮度调整、拍照、录像、回放图片、回放录像)》《项目实战:Qt+ffmpeg摄像头检测工具》《live555开发笔记(一):live555介绍、windows上msvc2017编译和工程模板》《FFmpeg开发笔记(一):ffmpeg介绍、windows开发环境搭建(mingw和msvc,无需源码编译)》《FFmpeg开发笔记(二):ffmpeg在ubuntu编译以及开发环境搭建》《FFmpeg开发笔记(三):ffmpeg介绍、windows编译以及开发环境搭建》《FFmpeg开发笔记(四):ffmpeg解码的基本流程详解》《FFmpeg开发笔记(五):ffmpeg解码的基本流程详解(ffmpeg3新解码api)》《FFmpeg开发笔记(六):ffmpeg解码视频并使用SDL同步时间显示播放》《FFmpeg开发笔记(七):ffmpeg解码音频保存为PCM并使用软件播放》《FFmpeg开发笔记(八):ffmpeg解码音频并使用SDL同步音频播放》《FFmpeg开发笔记(九):ffmpeg解码rtsp流并使用SDL同步播放》《FFmpeg开发笔记(十):ffmpeg在ubuntu上的交叉编译移植到海思HI35xx平台》《FFmpeg开发笔记(十一):ffmpeg在移植到海思HI35xx平台之将ffmpeg库引入到sample的demo中》《SDL开发笔记(一):SDL介绍、编译使用以及工程模板》《SDL开发笔记(二):音频基础介绍、使用SDL播放音频》《SDL开发笔记(三):使用SDL渲染窗口颜色和图片》持续补充中…Onvif开发专栏《Onvif开发笔记(一):使用gSOAP编译Onvif协议之gSOAP介绍与编译》《Onvif开发笔记(二):使用gSOAP编译Onvif协议之编译Onvif代码框架》持续补充中…Rock Pi开发专栏《Rock Pi开发笔记(一):Rock Pi系列arm产品方案快速落地方案介绍》《Rock Pi开发笔记(二):入手Rock Pi 4B plus(基于瑞星微RK3399)板子并制作系统运行》《Rock Pi开发笔记(三):Rock Pi 4B plus(基于瑞星微RK3399)板子硬件资源介绍》持续补充中…Linux实用技巧《linux实用技巧:ubuntu18.04安装samba服务器实现局域网文件共享》《linux实用技巧:ubuntu18.04安装配置ibus中文输入法》《linux实用技巧:通过命令行安装deb软件包》《linux实用技巧:ubuntu16.04安装BeyondCompare文件/文件夹对比工具》《linux实用技巧:在虚拟机vmware16软件上安装CentOs8.2虚拟机,重置可用源和安装输入法》《linux实用技巧:cp时自动将软链接所指定的文件实体也一起copy(软链接将会变成目标文件实体)》《linux实用技巧:获取当前系统显示分辨率"xrandr --current"》《linux实用技巧:ubuntu16.04 64位系统安装32位系统兼容包并修改dash(缺省)为bash》《shell实用技巧:文件统计信息和银行账户管理系统》《linux实用技巧:使用脚本获取活动网卡的mac地址》《linux实用技巧:从另一台机子上拷贝文件到本机,从本机拷贝文件到另一台机子(远程拷贝scp)》《linux实用技巧:ubuntu从零开始拉取远程git空仓库并提交代码及git相关其他问题》持续补充中...国产麒麟系统相关开发《麒麟系统开发笔记(一):国产麒麟系统搭建开发环境之虚拟机安装》《麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12》《麒麟系统开发笔记(三):从Qt源码编译安装之编译安装Qt5.12》《麒麟系统开发笔记(四):从Qt源码编译安装之编译安装QtCreator4.8.1,并配置编译测试Demo》持续补充中...硬件相关开发《硬件开发笔记(一):高速电路设计Cadence Aleegro软件介绍和安装过程》《硬件开发笔记(二):硬件开发基本流程,制作一个USB转RS232的模块(一):开发基本过程和元器件选型》《硬件开发笔记(三):硬件开发基本流程,制作一个USB转RS232的模块(二):设计原理图库》《硬件开发笔记(四):硬件开发基本流程,制作一个USB转RS232的模块(三):设计原理图》《硬件实用技巧:OrCad自带原理图olb/OLB库枚举介绍》持续补充中...单片机相关开发《stm32开发笔记(一):库函数V3.5版本环境搭建以及工程模版配置》《stm32开发笔记(二):stm32系列使用V3.5固件库的帮助文件以及GPIO基本功能》《stm32开发笔记(三):stm32系列的GPIO基本功能之输出驱动LED灯、输入按键KEY以及Demo》《stm32实用技巧:JLINK接口定义和使用JTAG或SW下载程序》《关于 通过jlink使用jtag(或swd)下载程序成功后,keil4 uversion停止运行 的解决方法》数据库相关开发《Qt实用技巧:Qt连接SQL Server数据库(需要配置ODBC)》《项目实战:Qt+Sql server英汉汉英电子词典》《sqlite实用技巧:查询表数据时,使用列对齐,显示表头》《MySql开发笔记:MySql数据库服务搭建以及建表脚本导入》《SQL不完全手册(一):概念和基础语句》《SQL不完全手册(二):高级语句》《SQL不完全手册(三):函数》程序员PS技能《程序员PS技能(一):PS2017基本框架使用》《程序员PS技能(二):程序员切图最常使用的工具组-选择工具组》《程序员PS技能(三):程序员使用PSD源文件切图》《程序员PS技能(四):程序员创建PSD文件、展示简单PSD设计流程,上传PSD至蓝湖,并下载Demo切图》持续补充中…其他(编程相关)《关于 SecureFx传输远程服务器中文显示乱码 的解决方法》《关于 腾讯云CentOS8.2重置恢复到自定义镜像后,第三方软件登陆提示需要密钥 的解决方法》《公司官网建站笔记(一):腾讯云服务器装CentOS8.2系统、重置密码、远程ssh登陆、sftp传递文件以及新建开发者账户》《公司官网建站笔记(二):在云服务器部署PHP服务(公网访问首页)》《公司官网建站笔记(三):腾讯云服务器CentOS8.2安装界面环境,使用vnc远程登陆并搭建轻量级Qt服务器》《关于 SVN状态图标不显示的问题(只显示绿色钩匹配) 的解决方法》《vm虚拟机安装CentOS8.2服务器系统》《CentOS8安装Geant4笔记(一):Geant4介绍、编译和安装》《CentOS8安装Geant4笔记(二):CentOS8安装Qt5.15.2并测试运行环境》《CentOS8安装Geant4笔记(三):Geant4介绍、编译、安装支持Qt5界面并运行exampleB1例程显示Qt界面》《获取下载Qt安装包,Qt源码全国网址备忘录(不用注册Qt账户,即可下载各版本Qt安装包和Qt源码包)》《台达PLC开发笔记(一):台达PLC连接介绍,分别使用485、网口与台达PLC建立连接》《台达PLC开发笔记(二):台达PLC设置主机通讯参数为RTU并成功通讯》《NSIS制作安装包笔记(一):NSIS介绍、使用NSIS默认向导脚本制作Windows安装包》《NSIS制作安装包笔记(二):NSIS使用NSIS+Qt界面制作安装包流程》《NSIS安装包开发笔记(三):NSIS使用Qt做的安装界面制作安装包交互详解》《西门子PLC开发笔记(一):PLC介绍,西门子S1200系列接线、编程、下载和仿真》《实用技巧:阿里云服务器建立公网物联网服务器(解决阿里云服务器端口,公网连接不上的问题)》《关于 百度飞浆paddleOCR编译32位版本 的解决方案》《Basic语言开发笔记:Basic语言介绍、环境搭建、基本语法示例与程序实例》《Mqtt开发笔记:Mqtt服务器搭建》《C++ STL开发温习与总结(一): 1.C++编程技术》《C++ STL开发温习与总结(二): 2.C++存储技术》《C++ STL开发温习与总结(三): 3.C++函数技术》《C++ STL开发温习与总结(四): 4.C++面向对象机制的实现》《C++ STL开发温习与总结(五): 5.C++标准库简介》《C++STL开发温习与总结(六): 6.C++语言输入/输出流定义之输入/输出格式控制》《C++拷贝构造函数(深拷贝,浅拷贝)详解》《C++运算符重载详解》《C++实用技巧:公交换乘算法》《VS2017编写MFC库以及使用Qt调用MFC库方法》《关于 ubuntu18.04使用QtCcreator无法输入中文 的解决方法》《架设个人FTP服务器的两种方法》《gprs实用技巧:gprs模块tcp连接稳定性测试》《c实用技巧:纯c对于excel数据表的处理》《c实用技巧:文件统计信息和银行账户管理系统》《VS2017编写纯C库以及使用C#调用C库方法》《关于 C#调用C库Dll,有回调函数时,只执行一次回调函数就直接挂掉 的解决方法》《关于 VS调试时出现“当前不会命中断点。还没有为该文将加载任何符号。” 的解决方法》《关于 C#调用一个C/C++dll库运行时实现多个应用(静态变量区分) 的解决方法》《C#实用技巧:创建并操作access数据库(可无密,也可加密)》《关于 C#调用c库,将C#的byte[]传入C库的方法和将C库的char*向上传入C#的回调函数byte[] 的方法》《直播技术:如何实现1080P延迟低于500ms的实时超清直播传输技术》其他(非编程相关)《关于 Photoshop20xx系列启动出现“应用程序无法正常启动(0xc0000022)“无法启动 的解决方法》《红胖子创业一年整总结:前二十年题记,萌芽初期,外包初期,创业初期,未来规划》《人到中年不如狗,只因年轻时消耗了青春,误了芳华》《学会生命倒计时法,就是精彩生活的开始》《比有钱更重要的,是拥有“选择权”(深度好文)》《关于 车机U盘音乐歌曲名显示乱码bug 的解决方法》《关于 谷歌浏览器主页被劫持的 解决方法》《红胖子 = 红 + 胖子 = 红(红模仿) + 胖子 --- 2007.6 ~ 至永远》《人到中年,没事多休息,有空多赚钱!》《研发团队管理:IT研发中项目和产品原来区别那么大,项目级的项目是项目,产品级的项目是产品!!!》《写给人生的九封信,愿你的人生淡定从容,繁华似锦!!!》《认怂,是中年人最大的优点》《基金:实战,连涨7天,8天到底抛还留?爱吹牛的赵吹吹又来了》《关于 在word中插入的表格跨页后每一页都显示标题栏 的解决方法》《一个人越想赚钱,就越要改掉这3个习惯,否则注定穷一辈子》《做人最大的无知,是错把平台当本事(深度好文)》《为人处世,请从学会闭嘴开始!》《开发笔记之数字证书(一):数字证书基本情况介绍》《开发笔记之数字证书(二):国内数字证书企业与行情介绍》《word Ctrl Z 撤销功能无法使用怎么办?》《U盘使用技巧:U盘自动启运行应用程序(autorun.inf无法运行终极解决方案)》《关于 win10远程桌面(家庭版)无法连接 的傻瓜式解决方法》《关于 chm帮助文档右边内容区域无法显示 的解决方法》《关于 电脑分配IP地址可以连接局域网但无法上互联网 的解决方法》《关于 移动硬盘数据丢失问题 的解决方法》《关于 ubuntu14.04有输入法但是无法输入中文 的解决方法》《PS实用技巧:用原始图片制作显示(正常状态)、鼠标悬浮(hover)、鼠标点击(pressed)的方法》
前言 Qt在地图方面的研发。百度地图介绍 百度的地图分为多个开发,都是在线的(离线的需要自己提取,本篇解说在线地图)。 百度地图JavaScript API支持HTTP和HTTPS,免费对外开放,可直接使用。接口使用无次数限制。在使用前,您需先申请密钥才可使用。 目前百度可使用的在线API分为四个版本:JavaScript API Lite 百度地图JavaScript API Lite 版是一套由JavaScript语言编写的应用程序接口。能够帮助您在移动端浏览器上构建地图应用。和JavaScript API标准版相比,Lite版专门针对移动端H5页面的使用场景,代码体积小,性能更好。 因为Lite版不支持PC浏览器,开发指南中不同功能相应页面最后均提供二维码,请使用手机扫描体验。JavaScript API GL 百度地图JavaScript API GL v1.0是一套由JavaScript语言编写的应用程序接口,可帮助您在网站中构建功能丰富、交互性强的地图应用,支持PC端和移动端基于浏览器的地图应用开发,且支持HTML5特性的地图开发。JavaScript API v2.0 百度地图JavaScript API是一套由JavaScript语言编写的应用程序接口,可帮助您在网站中构建功能丰富、交互性强的地图应用,支持PC端和移动端基于浏览器的地图应用开发,且支持HTML5特性的地图开发。JavaScript API v3.0 度地图JavaScript API是一套由JavaScript语言编写的应用程序接口,可帮助您在网站中构建功能丰富、交互性强的地图应用,支持PC端和移动端基于浏览器的地图应用开发,且支持HTML5特性的地图开发。申请密钥 申请地址:http://lbsyun.baidu.com/apiconsole/key?application=key网页调试Html源码<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>地图展示</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <style> body, html, #container { overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: "微软雅黑"; .info { z-index: 999; width: auto; min-width: 22rem; padding: .75rem 1.25rem; margin-left: 1.25rem; position: fixed; top: 1rem; background-color: #fff; border-radius: .25rem; font-size: 14px; color: #666; box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5); </style> <!-- <script src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=填你的AK"></script> --> <!-- <script src="http://api.map.baidu.com/api?type=webgl&v=1.0&ak=填你的AK"></script> --> <!-- <script src="http://api.map.baidu.com/api?type=webgl&v=2.0&ak=填你的AK"></script> --> <script src="http://api.map.baidu.com/api?type=webgl&v=3.0&ak=填你的AK"></script> </head> <body> <div class = "info">最新版GL地图命名空间为BMapGL, 可按住鼠标右键控制地图旋转、修改倾斜角度。</div> <div id="container"></div> </body> </html> <script> var map = new BMapGL.Map('container'); // 创建Map实例 map.centerAndZoom(new BMapGL.Point(116.404, 39.915), 12); // 初始化地图,设置中心点坐标和地图级别 map.enableScrollWheelZoom(true); // 开启鼠标滚轮缩放 </script> 以上代码请注意: 运行结果 Demo加载代码_pWebEngineView = new QWebEngineView(this); _pWebEnginePage = new QWebEnginePage(this); _pWebChannel = new QWebChannel(this); LOG << QFile::exists(_indexFilePath); _pWebEnginePage->load(QUrl(_indexFilePath)); _pWebEnginePage->setWebChannel(_pWebChannel); _pWebEngineView->setPage(_pWebEnginePage);运行结果 工程模板:v1.0.0 mapDemo_v1.0.0_基础模板_调用百度在线地图工程模板.rar
前言 在pc上搭建流媒体服务器软件,打开视频接受推流,使用live555方案。live555介绍 Live555是一个为流媒体提供解决方案的跨平台的C++开源项目,它实现了标准流媒体传输,是一个为流媒体提供解决方案的跨平台的C++开源项目,它实现了对标准流媒体传输协议如RTP/RTCP、RTSP、SIP等的支持。Live555实现了对多种音视频编码格式的音视频数据的流化、接收和处理等支持,包括MPEG、H.263+ 、DV、JPEG视频和多种音频编码。同时由于良好的设计,Live555非常容易扩展对其他格式的支持。Live555已经被用于多款播放器的流媒体播放功能的实现,如VLC(VideoLan)、MPlayer。 Live555既可以开发客户端拉流、推流也可以开发Live555流媒体服务器。live555下载 官网地址:http://www.live555.com/ QQ群:1047134658(点击“文件”搜索“live555”,群内与博文同步更新)live555在Win10系统vs2017上的编译步骤一:下载,解压 步骤二:使用VS2017建立空项目 步骤三:将live555的源代码复制并添加到工程当中 需要包含头文件路径 步骤四:将工程的目标改为静态库 步骤五:编译出现_CRT_SECURE_NO_WARINGS等问题,解决 添加两个宏_CRT_SECURE_NO_WARNINGS _WINSOCK_DEPRECATED_NO_WARNINGS 步骤六:编译成功,继续生成release库 切换release后,需要重头添加库路径和宏文件,重复步骤三四五。 步骤七:整理四个版本的库和头文件 模块化 Demovoid Live555Manager::testEnv() qDebug() << __FILE__ << __LINE__ << BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING; qDebug() << __FILE__ << __LINE__ << USAGEENVIRONMENT_LIBRARY_VERSION_STRING; qDebug() << __FILE__ << __LINE__ << GROUPSOCK_LIBRARY_VERSION_STRING; }运行结果 工程模板v1.0.0 对应工程模板:live555Demo_v1.0.0_基础模板_运行环境测试.rar
前言 Qt使用一些压缩解压功能,选择libzip库,libzip库比较原始,也是很多其他库的基础支撑库。libzip libzip是一个C库,用于读取,创建和修改zip档案。可以从数据缓冲区,文件或直接从其他zip归档文件直接复制的压缩数据中添加文件。在不关闭存档的情况下所做的更改可以还原。 当前版本是1.7.3,于2020年7月15日发布。 官网:https://libzip.org/ QQ群:1047134658(点击“文件”搜索“libzip”,群内与博文同步更新)libzip编译步骤一:解压步骤二:Cmake配置(vs2017 x64版本) 需要zlib,之前已经编译过vs2017 x64版本的zlib了,导入再配置步骤三:生成工程步骤四:打开VS2017编译步骤五:安装install模块化补充:查看命令行工具帮助和源码辅助开发ziptool.exe -h usage: ziptool.exe [-ceghnrst] [-l len] [-o offset] archive command1 [args] [command2 [args] ...] Supported options are: -c check consistency -e error if archive already exists (only useful with -n) -g guess file name encoding (for stat) -h display this usage -l len only use len bytes of file -n create archive if it doesn't exist -o offset start reading file at offset -r print raw file name encoding without translation (for stat) -s follow file name convention strictly (for stat) -t disregard current archive contents, if any Supported commands and arguments are: add name content add file called name using content add_dir name add directory add_file name file_to_add offset len add file to archive, len bytes starting from offset add_from_zip name archivename index offset len add file from another archive, len bytes starting from offset cat index output file contents to stdout count_extra index flags show number of extra fields for archive entry count_extra_by_id index extra_id flags show number of extra fields of type extra_id for archive entry delete index remove entry delete_extra index extra_idx flags remove extra field delete_extra_by_id index extra_id extra_index flags remove extra field of type extra_id get_archive_comment show archive comment get_extra index extra_index flags show extra field get_extra_by_id index extra_id extra_index flags show extra field of type extra_id get_file_comment index get file comment get_num_entries flags get number of entries in archive name_locate name flags find entry in archive print_progress print progress during zip_close() rename index name rename entry replace_file_contents index data replace entry with data set_archive_comment comment set archive comment set_extra index extra_id extra_index flags value set extra field set_file_comment index comment set file comment set_file_compression index method compression_flags set file compression method set_file_dostime index time date set file modification time and date (DOS format) set_file_encryption index method password set file encryption method set_file_mtime index timestamp set file modification time set_file_mtime_all timestamp set file modification time for all files set_password password set default password for encryption stat index print information about entry Supported flags are: 0 (no flags) C ZIP_FL_NOCASE c ZIP_FL_CENTRAL d ZIP_FL_NODIR l ZIP_FL_LOCAL u ZIP_FL_UNCHANGED Supported compression methods are: default deflate store Supported encryption methods are: AES-128 AES-192 AES-256 PKWARE The index is zero-based.工程模板v1.0.0 对应工程模板:zipDemo_v1.0.0_基础模板_zip库的基础环境.rar
需求 1. 全屏软键盘; 2. 输入英文; 3. 输入中文; 4. 支持触摸、键盘和输入混合输入; 5. 目前有黑色系皮肤; 6. Qt4和Qt5区分2个版本;Demo:Qt5 CSDN(粉丝免积分下载):https://download.csdn.net/download/qq21497936/13945327 QQ群:1047134658(点击“文件”搜索“softKeyboard”,群内与博文同步更新)Demo:Qt4 移植到MCGS嵌入式工控机上 V1.0.0 Demo代码 可视化的布局,以便于定制修改,所见即所得: KeyBoardWidget.h#ifndef KEYBOARDWIDGET_H #define KEYBOARDWIDGET_H #include <QWidget> #include <QPushButton> #include <QLabel> namespace Ui { class KeyBoardWidget; class KeyBoardWidget : public QWidget Q_OBJECT private: enum INPUT_MODE { INPUT_MODE_ZH = 0x01, INPUT_MODE_EN, INPUT_MODE_SYMB, public: explicit KeyBoardWidget(QWidget *parent = 0); ~KeyBoardWidget(); public: void clearChineseCache(); void setKeyPressEvent(QKeyEvent *event); signals: void signal_sendKeyToFocusItem(QString keyText); protected: void updateChineseCharactersButtonState(); void switchLanguage(int inputMode); void searchChineseCharacters(int currentpage); protected slots: void slot_characterButtonsClicked(); void slot_switchLanguage(); void slot_backspace(); void slot_blankspace(); void slot_chineseCharacterSelected(); void slot_chineseCharacterPrevious(); void slot_chineseCharacterNext(); void slot_enter(); void slot_upper(); void slot_symbols(); void slot_emoji(); void slot_hideKeyboard(); protected: void updateKeyboard(); protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void showEvent(QShowEvent *event); void hideEvent(QHideEvent *event); private: Ui::KeyBoardWidget *ui; private: QList<QPushButton*> _listCharacterBtns; QList<QPushButton*> _listChineseCharactersBtns; INPUT_MODE _currentMode; INPUT_MODE _lastMode; bool _upperMode; int _symbolPage; QFont _font; private: static QString _strKeyboradCharacters; static QString _strKeyBoradSymbols[]; #endif // KEYBOARDWIDGET_H KeyBoardWidget.cpp#include "KeyBoardWidget.h" #include "ui_KeyBoardWidget.h" #include <QLabel> #include <QPushButton> #include <QVBoxLayout> #include <QHBoxLayout> #include <QFontDatabase> #include <QFile> #include <QApplication> #include <QMouseEvent> #include <QDebug> #include <QDesktopWidget> KeyBoardWidget::KeyBoardWidget(QWidget *parent) : QWidget(parent), ui(new Ui::KeyBoardWidget), _currentMode(INPUT_MODE_EN), _upperMode(false), _symbolPage(0) ui->setupUi(this); this->setFixedSize(qApp->desktop()->width(), 380); //设置主窗体样式 setWindowFlags(windowFlags() | Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus); //图标字体 int fontId = QFontDatabase::addApplicationFont(":/font/res/FontAwesome.otf"); QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0); _font.setFamily(fontName); _font.setPixelSize(24); // 中文汉字按键存入列表 _listChineseCharactersBtns.append(ui->pushButton_r1); _listChineseCharactersBtns.append(ui->pushButton_r2); _listChineseCharactersBtns.append(ui->pushButton_r3); _listChineseCharactersBtns.append(ui->pushButton_r4); _listChineseCharactersBtns.append(ui->pushButton_r5); for(int index = 0; index < _listChineseCharactersBtns.size(); index++) connect(_listChineseCharactersBtns.at(index), SIGNAL(clicked(bool)), this, SLOT(slot_chineseCharacterSelected())); // 翻页按键 ui->pushButton_prev->setFont(_font); ui->pushButton_prev->setText(QString(QChar(0xf0d9))); connect(ui->pushButton_prev, SIGNAL(clicked(bool)), this, SLOT(slot_chineseCharacterPrevious())); ui->pushButton_next->setFont(_font); ui->pushButton_next->setText(QString(QChar(0xf0da))); connect(ui->pushButton_next, SIGNAL(clicked(bool)), this, SLOT(slot_chineseCharacterNext())); // 字符按键存入列表 _listCharacterBtns.append(ui->pushButton_c1); _listCharacterBtns.append(ui->pushButton_c2); _listCharacterBtns.append(ui->pushButton_c3); _listCharacterBtns.append(ui->pushButton_c4); _listCharacterBtns.append(ui->pushButton_c5); _listCharacterBtns.append(ui->pushButton_c6); _listCharacterBtns.append(ui->pushButton_c7); _listCharacterBtns.append(ui->pushButton_c8); _listCharacterBtns.append(ui->pushButton_c9); _listCharacterBtns.append(ui->pushButton_c10); _listCharacterBtns.append(ui->pushButton_c11); _listCharacterBtns.append(ui->pushButton_c12); _listCharacterBtns.append(ui->pushButton_c13); _listCharacterBtns.append(ui->pushButton_c14); _listCharacterBtns.append(ui->pushButton_c15); _listCharacterBtns.append(ui->pushButton_c16); _listCharacterBtns.append(ui->pushButton_c17); _listCharacterBtns.append(ui->pushButton_c18); _listCharacterBtns.append(ui->pushButton_c19); _listCharacterBtns.append(ui->pushButton_c20); _listCharacterBtns.append(ui->pushButton_c21); _listCharacterBtns.append(ui->pushButton_c22); _listCharacterBtns.append(ui->pushButton_c23); _listCharacterBtns.append(ui->pushButton_c24); _listCharacterBtns.append(ui->pushButton_c25); _listCharacterBtns.append(ui->pushButton_c26); _listCharacterBtns.append(ui->pushButton_c27); _listCharacterBtns.append(ui->pushButton_c28); _listCharacterBtns.append(ui->pushButton_c29); for(int index = 0; index < _strKeyboradCharacters.size(); index++) _listCharacterBtns.at(index)->setText(_strKeyboradCharacters.at(index)); connect(_listCharacterBtns.at(index), SIGNAL(clicked(bool)), this, SLOT(slot_characterButtonsClicked())); // 功能键:回退 ui->pushButton_backspace->setText(QChar(0xf060)); ui->pushButton_backspace->setFont(_font); connect(ui->pushButton_backspace, SIGNAL(clicked(bool)), this, SLOT(slot_backspace())); // 功能键:大小写 ui->pushButton_upper->setFont(_font); ui->pushButton_upper->setText(QChar(0xf062)); connect(ui->pushButton_upper, SIGNAL(clicked(bool)), this, SLOT(slot_upper())); // 功能键:回车 ui->pushButton_enter->setFont(_font); ui->pushButton_enter->setText("Enter"); connect(ui->pushButton_enter, SIGNAL(clicked(bool)), this, SLOT(slot_enter())); // 功能键:切换符号 ui->pushButton_symbol->setText(".?123"); connect(ui->pushButton_symbol, SIGNAL(clicked(bool)), this, SLOT(slot_symbols())); // 功能键:语言切换 ui->pushButton_language->setText("English"); connect(ui->pushButton_language, SIGNAL(clicked(bool)), this, SLOT(slot_switchLanguage())); // 功能键:空格 ui->pushButton_blankspace->setText(""); connect(ui->pushButton_blankspace, SIGNAL(clicked(bool)), this, SLOT(slot_blankspace())); // 功能键:表情 ui->pushButton_emoji->setFont(_font); ui->pushButton_emoji->setText(QChar(0xf118)); connect(ui->pushButton_emoji, SIGNAL(clicked(bool)), this, SLOT(slot_emoji())); // 功能键:隐藏 ui->pushButton_hideKeyboard->setFont(_font); ui->pushButton_hideKeyboard->setText(QString(QChar(0xf11c)).append(QChar(0xf103))); connect(ui->pushButton_hideKeyboard, SIGNAL(clicked(bool)), this, SLOT(slot_hideKeyboard())); updateChineseCharactersButtonState(); KeyBoardWidget::~KeyBoardWidget() delete ui; void KeyBoardWidget::setKeyPressEvent(QKeyEvent *event) if(_currentMode == INPUT_MODE_SYMB && _symbolPage == 0) switch (event->key()) case Qt::Key_1: _listCharacterBtns.at(0)->click(); break; case Qt::Key_2: _listCharacterBtns.at(1)->click(); break; case Qt::Key_3: _listCharacterBtns.at(2)->click(); break; case Qt::Key_4: _listCharacterBtns.at(3)->click(); break; case Qt::Key_5: _listCharacterBtns.at(4)->click(); break; case Qt::Key_6: _listCharacterBtns.at(5)->click(); break; case Qt::Key_7: _listCharacterBtns.at(6)->click(); break; case Qt::Key_8: _listCharacterBtns.at(7)->click(); break; case Qt::Key_9: _listCharacterBtns.at(8)->click(); break; case Qt::Key_0: _listCharacterBtns.at(9)->click(); break; case Qt::Key_Backspace: ui->pushButton_backspace->click(); break; case Qt::Key_Return: ui->pushButton_enter->click(); break; default: break; switch (event->key()) case Qt::Key_Q: _listCharacterBtns.at(0)->click(); break; case Qt::Key_W: _listCharacterBtns.at(1)->click(); break; case Qt::Key_E: _listCharacterBtns.at(2)->click(); break; case Qt::Key_R: _listCharacterBtns.at(3)->click(); break; case Qt::Key_T: _listCharacterBtns.at(4)->click(); break; case Qt::Key_Y: _listCharacterBtns.at(5)->click(); break; case Qt::Key_U: _listCharacterBtns.at(6)->click(); break; case Qt::Key_I: _listCharacterBtns.at(7)->click(); break; case Qt::Key_O: _listCharacterBtns.at(8)->click(); break; case Qt::Key_P: _listCharacterBtns.at(9)->click(); break; case Qt::Key_A: _listCharacterBtns.at(10)->click(); break; case Qt::Key_S: _listCharacterBtns.at(11)->click(); break; case Qt::Key_D: _listCharacterBtns.at(12)->click(); break; case Qt::Key_F: _listCharacterBtns.at(13)->click(); break; case Qt::Key_G: _listCharacterBtns.at(14)->click(); break; case Qt::Key_H: _listCharacterBtns.at(15)->click(); break; case Qt::Key_J: _listCharacterBtns.at(16)->click(); break; case Qt::Key_K: _listCharacterBtns.at(17)->click(); break; case Qt::Key_L: _listCharacterBtns.at(18)->click(); break; case Qt::Key_Z: _listCharacterBtns.at(19)->click(); break; case Qt::Key_X: _listCharacterBtns.at(20)->click(); break; case Qt::Key_C: _listCharacterBtns.at(21)->click(); break; case Qt::Key_V: _listCharacterBtns.at(22)->click(); break; case Qt::Key_B: _listCharacterBtns.at(23)->click(); break; case Qt::Key_N: _listCharacterBtns.at(24)->click(); break; case Qt::Key_M: _listCharacterBtns.at(25)->click(); break; case Qt::Key_Comma: _listCharacterBtns.at(26)->click(); break; case Qt::Key_Period: _listCharacterBtns.at(27)->click(); break; case Qt::Key_Question: _listCharacterBtns.at(28)->click(); break; case Qt::Key_Backspace: ui->pushButton_backspace->click(); break; case Qt::Key_Space: ui->pushButton_blankspace->click(); break; case Qt::Key_Return: ui->pushButton_enter->click(); break; case Qt::Key_CapsLock: ui->pushButton_upper->click(); break; default: break;
前言 Qt开发Xml相关技术,使用到tinyxml2库。TinyXML TinyXML是一个简单的、小的C++的XML解析器,可以集成到其他程序中。它是ROS的标准XML解析器。 最新的已经是TinyXML2版本了。 github下载地址:https://github.com/leethomason/tinyxml2 CSDN下载地址:https://download.csdn.net/download/qq21497936/13944558 QQ群:1047134658(点击“文件”搜索“tinyxml2”,群内与博文同步更新)TinyXML编译步骤一:解压步骤二:Cmake配置 直接强上,先修改C编译器的 然后修改CXX编译器的步骤三:生成工程步骤四:命令行编译步骤五:安装install模块化Demovoid TinyXmlManager::testEnv() // 测试创建一个简单html文件 tinyxml2::XMLDocument doc; // 添加第一行 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); // 添加第一个节点 // 添加第一个节点中的属性 <ofd:OFD xmlns:ofd="http://www.ofdspec.org" DocType="OFD" Version="1.0"> tinyxml2::XMLElement * pXmlElement; pXmlElement = doc.NewElement("ofd:OFD"); pXmlElement->SetAttribute("xmlns:ofd", "http://www.ofdspec.org"); pXmlElement->SetAttribute("DocType", "OFD"); pXmlElement->SetAttribute("Version", "1.0"); // 子节点 <ofd:DocBody> tinyxml2::XMLElement * pXmlElement2; pXmlElement2 = doc.NewElement("ofd:DocBody"); pXmlElement2->SetAttribute("Author", "红模仿"); pXmlElement2->SetAttribute("QQ", 21497936); pXmlElement2->SetAttribute("Blog", "https://blog.csdn.net/qq21497936"); pXmlElement->InsertEndChild(pXmlElement2); doc.InsertEndChild(pXmlElement); // 保存 doc.SaveFile("1.xml"); }测试结果工程模板v1.0.0 对应工程模板:tinyXmlDemo_v1.0.0_基础工程_运行环境测试.rar
问题 经常弄编译,CMake可视化界面配置一些CMake工程的时候,主要是windows下的mingw32版本的,经常会出现c和cxx编译器过不去的情况,其实路径都没有问题,尝试多种方法并且解决了,如重装系统,换cmake版本,但是不可能遇到每次都换。原理 其实检查编译器这个步骤我们可以判断是没问题的,所以直接在检测C和CXX两个脚本上去掉这2个检查即可。修改文件两个文件所在文件夹:C:\CMake\share\cmake-3.10\ModulesC检查脚本路径:CMakeTestCCompiler.cmakeCXX检查脚本路径:CMakeTestCXXCompiler.cmake测试通过
需求 1. 双Y轴段曲线; 2. 拽拖分析已有数据; 3. 支持悬浮显示当前最近x的各段y坐标; 4. 优化显示性能以及缓存; 5. 支持各种有颜色的调整‘; 6. 读取文件或者下位机数据;相关博客 《案例分享:Qt高频fpga采集数据压力位移速度加速度分析系统(通道配置、电压转换、采样频率、通道补偿、定时采集、距离采集,导出exce、自动XY轴、隐藏XY轴、隐藏显示通道,文件回放等等)》 《案例分享:Qt多段Y轴折线图框架(双Y轴段折线、支持拽拖、浮动游标显示X值各段Y值、支持大量实时显示下位机数据)》 《案例分享:Qt便携式致病菌快速检测仪(账号管理、实验过程、二维图表、历史数据、通讯管理、实验报告、中英文等等)》 《案例分享:Qt多通道数据采集系统(通道配置、电压转换、采样频率、通道补偿值、定时采集、导出excel和图表、自动XY轴、隐藏XY轴、实时隐藏显示通道)》 《Qt开发笔记之QCustomPlot:QCustomPlot介绍、编译与使用》 《Qt开发笔记之Qwt(一):Qwt介绍、编译与Demo》注意 Qt相关的二维折线图,采用其他方式都无法实现多段Y轴(非双Y轴,单Y轴多段),包括QCharts、QCustomPlot、Qwt,其他已有的框架内嵌web可实现,基于需要实时采集数据,内嵌web实时体验并不好,于是写了个基础框架,以便实现实时数据的大量采集。Demo 体验下载地址 CSDN(粉丝免积分下载):https://download.csdn.net/download/qq21497936/13777399 QQ群:1047134658(点击“文件”搜索“chartDemo”,群内与博文同步更新)V1.1.0 Demo部分源码#ifndef LINECHART2WIDGET_H #define LINECHART2WIDGET_H #include <QWidget> #include <QColor> #include <QPainter> #include <QMouseEvent> #include <QPointF> class LineChart2Widget : public QWidget Q_OBJECT public: explicit LineChart2Widget(QWidget *parent = nullptr); public: void addData(QVector<QPointF> vectorPoint); void setData(QVector<QPointF> vectorPoint); void clear(); void addData2(QVector<QPointF> vectorPoint); void setData2(QVector<QPointF> vectorPoint); void clear2(); protected: QPointF realConvertToChart(QPointF pointF); // 实际点转为图表点坐标 QPointF chartConvertToReal(QPointF pointF); // 图表点坐标转为实际点 QVector<QPointF> realConvertToChart(QVector<QPointF> vectorPointF); // 实际点转为图表点坐标 QPointF realConvertToChart2(QPointF pointF); // 实际点转为图表点坐标 QPointF chartConvertToReal2(QPointF pointF); // 图表点坐标转为实际点 QVector<QPointF> realConvertToChart2(QVector<QPointF> vectorPointF); // 实际点转为图表点坐标 protected: void paintEvent(QPaintEvent *event); void showEvent(QShowEvent *event); void resizeEvent(QResizeEvent *event); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); protected: void drawBackground(QPainter *painter); // 绘制背景 void drawMarginBackground(QPainter *painter); // 绘制边框背景(边框的) void drawAxis(QPainter *painter); // 绘制坐标轴 void drawLabel(QPainter *painter); // 绘制坐标值 void drawLines(QPainter *painter); // 绘制曲线 void drawCursorRealValue(QPainter *painter); // 绘制实际值 void drawMouseCross(QPainter *painter); // 绘制鼠标的十字线 void drawTwoValue(QPainter *painter); // 绘制双轴的X,Y值(最近接X轴的上一个Y点) private: double _leftMargin; // 左边距离(坐标轴距离左部边框) double _rightMargin; // 右边距离(坐标轴距离右部边框) double _bottomMargin; // 底部距离(坐标轴距离底部边框) double _topMargin; // 顶部距离(坐标轴距离顶部边框) double _left; // 左部x坐标 double _right; // 右部x坐标 double _top; // 顶部y坐标 double _bottom; // 底部y坐标 double _width; // 宽度 double _height; // 高度 double _minX; // x轴最小值 double _maxX; // x轴最大值 QColor _backgroundColor; // 背景颜色 QColor _axisColor; // 坐标轴颜色 QColor _axisLabelColor; // 坐标轴文本颜色 QColor _lineColor; // 折线颜色 QColor _dataColor; // 矩形文字颜色 QColor _dataBackgroundColor;// 矩形背景颜色 int _xTickCount; // X轴主tick int _xTickLength; // X轴主tick长度 int _xSubTickCount; // X轴子tick int _xSubTickLength; // X轴子tick长度 double _xTickDistance; // 临时变量: double _xSubTickDistance; // 临时变量: double _xTickValue; // 临时变量: double _xSubTickValue; // 临时变量: double _xTickValueScale; // 临时变量: double _xSubTickValueScale; // 临时变量: bool _leftButtonPressed; // 临时变量:鼠标左键是否按下 QPointF _originPointF; // 临时变量:记录鼠标左键按下的坐标 QPointF _offsetPointF; // 临时变量:偏移的坐标段 QPointF _zeroPointF; // 零点,用于区分x轴和y轴的坐标 QPointF _nowPointF; // 临时变量:零点 double _scale; // 缩放比例 QVector<QPointF> _vectorPointF; // 一条线的存储位置 QVector<QPointF> _vectorPointF2; // 一条线的存储位置 bool _showCursorRealValue; // 是否显示鼠标当前de的值 bool _canDragYAxis; // Y轴是否允许被拖动 bool _showCrossAxis; // 画十字轴 private: int _yAxisNumber; // 几段Y轴 int _yAxisSpace; // Y轴间距 double _yAxisHeight; // 每一段Y轴高度 double _offsetY; // 临时变量: int _yTickCount; // Y轴分的主tick int _yTickLength; // Y轴主tick长度 int _ySubTickCount; // Y轴两个大tick之间的小tick int _ySubTickLength; // Y轴子tick长度 double _yTickDistance; // 临时变量: double _ySubTickDistance; // 临时变量: private: QString _yAxisContent; // 第一段Y轴内容 double _yTickValue; // 临时变量: double _ySubTickValue; // 临时变量: double _yTickValueScale; // 临时变量: double _ySubTickValueScale; // 临时变量: private: QString _yAxisContent2; // 第一段Y轴内容 double _yTickValue2; // 临时变量: double _ySubTickValue2; // 临时变量: double _yTickValueScale2; // 临时变量: double _ySubTickValueScale2; // 临时变量: private: double _minY; // y轴最小值 double _maxY; // y轴最大值 double _minY2; // y轴最小值 double _maxY2; // y轴最大值 double _x; // 十字轴的x坐标 double _y1; // 十字轴的导高值 double _y2; // 十字轴的超出值 #endif // LINECHART2WIDGET_H
需求 1. 屏幕分辨率1920 x 1080; 2. 白平衡、冻结、自动背光、自动光源等功能;’ 2. 拍照功能,可设置拍照路径(U盘,SD卡,内置存储); 3. 录像功能,可设置录像路径(U盘,SD卡,内置存储); 4. 亮度调整,摄像头光源亮度调整; 5. 物理按键,包括拍照、录像、上下左右、菜单、默认亮度、选择等等; 6. 定制开机界面; 7. 照片、视频九宫格浏览控件; 8. 照片浏览器; 9. 视频播放器; 10. 可查看照片、视频同时支持按键对照片和视频的操作; 11. 对存储控件的资源浏览器控件’,并可对其复制、粘贴、删除等操作; 12. 设置时间日期,仿苹果滑动效果; 13. 其他各种定制控件;注意 受限于成本(方案整体成本,较同行业较低),不断压缩的成本,导致该产品的出现关键难点,其在于fpga上的仿arm跑linux的芯片性能等同于2011年的arm水平,经过fpga+arm+qt三方的代码优化和内存优化。’相关博客 《案例分享:Qt+Arm基于RV1126平台的内窥镜软硬整套解决方案(实时影像、冻结、拍照、录像、背光调整、硬件光源调整,其他产品也可使用该平台,如视频监控,物联网产品等等)》关于定制 支持相关的软硬shang业定制(非shang业勿扰,无ye务不讨论技术细节)Demo 软件界面 关键代码EndoscopeWidget.h#ifndef ENDOSCOPEWIDGET_H #define ENDOSCOPEWIDGET_H #include <QWidget> #include <QButtonGroup> #include <QThread> #include <QLabel> #ifdef LINUX #include "X264Manager.h" extern "C" { #include "fpga_comm_app.h" #include "common.h" #endif #ifndef LINUX #define LOCAL_DIR ("local") #define USB1_DIR ("usb1") // usb #define USB2_DIR ("usb2") // usb默认路径 #endif #define PICTURE_DIR ("Picture") #define VIDEO_DIR ("Video") #define DEBUG_X264_SRC (1) // 1 - 模拟数据源测试x264, 0 - 使用fpga数据源操作x264库 #define DEBUG_SAVE_PATH (1) // 1 - 存储到应用目录下(arm、pc均可用), 0 - 存储到U盘(必须在arm上) #define MKDIR_USE_SHELL (1) // 1 - 使用mkdir创建目录, 0 - 使用qt自带的创建目录(建议使用1) #define SKIP_FRAMES (0) // 1 - 是跳帧编码, 0 - 不跳帧 #define SKIP_NUM (0) // 跳帧时有用,当前帧数 % SKIP_NUM== 0时跳帧 #define X264_USE_THREAD (0) // 1 - x264编码使用另外的线程(需要拷贝缓存), 0 - 主线程直接调用 #define CFG_FILE ("cfg") // 配置文件 namespace Ui { class EndoscopeWidget; class EndoscopeWidget : public QWidget Q_OBJECT public: enum LANGUAGE_TYPE { // 语言类型 LANGUAGE_TYPE_CHINESE_SIMPLE = 0x00, LANGUAGE_TYPE_ENGLISH, LANGUAGE_TYPE_CHINESE_TRADITION enum SAVE_LOCATION { // 存储位置 SAVE_LOCATION_LOCAL = 0x00, SAVE_LOCATION_USB1, SAVE_LOCATION_USB2 enum FUNCTION_TYPE { // 功能类型 FUNCTION_TYPE_NO_USE = 0x00, FUNCTION_TYPE_PHTOTO, FUNCTION_TYPE_RECORD, FUNCTION_TYPE_FREEZE, FUNCTION_TYPE_WHITE_BALANCE_CORRECT public: explicit EndoscopeWidget(QWidget *parent = 0); ~EndoscopeWidget(); signals: void signal_recvYuv(QByteArray byteArray); protected: void addFont(); // 添加字体 void loadCfg(); // 加载配置文件 void saveCfg(); // 存储配置文件 void updateDate(); // 更新日期 void updateLocateState(); // 更新本地local位置使能 void mkdir(QString currentDir); // 切换存储的时候需要创建文件夹 protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); protected slots: void slot_labelInfoTimeOut(); protected slots: void slot_backgroundLightBrightnessValueChanged(int value); void slot_lightSourceBrightnessValueChanged(int value); protected slots: void slot_dateChanged(); // 日期改变更新 void slot_languageButtonClicked(QAbstractButton *pBtn); // 语言按钮(中文简体、English、中文繁体) void slot_locateLocationClicked(QAbstractButton *pBtn); // 存储位置(本机、USB1,USB2) void slot_key1ButtonClicked(QAbstractButton *pBtn); // 按键一功能(不用、拍照、录像、冻结、白平衡校正) void slot_key2ButtonClicked(QAbstractButton *pBtn); // 按键二功能(不用、拍照、录像、冻结、白平衡校正) void slot_doubleClickedVideoFile(QString filePath); // 双击选中视频文件 private slots: // 左侧菜单 void on_pushButton_photograph_clicked(); // 拍照 void on_pushButton_record_clicked(bool checked); // 录像 void on_pushButton_freezeScreen_clicked(bool checked); // 冻结 void on_pushButton_whiteBalanceCorrect_clicked(); // 白平衡校正 void on_pushButton_defaultLight_clicked(); // 默认亮度 void on_pushButton_photoSee_clicked(); // 图片查看 private slots: // 右侧菜单 void on_pushButton_lightSourceSet_clicked(); // 光源亮度设置 void on_pushButton_dateSet_clicked(); // 时间日期设置 void on_pushButton_languageSet_clicked(); // 语言设置 void on_pushButton_key1Set_clicked(); // 按键一设置 void on_pushButton_key2Set_clicked(); // 按键二设置 void on_pushButton_backgroundLightSet_clicked(); // 背光亮度设置 void on_pushButton_photoVideoSet_clicked(); // 照片/录像文件设置 void on_pushButton_set_clicked(bool checked); // 设置返回 private slots: // 文件操作:左侧操作图片菜单 void on_pushButton_delete_clicked(); // 文件操作:删除 void on_pushButton_selectAll_clicked(); // 文件操作:选择所有 void on_pushButton_copy_clicked(); // 文件操作:复制 void on_pushButton_paste_clicked(); // 文件操作:粘贴 void on_pushButton_back_clicked(); // 文件操作:返回 private slots: void on_pushButton_startPlay_clicked(); // 播放器:播放 void on_pushButton_pause_clicked(); // 播放器:暂停 void on_pushButton_resume_clicked(); // 播放器:恢复 void on_pushButton_stop_clicked(); // 播放器:停止 void on_pushButton_playerBack_clicked(); // 播放器:返回 private: Ui::EndoscopeWidget *ui; QList<QString> _listCopyFile; // 复制的文件列表 QButtonGroup _buttonGroupLanguage; // 语言选择 QButtonGroup _buttonGroupKey1Function; // 按键1功能 QButtonGroup _buttonGroupKey2Function; // 按键2功能 QButtonGroup _buttonLocation; // 存储位置 QString _filePath; // 播放地址 bool _isLoopSaveImageIndex; int _imageIndex; // 当天拍照的序号(从0开始) bool _isLoopSaveVideoIndex; int _videoIndex; // 当天录像的序号(从0开始) QString _cfgFile; // 配置文件 LANGUAGE_TYPE _language; // 当前语言 SAVE_LOCATION _saveLocation; // 当前存储位置 FUNCTION_TYPE _key1Function; // 按键1功能 FUNCTION_TYPE _key2Function; // 按键2功能 int _backgroundLightBrightness; // 背光亮度 int _lightSourceBrightness; // 光源亮度 QString _storeDir; QString _photoDir; // 辅助变量:当前拍照文件夹 QString _videoDir; // 辅助变量:当前视频文件夹 QString _fileName; // 辅助变量:存储文件名称 #ifdef LINUX static QThread *_pX264ManagerThread; // x264视频编码线程 static X264Manager *_pX264Manager; // x264管理类 static int _index; private: QTimer *_pTimer; protected slots: void slot_timeOut(); public: static bool _recording; static int fpga_com_read_record_data_handler_t(char *buffer, int length); #endif QTimer *_pTimerInfo; // 计时器用于显示 QLabel *_pLabelRecIcon; // 图标 QLabel *_pLabelRecord; // 图标 QLabel *_pLabelInfo; // 提示Label #endif // ENDOSCOPEWIDGET_HEndoscopeWidget.cpp#include "EndoscopeWidget.h" #include "ui_EndoscopeWidget.h" #include <QStyleOption> #include <QPaintEvent> #include <QPainter> #include <QDebug> #include <QDate> #include <QFontDatabase> #include <QButtonGroup> #include <QProcess> #include <QMessageBox> #include "DateTime2Widget.h" //#include "JpegManager.h" #ifdef LINUX QThread *EndoscopeWidget::_pX264ManagerThread = 0; X264Manager *EndoscopeWidget::_pX264Manager = 0; bool EndoscopeWidget::_recording = false; int EndoscopeWidget::_index = 0; #endif EndoscopeWidget::EndoscopeWidget(QWidget *parent) : QWidget(parent), ui(new Ui::EndoscopeWidget), _imageIndex(1), _isLoopSaveImageIndex(false), _videoIndex(1), _cfgFile(CFG_FILE), // 配置文件 _language(LANGUAGE_TYPE_CHINESE_SIMPLE),// 默认语言(未加载配置文件之前) _saveLocation(SAVE_LOCATION_LOCAL), // 默认存储在本地(未加载配置文件之前) _key1Function(FUNCTION_TYPE_NO_USE), // 默认按键1无功能(未加载配置文件之前) _key2Function(FUNCTION_TYPE_NO_USE), // 默认按键2无功能(未加载配置文件之前) _backgroundLightBrightness(3), _lightSourceBrightness(9), _pLabelRecIcon(0), _pLabelRecord(0), _pLabelInfo(0), _pTimerInfo(0), #ifdef LINUX _pTimer(0), #endif _isLoopSaveVideoIndex(false) ui->setupUi(this); // 加载配置文件 loadCfg(); // 加入自带的字体 “Roboto-Condensed” addFont(); // rec图标和提示信息 _pLabelRecIcon = new QLabel(this); _pLabelRecIcon->setStyleSheet("border-image: url(:/images/recIcon.png);"); _pLabelRecIcon->show(); _pLabelRecord = new QLabel(this); _pLabelRecord->setStyleSheet("border-image: url(:/images/rec.png);"); _pLabelRecord->show(); _pLabelInfo = new QLabel(this); _pLabelInfo->setStyleSheet("font: 14px \"思源黑体\"; color: rgb(210,210,210);"); _pLabelInfo->setAlignment(Qt::AlignVCenter | Qt::AlignLeft); _pLabelInfo->hide(); _pTimerInfo = new QTimer(); _pTimerInfo->setInterval(1500); connect(_pTimerInfo, SIGNAL(timeout()), this, SLOT(slot_labelInfoTimeOut())); // 初始化图像控件的默认存储地址(无需加载) // ui->widget_camera->setPhotoDir(QString("%1/%2").arg(LOCAL_DIR).arg(PICTURE_DIR)); // ui->widget_camera->setRecordDir(QString("%1/%2").arg(LOCAL_DIR).arg(VIDEO_DIR)); // 初始化按钮(拍照、录像、触屏冻结、白平衡校正、默认亮度、照片查看) // 初始化按钮的图标区域 int iconWidth = 60; int iconHeight = 60; int iconCenterX = 46; int iconCenterY = 63; QRect iconRect(iconCenterX - iconWidth / 2, iconCenterY - iconHeight / 2, iconWidth, iconHeight); // 初始化按钮的文字区域 int textWidht = 236; int textheight = 60; int textCenterX = 168; int textCenterY = 63; QRect textRect(textCenterX - textWidht / 2, textCenterY - textheight / 2, textWidht, textheight); // 初始化按钮的字体 QFont font = QFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(36); // 拍照 ui->pushButton_photograph->setIconPixmap(QPixmap(":/images/photograph.png")); ui->pushButton_photograph->setIconPixmapPressed(QPixmap(":/images/photograph_pressed.png")); ui->pushButton_photograph->setIconPixmapDisable(QPixmap(":/images/photograph_disabled.png")); ui->pushButton_photograph->setIconPixmapRect(iconRect); ui->pushButton_photograph->setText(tr("拍照")); ui->pushButton_photograph->setTextRect(textRect); ui->pushButton_photograph->setFont(font); // 录像 ui->pushButton_record->setIconPixmap(QPixmap(":/images/record.png")); ui->pushButton_record->setIconPixmapPressed(QPixmap(":/images/record_pressed.png")); ui->pushButton_record->setIconPixmapDisable(QPixmap(":/images/record_disabled.png")); ui->pushButton_record->setIconPixmapRect(iconRect); ui->pushButton_record->setText(tr("录像")); ui->pushButton_record->setTextRect(textRect); ui->pushButton_record->setFont(font); // 触屏冻结 ui->pushButton_freezeScreen->setIconPixmap(QPixmap(":/images/freezeScreen.png")); ui->pushButton_freezeScreen->setIconPixmapPressed(QPixmap(":/images/freezeScreen_pressed.png")); ui->pushButton_freezeScreen->setIconPixmapDisable(QPixmap(":/images/freezeScreen_disabled.png")); ui->pushButton_freezeScreen->setIconPixmapRect(iconRect); ui->pushButton_freezeScreen->setText(tr("触屏冻结")); ui->pushButton_freezeScreen->setTextRect(textRect); ui->pushButton_freezeScreen->setFont(font); // 白平衡校正 ui->pushButton_whiteBalanceCorrect->setIconPixmap(QPixmap(":/images/whiteBalanceCorrect.png")); ui->pushButton_whiteBalanceCorrect->setIconPixmapPressed(QPixmap(":/images/whiteBalanceCorrect_pressed.png")); ui->pushButton_whiteBalanceCorrect->setIconPixmapDisable(QPixmap(":/images/whiteBalanceCorrect_disabled.png")); ui->pushButton_whiteBalanceCorrect->setIconPixmapRect(iconRect); ui->pushButton_whiteBalanceCorrect->setText(tr("白平衡校正")); ui->pushButton_whiteBalanceCorrect->setTextRect(textRect); ui->pushButton_whiteBalanceCorrect->setFont(font); // 默认亮度 ui->pushButton_defaultLight->setIconPixmap(QPixmap(":/images/defaultLight.png")); ui->pushButton_defaultLight->setIconPixmapPressed(QPixmap(":/images/defaultLight_pressed.png")); ui->pushButton_defaultLight->setIconPixmapDisable(QPixmap(":/images/defaultLight_disabled.png")); ui->pushButton_defaultLight->setIconPixmapRect(iconRect); ui->pushButton_defaultLight->setText(tr("默认亮度")); ui->pushButton_defaultLight->setTextRect(textRect); ui->pushButton_defaultLight->setFont(font); // 照片查看 ui->pushButton_photoSee->setIconPixmap(QPixmap(":/images/photoSee.png")); ui->pushButton_photoSee->setIconPixmapPressed(QPixmap(":/images/photoSee_pressed.png")); ui->pushButton_photoSee->setIconPixmapDisable(QPixmap(":/images/photoSee_disabled.png")); ui->pushButton_photoSee->setIconPixmapRect(iconRect); ui->pushButton_photoSee->setText(tr("照片查看")); ui->pushButton_photoSee->setTextRect(textRect); ui->pushButton_photoSee->setFont(font); // 初始化按钮(删除、复制、粘贴、选择、返回) int iconWidth2 = 40; int iconHeight2 = 40; int iconCenterX2 = 80; int iconCenterY2 = 63; QRect iconRect2(iconCenterX2 - iconWidth2 / 2, iconCenterY2 - iconHeight2 / 2, iconWidth2, iconHeight2); // 初始化按钮的文字区域 int textWidht = 236; int textheight = 60; int textCenterX = 170; int textCenterY = 63; QRect textRect(textCenterX - textWidht / 2, textCenterY - textheight / 2, textWidht, textheight); // 初始化按钮的字体 QFont font = QFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(32); // 删除 ui->pushButton_delete->setIconPixmap(QPixmap(":/images/delete.png")); ui->pushButton_delete->setIconPixmapPressed(QPixmap(":/images/delete_pressed.png")); ui->pushButton_delete->setIconPixmapDisable(QPixmap(":/images/delete_disabled.png")); ui->pushButton_delete->setIconPixmapRect(iconRect2); ui->pushButton_delete->setText(tr("删 除")); ui->pushButton_delete->setTextRect(textRect); ui->pushButton_delete->setFont(font); // 全选 ui->pushButton_selectAll->setIconPixmap(QPixmap(":/images/selectAll.png")); ui->pushButton_selectAll->setIconPixmapPressed(QPixmap(":/images/selectAll_pressed.png")); ui->pushButton_selectAll->setIconPixmapDisable(QPixmap(":/images/selectAll_disabled.png")); ui->pushButton_selectAll->setIconPixmapRect(iconRect2); ui->pushButton_selectAll->setText(tr("全 选")); ui->pushButton_selectAll->setTextRect(textRect); ui->pushButton_selectAll->setFont(font); // 复制 ui->pushButton_copy->setIconPixmap(QPixmap(":/images/copy.png")); ui->pushButton_copy->setIconPixmapPressed(QPixmap(":/images/copy_pressed.png")); ui->pushButton_copy->setIconPixmapDisable(QPixmap(":/images/copy_disabled.png")); ui->pushButton_copy->setIconPixmapRect(iconRect2); ui->pushButton_copy->setText(tr("复 制")); ui->pushButton_copy->setTextRect(textRect); ui->pushButton_copy->setFont(font); // 粘贴 ui->pushButton_paste->setIconPixmap(QPixmap(":/images/paste.png")); ui->pushButton_paste->setIconPixmapPressed(QPixmap(":/images/paste_pressed.png")); ui->pushButton_paste->setIconPixmapDisable(QPixmap(":/images/paste_disabled.png")); ui->pushButton_paste->setIconPixmapRect(iconRect2); ui->pushButton_paste->setText(tr("粘 贴")); ui->pushButton_paste->setTextRect(textRect); ui->pushButton_paste->setFont(font); // 返回 ui->pushButton_back->setIconPixmap(QPixmap(":/images/back.png")); ui->pushButton_back->setIconPixmapPressed(QPixmap(":/images/back_pressed.png")); ui->pushButton_back->setIconPixmapDisable(QPixmap(":/images/delete_disabled.png")); ui->pushButton_back->setIconPixmapRect(iconRect2); ui->pushButton_back->setText(tr("返 回")); ui->pushButton_back->setTextRect(textRect); ui->pushButton_back->setFont(font); // 初始化按钮(播放、暂停、恢复、停止、返回) // 初始化按钮的文字区域 int textWidht = 236; int textheight = 60; int textCenterX = 170; int textCenterY = 63; QRect textRect(textCenterX - textWidht / 2, textCenterY - textheight / 2, textWidht, textheight); // 初始化按钮的字体 QFont font = QFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(32); // 播放 ui->pushButton_startPlay->setText(tr("播 放")); ui->pushButton_startPlay->setTextRect(textRect); ui->pushButton_startPlay->setFont(font); // 暂停 ui->pushButton_pause->setText(tr("暂 停")); ui->pushButton_pause->setTextRect(textRect); ui->pushButton_pause->setFont(font); // 恢复 ui->pushButton_resume->setText(tr("恢 复")); ui->pushButton_resume->setTextRect(textRect); ui->pushButton_resume->setFont(font); // 停止 ui->pushButton_stop->setText(tr("停 止")); ui->pushButton_stop->setTextRect(textRect); ui->pushButton_stop->setFont(font); // 返回 ui->pushButton_playerBack->setText(tr("返 回")); ui->pushButton_playerBack->setTextRect(textRect); ui->pushButton_playerBack->setFont(font); // 初始化按钮(设置) int iconWidth2 = 34; int iconHeight2 = 34; int iconCenterX2 = 256; int iconCenterY2 = 46; QRect iconRect2(iconCenterX2 - iconWidth2 / 2, iconCenterY2 - iconHeight2 / 2, iconWidth2, iconHeight2); // 初始化按钮的文字区域 QRect textRect = ui->pushButton_set->rect(); // 初始化按钮的字体 QFont font = QFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(36); ui->pushButton_set->setIconPixmap(QPixmap(":/images/back.png")); ui->pushButton_set->setIconPixmapPressed(QPixmap(":/images/back_pressed.png")); ui->pushButton_set->setIconPixmapDisable(QPixmap(":/images/back_pressed.png")); ui->pushButton_set->setIconPixmapRect(iconRect2); ui->pushButton_set->setText(tr("设置选项")); ui->pushButton_set->setTextRect(textRect); ui->pushButton_set->setFont(font); // 初始化各区域显示界面 ui->stackedWidget_leftKeys->setCurrentIndex(0); ui->stackedWidget_center->setCurrentIndex(0); ui->stackedWidget_rightKeys->setCurrentIndex(0); // 用于模拟,打开usb摄像头 ui->widget_camera->open(0); // 背景亮度改为4级(0,1,2,3)(默认为9级,0~8) QFont font = ui->widget_backgroundLightSlider->getFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(32); ui->widget_backgroundLightSlider->setAddPixmap(QPixmap(":/images/add.png")); ui->widget_backgroundLightSlider->setAddPixmapPressed(QPixmap(":/images/add_pressed.png")); ui->widget_backgroundLightSlider->setDecPixmap(QPixmap(":/images/dec.png")); ui->widget_backgroundLightSlider->setDecPixmapPressed(QPixmap(":/images/dec_pressed.png")); ui->widget_backgroundLightSlider->setFont(font); ui->widget_backgroundLightSlider->setMinValue(0); ui->widget_backgroundLightSlider->setMaxValue(3); ui->widget_backgroundLightSlider->setValue(_backgroundLightBrightness); ui->widget_backgroundLightSlider->setBackgroundPixmap(QPixmap(":/sliderWidget/images/background.png")); connect(ui->widget_backgroundLightSlider, SIGNAL(signal_valueChanged(int)), this, SLOT(slot_backgroundLightBrightnessValueChanged(int))); // 光源亮度9级别(0,1,2,3,4,5,6,7,8,9) QFont font = ui->widget_backgroundLightSlider->getFont(); font.setFamily("思源黑体 CN Normal"); font.setPixelSize(32); ui->widget_lightSourceSlider->setAddPixmap(QPixmap(":/images/add.png")); ui->widget_lightSourceSlider->setAddPixmapPressed(QPixmap(":/images/add_pressed.png")); ui->widget_lightSourceSlider->setDecPixmap(QPixmap(":/images/dec.png")); ui->widget_lightSourceSlider->setDecPixmapPressed(QPixmap(":/images/dec_pressed.png")); ui->widget_lightSourceSlider->setFont(font); ui->widget_lightSourceSlider->setMinValue(0); ui->widget_lightSourceSlider->setMaxValue(9); ui->widget_lightSourceSlider->setValue(_lightSourceBrightness); ui->widget_lightSourceSlider->setBackgroundPixmap(QPixmap(":/sliderWidget/images/ligthSourceBackground.png")); connect(ui->widget_lightSourceSlider, SIGNAL(signal_valueChanged(int)), this, SLOT(slot_lightSourceBrightnessValueChanged(int))); // 语言选择 _buttonGroupLanguage.addButton(ui->pushButton_chineseSimple); _buttonGroupLanguage.addButton(ui->pushButton_english); _buttonGroupLanguage.addButton(ui->pushButton_chineseTradition); connect(&_buttonGroupLanguage, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slot_languageButtonClicked(QAbstractButton*))); switch (_language) case LANGUAGE_TYPE_CHINESE_SIMPLE: ui->pushButton_chineseSimple->setChecked(true); break; case LANGUAGE_TYPE_ENGLISH: ui->pushButton_english->setChecked(true); break; case LANGUAGE_TYPE_CHINESE_TRADITION: ui->pushButton_chineseTradition->setChecked(true); break; default: break; // 按键1和2的功能 // 按键1的功能按钮 ui->pushButton_key1NoUse->setText(tr("不使用")); ui->pushButton_key1Photo->setText(tr("拍照")); ui->pushButton_key1Record->setText(tr("录像")); ui->pushButton_key1Freeze->setText(tr("冻结")); ui->pushButton_key1WhiteBalanceCorrect->setText(tr("白平衡校准")); _buttonGroupKey1Function.addButton(ui->pushButton_key1NoUse); _buttonGroupKey1Function.addButton(ui->pushButton_key1Photo); _buttonGroupKey1Function.addButton(ui->pushButton_key1Record); _buttonGroupKey1Function.addButton(ui->pushButton_key1Freeze); _buttonGroupKey1Function.addButton(ui->pushButton_key1WhiteBalanceCorrect); connect(&_buttonGroupKey1Function, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slot_key1ButtonClicked(QAbstractButton*))); switch (_key1Function) case FUNCTION_TYPE_NO_USE: ui->pushButton_key1NoUse->setChecked(true); break; case FUNCTION_TYPE_PHTOTO: ui->pushButton_key1Photo->setChecked(true); break; case FUNCTION_TYPE_RECORD: ui->pushButton_key1Record->setChecked(true); break; case FUNCTION_TYPE_FREEZE: ui->pushButton_key1Freeze->setChecked(true); break; case FUNCTION_TYPE_WHITE_BALANCE_CORRECT: ui->pushButton_key1WhiteBalanceCorrect->setChecked(true); break; default: break; // 按键2的功能按钮 ui->pushButton_key2NoUse->setText(tr("不使用")); ui->pushButton_key2Photo->setText(tr("拍照")); ui->pushButton_key2Record->setText(tr("录像")); ui->pushButton_key2Freeze->setText(tr("冻结")); ui->pushButton_key2WhiteBalanceCorrect->setText(tr("白平衡校准")); _buttonGroupKey2Function.addButton(ui->pushButton_key2NoUse); _buttonGroupKey2Function.addButton(ui->pushButton_key2Photo); _buttonGroupKey2Function.addButton(ui->pushButton_key2Record); _buttonGroupKey2Function.addButton(ui->pushButton_key2Freeze); _buttonGroupKey2Function.addButton(ui->pushButton_key2WhiteBalanceCorrect); connect(&_buttonGroupKey2Function, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slot_key2ButtonClicked(QAbstractButton*))); switch (_key1Function) case FUNCTION_TYPE_NO_USE: ui->pushButton_key2NoUse->setChecked(true); break; case FUNCTION_TYPE_PHTOTO: ui->pushButton_key2Photo->setChecked(true); break; case FUNCTION_TYPE_RECORD: ui->pushButton_key2Record->setChecked(true); break; case FUNCTION_TYPE_FREEZE: ui->pushButton_key2Freeze->setChecked(true); break; case FUNCTION_TYPE_WHITE_BALANCE_CORRECT: ui->pushButton_key2WhiteBalanceCorrect->setChecked(true); break; default: break; // 存储位置选择 // 存储位置选择 ui->label_locateLocal->setText(tr("本机")); ui->label_locateUsb1->setText(tr("USB1")); ui->label_locateUsb2->setText(tr("USB2")); ui->label_locateLocal->setParent(ui->pushButton_locateLocal); ui->label_locateUsb1->setParent(ui->pushButton_locateUsb1); ui->label_locateUsb2->setParent(ui->pushButton_locateUsb2); ui->label_locateLocal->move(0, 0); ui->label_locateUsb1->move(0, 0); ui->label_locateUsb2->move(0, 0); ui->label_locateLocalStore->setText(QString("%1MB%2").arg(320).arg(tr("剩余"))); ui->label_locateUsb1Store->setText(QString("%1MB%2").arg(320).arg(tr("剩余"))); ui->label_locateUsb2Store->setText(QString("%1MB%2").arg(0).arg(tr("剩余"))); ui->label_locateLocalStore->setParent(ui->pushButton_locateLocal); ui->label_locateUsb1Store->setParent(ui->pushButton_locateUsb1); ui->label_locateUsb2Store->setParent(ui->pushButton_locateUsb2); ui->label_locateLocalStore->move(ui->pushButton_locateLocal->width() / 2, 0); ui->label_locateUsb1Store->move(ui->pushButton_locateUsb1->width() / 2, 0); ui->label_locateUsb2Store->move(ui->pushButton_locateUsb2->width() / 2, 0); _buttonLocation.addButton(ui->pushButton_locateLocal); _buttonLocation.addButton(ui->pushButton_locateUsb1); _buttonLocation.addButton(ui->pushButton_locateUsb2); connect(&_buttonLocation, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(slot_locateLocationClicked(QAbstractButton*))); switch (_saveLocation) case SAVE_LOCATION_LOCAL: ui->pushButton_locateLocal->setChecked(true); break; case SAVE_LOCATION_USB1: ui->pushButton_locateUsb1->setChecked(true); break; case SAVE_LOCATION_USB2: ui->pushButton_locateUsb2->setChecked(true); break; default: break; // 更新一下路径 updateLocateState(); // 文件浏览器信号 ui->widget_resourceBrowser->setCols(4); ui->widget_resourceBrowser->setRows(4); connect(ui->widget_resourceBrowser, SIGNAL(signal_doubleClickedVideoFile(QString)), this, SLOT(slot_doubleClickedVideoFile(QString))); // 时间控件关联日期控件 ui->widget_time->setBackgroundPixmap(QPixmap(":/images/timeBackground.png")); connect(ui->widget_time, SIGNAL(signal_dateChanged()), this, SLOT(slot_dateChanged())); // 日期控件初始化 QFont font = ui->widget_dateSet->getFont(); font.setPixelSize(44); ui->widget_dateSet->setFont(font); ui->widget_dateSet->setBackgroundPixmap(QPixmap(":/images/setTimeBackground.png")); // 时间控件初始化 QFont font = ui->widget_timeSet->getFont(); font.setPixelSize(32); ui->widget_timeSet->setFont(font); ui->widget_timeSet->setBackgroundPixmap(QPixmap(":/images/setTimeBackground.png")); // 刷新日期 updateDate(); #ifdef LINUX // 注册录像回调函数 // fpga_comm_init(&fpga_com_read_record_data_handler_t); fpga_comm_init(0); // 初始化编码进程 // _pX264ManagerThread = new QThread(); _pX264Manager = new X264Manager(); connect(this, SIGNAL(signal_recvYuv(QByteArray)), _pX264Manager, SLOT(slot_recvYuv(QByteArray)), Qt::QueuedConnection); // _pX264Manager->moveToThread(_pX264ManagerThread); // _pX264ManagerThread->start(); #endif EndoscopeWidget::~EndoscopeWidget() delete ui; #endif
需求 电脑端通过条码打印机TSC-TTP244 Pro: 1. 打印出尺寸为60*30cm 2. 条码打印机TSC-TTP244 Pro 不干胶纸 (不需要碳带,热敏纸) 3. windows系统要求用QT编写程序,并加上必要的注释(所有源代码要给我们,包括SDK) 4. 界面需要适应不同分辨率的电脑 5. 条码样式如下: Demo 硬件:条码打印机TSC 244 Pro v1.0.0 class TscPrinterManager : public QObject Q_OBJECT private: explicit TscPrinterManager(QObject *parent = 0); signals: public slots: public: static TscPrinterManager *getInstance(); public: bool initPrinter(); void abount(); void test(); bool printHengYaHanJieFa(QString vType, int v1, int v2, int v3, int v4, int vS1, int vS2, int vS3, int vS4, QString model, int num); bool printHengLiuHanJieFa(QString vType, int v1, int v2, int v3, int v4, int vS1, int vS2, int vS3, int vS4, QString model, int num); QString getDevName() const; void setDevName(const QString &devName); private: QLibrary _library; QString _libName; QString _devName; QTextCodec *_pTextCodec; private: // 打印机函数 文档中共20个函数,当前初始化13个 function_about _pFunAbout; function_openport _pFunOpenPort; function_closeport _pFunClosePort; function_barcode _pFunBarcode; function_clearBuffer _pFunClearBuffer; function_downloadpcx _pFunDownLoadPcx; function_formfeed _pFunFromFeed; function_nobackfeed _pFunNobackFeed; function_printerfont _pFunPrinterFont; function_printlabel _pFunPrintLabel; function_sendcommand _pFunSendCommand; function_setup _pFunSetup; function_windowsfont _pFunWindowsFont; function_windowsunicode _pFunWindowsUnicode; private: static TscPrinterManager *_pInstance; static QMutex _mutex;
需求 生命探测仪 1. 扫描雷达状态显示:正在扫描 or 扫描停止; 2. 显示扫描雷达的灵敏度; 3. 探测过程中的数据文件保存(用于跟踪和后期回放) 4. 探测仪连接app的终端的状态显示; 5. 电池电量显示; 6. 多语言切换,中文/英文; 7. 探测目标二维成图显示界面,包括生命体、静止目标、动态目标; 8. 显示or隐藏动态目标的移动轨迹; 9. 雷达探测过程中实时现实探测的前方障碍物物体等,同时转换为一维火山图显示; 10. 前方探测距离的、方位范围‘、灵敏度设置; 11. 探测文件实时保存; 12. 探测文件的探测过程回放;Demo 硬件 Demo头文件代码RadarScanWidget.h#ifndef RADARSCANWIDGET_H #define RADARSCANWIDGET_H #include <QWidget> #include <QElapsedTimer> #include <QPixmap> #include <QTimer> namespace Ui { class RadarScanWidget; class RadarScanWidget : public QWidget Q_OBJECT public: enum COORDINATE_HORIZAL{ COORDINATE_HORIZAL_4 = 0x00, COORDINATE_HORIZAL_6 = 0x01, COORDINATE_HORIZAL_8 = 0x02, enum COORDINATE_VERTICAL{ COORDINATE_VERTICAL_10 = 0x00, COORDINATE_VERTICAL_20 = 0x01, COORDINATE_VERTICAL_30 = 0x02, public: explicit RadarScanWidget(QWidget *parent = 0); ~RadarScanWidget(); public: inline bool hasMoveTarget() { return _listListPointFForMove.size() > 15; } void setShowMoveLineMoreThanLimitPoints(int showMoveLineMoreThanLimitPoints); signals: void signalStaticTargetNumber(int number); public slots: void startScanning(); void stopScanning(); void setHorizalCoordinate(COORDINATE_HORIZAL c); void setVerticalCoordinate(COORDINATE_VERTICAL c); void setShowPath(bool showPath); void recvTargetPointF(QList<QPointF> listPointF, bool isStatic); void recvMatrixUChar(int frameIndex, QList<uchar> listUChar); void clearAllData(); protected slots: void timeout(); protected: void paintEvent(QPaintEvent *event); void timerEvent(QTimerEvent *event); protected: void drawBackground(QPainter &painter); void drawChartBackground(QPainter &painter); void drawChart(QPainter &painter); void drawArc(QPainter &painter); void drawPointData(QPainter &painter); void drawWallData(QPainter &painter); protected: QPointF judgetStaticDistanceLessThanDistance(QPointF p1, QPointF p2, qreal distance, bool *ok = 0); bool judgetMoveDistanceLessThanDistance(QPointF p1, QPointF p2, qreal distance); private: Ui::RadarScanWidget *ui; int _offsetX; int _offsetY; int _stepsX; int _stepsY; int _rangleXMin; int _rangleXMax; int _rangleYMin; int _rangleYMax; int _width; int _height; QColor _backgroundColor; QColor _backgroundChartColor; QColor _lineColor; QColor _color; QColor _pointColor; QStringList _strListVericalLocaltion; QStringList _strListHorizalLocaltion; int _offsetHorizalTextX; int _offsetHorizalTextY; int _offsetVerticalTextX; int _offsetVerticalTextY; int _originX; int _originY; bool _isScanning; COORDINATE_HORIZAL _cooradinateHorizal; COORDINATE_VERTICAL _cooradinateVertical; int _indexOfArc; int _timerId; int _interval; QList<QList<QPointF> > _listListPointFForMove; QList<QList<QPointF> > _listListPointFForMoveLine; QList<QList<QPointF> > _listListPointFForStatic; QList<QList<uchar> > _listListUCharForMaxtric; QList<QPointF> _listPointFForStatic; bool _showPath; QElapsedTimer _elapsedTimerForMove; QElapsedTimer _elapsedTimerForStatic; int _intervalTime; QPixmap _pixmap; QList<QPixmap> _listPixmapForMove; QList<QPixmap> _listPixmapForStatic; QList<int> _listCount; QTimer *_pTimer; int _staticCircleR; QList<int> _listStaticTime; int _staticsStaticTargetTime; int _showMoveLineMoreThanLimitPoints; #endif // RADARSCANWIDGET_H
前话 接下来介绍树莓派蓝牙模块的开发,使用的协议为bluez。ssh远程登录到树莓派 请参照博客《树莓派开发笔记(一):入手树莓派3b,成功运行树莓派系统》Demo:蓝牙探测信号rssi强度,并发送给服务器 客户端bob,服务器alice,探测两方的rssi,并传送给服务器alice Bluez简介 BlueZ是官方Linux Bluetooth栈,由主机控制接口(Host Control Interface,HCI)层、Bluetooth协议核心、逻辑链路控制和适配协议(Logical Link Control and Adaptation Protocol,L2CAP)、SCO 音频层、其他 Bluetooth 服务、用户空间后台进程以及配置工具组成。BlueZ由许多单独的模块组成:蓝牙内核子系统核心L2CAP和SCO音频内核层RFCOMM,BNEP,CMTP和HIDP内核实现HCI UART,USB,PCMCIA和虚拟设备驱动程序通用蓝牙和SDP库和守护程序配置和测试实用程序协议解码和分析工具搭建Bluez步骤一:安装bluezsudo apt-get install bluez蓝牙明命令行hciconfig/hcitool的使用检查蓝牙设备是否加载成功hciconfig 打开蓝牙sudo hciconfig hci0 up 扫描蓝牙sudo hciconfig iscan 蓝牙命令行工具bluetoothctl (注意:不好用,显示的都是mac地址,而且中文乱码,周围蓝牙多,根本分不清楚)启动蓝牙程序bluetoothctl 启动/关闭蓝牙电源power on/off 获取要配对设备的MAC地址 电脑上的蓝牙,先打开: pybluez使用sudo python3 -m pip install pybluez关键源码server.py# -*-coding: utf-8 -*- from bluetooth import * import sys import time import os import struct import bluetooth._bluetooth as bluez import bluetooth global hostRssi os.system("bluetoothctl power on") # 获取服务,通过uuid查找目标服务 #uuid = "63078d70-feb9-lle7-9812-dca90488bd22" #os.system("bluetoothctl discoverable on") dstuuid = "11111111-1111-1111-1111-111111111111" localuuid = "22222222-2222-2222-2222-222222222222" print("本地服务器,搜索客户端蓝牙rssi") data = client.recv(1024) print (data) client.close() bluetooth_sock.close() client.pyfrom bluetooth import * import sys import time import os import struct import bluetooth._bluetooth as bluez import bluetooth global hostRssi #开启蓝牙可见 os.system("bluetoothctl power on") os.system("bluetoothctl discoverable on") dstuuid = "22222222-2222-2222-2222-222222222222" localuuid = "11111111-1111-1111-1111-111111111111" bluetooth_sock=BluetoothSocket(RFCOMM) bluetooth_sock.bind(("",PORT_ANY)) bluetooth_sock.listen(1) data = "server:" + str(hostRssi) + ", client:" + str(clientRssi) ...入坑入坑一:打开蓝颜失败sudo vim /lib/systemd/system/bluetooth.service 修改文件内容#ExecStart=/usr/lib/bluez5/bluetooth/bluetoothd ExecStart=/usr/lib/bluez5/bluetooth/bluetoothd -E -C&emso;&emso;然后重启服务sudo sdptool add SP sudo systemctl daemon-reload sudo systemctl restart bluetooth sudo sdptool browse local入坑二:“no advertisable device” 原因:由于蓝牙不可见导致
需求 1.通道使能、选择、更改通道名称、设置显示颜色 2.采样率可设置(Sa/s/chj) 3.单位换算,按照给定的进行换算 4.对通道可进行设置补偿值 5.通道取消可动态显示和隐藏,并可动态调整显示颜色 6.一定范围的X轴、全范围Y轴、支持自动X轴、自动Y轴 7.清除图表(实际数据不清除),方便对比跟踪 8.支持将已有的采集数据按照指定规则导出到excel表 9.将当前二维表导出为图表保存 10.定时采集,选择实验采集多久,到时间后停止采集 11.通信设置,使用串口,可设置串口号和波特率 12.对设置设置界面和主界面的所有相关配置参数进行保存,并在下次启动时恢复最后一次启动的配置数据 13.支持日志系统,对相关操作和数据进行日志输出 14.双击空白区域,可全屏(分辨率固定为客户定制要求,所以限制了,屏幕小的可尝试双击全屏看)性能 支持长时间采集,几万点同时显示,不卡顿补充说明 支持模拟方式,带有模拟下位机数据输入上位机,点击“开始采集”即可模拟方式说明 注意:同时支持实际下位机协议数据和模拟数据两种方式,模拟数据主要是方便客户与开发者调试、测试和修复 1.使用模拟数据时,请先随意打开串口,点击“启动”后即可模拟数据 2.使用模拟数据时,导出excel,为“hello world”内容”相关博客 《案例分享:Qt高频fpga采集数据压力位移速度加速度分析系统(通道配置、电压转换、采样频率、通道补偿、定时采集、距离采集,导出exce、自动XY轴、隐藏XY轴、隐藏显示通道,文件回放等等)》 《案例分享:Qt多段Y轴折线图框架(双Y轴段折线、支持拽拖、浮动游标显示X值各段Y值、支持大量实时显示下位机数据)》 《案例分享:Qt便携式致病菌快速检测仪(账号管理、实验过程、二维图表、历史数据、通讯管理、实验报告、中英文等等)》 《案例分享:Qt多通道数据采集系统(通道配置、电压转换、采样频率、通道补偿值、定时采集、导出excel和图表、自动XY轴、隐藏XY轴、实时隐藏显示通道)》 《Qt开发笔记之QCustomPlot:QCustomPlot介绍、编译与使用》 《Qt开发笔记之Qwt(一):Qwt介绍、编译与Demo》Demo
错误 LINK : fatal error LNK1158: 无法运行“rc.exe” 本地环境 已装VS2017以及2015的相关库和windowsSDK。 一下是QtCreator的配置: 解决 rc实际是windows sdk里面的,所以安装windows sdk搜索一下,将其拷贝到vs2015的vc目录下,如下图: 拷贝至: 再编译,运行成功: 补充(2021年11月30日) 按照上面,编译msvc2015x64还是无法解决,这时其实是路径问题,直接将rc.exe和rcdll.dll放入到qt的msvc2015x64目录即可,目标路径如下:C:\Qt\Qt5.9.3\5.9.3\msvc2015_64\bin
前言 西门子PLC、台达触摸屏、法兰克机床等等多年以前玩得比较多,改造机床、维修机床、给机床编程等等,没事还能车个零件啥的,对于多年以前的研发改造编程,有时间就重新整理下。 先上点有历史年代感的照片: 需求 Qt实现与PLC调试工具。相关博客 《案例分享:Qt西门子PLC调试模拟工具(包含PLC上位机通讯,PLC服务器,读写Byte、Int、DInt、Real)(持续更新,当前v1.5.0)》 《西门子PLC开发笔记(一):PLC介绍,西门子S1200系列接线、编程、下载和仿真》 《台达PLC开发笔记(一):台达PLC连接介绍,分别使用485、网口与台达PLC建立连接》Demo西门子PLC实物连接图 连接西门子PLC实物读取数据演示(区分数据类型) 连接西门子PLC实物写入数据演示(区分数据类型) 连接西门子PLC实物读取数据演示(无类型) 连接西门子PLC实物写入数据演示(无类型) 模拟服务器演示 体验下载地址 CSDN(0积分下载):https://download.csdn.net/download/qq21497936/18513620 QQ群:1047134658(点击“文件”搜索“plcCommunication”,群内与博文同步更新)v1.5.0 头文件源码 PlcWidget.h#ifndef PLCWIDGET_H #define PLCWIDGET_H /************************************************************\ * 控件名称:PlcWidget * 功能描述:Plc通讯Demo * 控件功能: * 1.PLC客户端(上位机与PLC通讯)) * 2.PLC服务端(仿真PLC,方便调试上位机) * 3.服务器与客户端的数据显示,客户端为读DB,服务器写DB * 著作权信息 * 作者:红胖子(AAA红模仿) * 公司:长沙红胖子网络科技有限公司 * 网址:hpzwl.blog.csdn.net * 联系方式:QQ(21497936) 微信(yangsir198808) 电话(15173255813) * 版本信息 * 日期 版本号 描述 * 2020年11月22日 v1.0.0 基础功能 * 2020年11月23日 v1.1.0 增加服务器功能 * 2020年12月01日 v1.2.0 增加写入功能 * 2020年12月08日 v1.3.0 增加写入和读取int,dint,float,byte功能 * 2020年12月17日 v1.4.0 增加ip地址等相关配置的保存和读取,修复客户端ip地址无法输入的问题, * 修复服务器超过一次连接、断开导致的DB区域数据错误问题 * 2021年05月10日 v1.5.0 主题修改,版本控制 \************************************************************/ #include <QWidget> #include <QThread> #include <QDateTime> #include <QTimer> #include <QJsonObject> #include <QJsonDocument> #include <QFile> #include <QMessageBox> #include "PlcClientManager.h" #include "PlcServerManager.h" namespace Ui { class PlcWidget; class PlcWidget : public QWidget Q_OBJECT public: explicit PlcWidget(QWidget *parent = 0); ~PlcWidget(); protected slots: // 客户端:与PLC管理模块部分 void slot_connectedChanged(bool connected); void slot_readDB(int dbNum, int start, int size, QByteArray data); protected slots: // 客户端:循环执行读取操作槽 void slot_timeOut(); protected: void loadCfg(); void saveCfg(); private slots: // 客户端:连接、断开的部分 void on_pushButton_connect_clicked(); void on_pushButton_disconncet_clicked(); private slots: // 客户端:DB块的读取部分、写入部分 void on_pushButton_readDB_clicked(); void on_pushButton_writeDB_clicked(); void on_pushButton_startReadDB_clicked(); void on_pushButton_stopReadDB_clicked(); void on_pushButton_clear_clicked(); protected slots: // 服务端:状态、缓存区状态改变 void slot_listenStateChanged(bool listen); void slot_dataChanged(); private slots: // 服务端:开始监听、停止的部分 void on_pushButton_serverListen_clicked(); void on_pushButton_serverStopListen_clicked(); void on_pushButton_serverSet_clicked(); void on_pushButton_rDB_clicked(); void on_pushButton_wDB_clicked(); protected: void closeEvent(QCloseEvent *event); private: Ui::PlcWidget *ui; QTimer *_pTimer; // 定时发送定时器 PlcClientManager *_pPlcClientManager; // 客户端模式管理类 QThread *_pPlcClientManagerThread; // 客户端模式线程 PlcServerManager *_pPlcServerManager; // 服务器模式管理类 QThread *_pPlcServerManagerThread; // 服务器模式线程 bool _readType; IntByte _intByte; DIntByte _dIntByte; RealByte _realByte; QString _cfg; protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void timerEvent(QTimerEvent *event); private: QPoint _beginPoint; QPoint _leftTopPoint; bool _leftButtonPressed; int _timerId; #endif // PLCWIDGET_H
需求 实现录屏功能。原理 使用抓屏模块按照指定范围和帧率抓屏,同时使用录像模块按照指定图像大小和帧率录制。Demo 体验下载地址 CSDN:https://download.csdn.net/download/qq21497936/13126842 QQ群:1047134658(点击“文件”搜索“ffmpegRecord”,群内与博文同步更新)v1.0.0#ifndef RECORDWIDGET_H #define RECORDWIDGET_H #include <QWidget> #include <QThread> #include <QFileDialog> #include <QDateTime> #include "GrabWindowManager.h" #include "FFmpegRecordManager.h" namespace Ui { class RecordWidget; class RecordWidget : public QWidget Q_OBJECT public: explicit RecordWidget(QWidget *parent = 0); ~RecordWidget(); protected slots: void slot_timeChange(int time); private slots: void on_pushButton_startRecord_clicked(); void on_pushButton_stopRecord_clicked(); void on_pushButton_browser_clicked(); private: Ui::RecordWidget *ui; GrabWindowManager *_pGrabWindowManager; // 抓屏管理类 QThread *_pGrabWindowManagerThread; // 抓屏线程 FFmpegRecordManager *_pFFmpegRecordManager; // 录制管理类 QThread *_pFFmpegRecordManagerThread; // 录制线程 #endif // RECORDWIDGET_H#include "RecordWidget.h" #include "ui_RecordWidget.h" #include <QDateTime> RecordWidget::RecordWidget(QWidget *parent) : QWidget(parent), ui(new Ui::RecordWidget), _pGrabWindowManager(0), _pGrabWindowManagerThread(0) ui->setupUi(this); QString version = "v1.0.0"; setWindowTitle(QString("录屏Demo %1(作者:红胖子(AAA红模仿) QQ:21497936 微信:yangsir198808 博客地址:blog.csdn.net/qq21497936)").arg(version)); // 初始化抓屏线程 _pGrabWindowManagerThread = new QThread(); _pGrabWindowManager = new GrabWindowManager(); _pGrabWindowManager->moveToThread(_pGrabWindowManagerThread); connect(_pGrabWindowManager, SIGNAL(signal_timeChange(int)), this, SLOT(slot_timeChange(int))); _pGrabWindowManagerThread->start(); // 初始化录制线程 _pFFmpegRecordManagerThread = new QThread(); _pFFmpegRecordManager = new FFmpegRecordManager(); _pFFmpegRecordManager->moveToThread(_pFFmpegRecordManagerThread); connect(_pFFmpegRecordManagerThread, SIGNAL(started()), _pFFmpegRecordManager, SLOT(slot_start())); _pFFmpegRecordManagerThread->start(); // 关联信号 connect(_pGrabWindowManager, SIGNAL(signal_grapWindow(QImage)), _pFFmpegRecordManager, SLOT(slot_encoderOneFrame(QImage))); // 按键状态初始化 ui->pushButton_startRecord->setEnabled(true); ui->pushButton_stopRecord->setEnabled(false); ui->lineEdit_dirPath->setReadOnly(true); ui->lineEdit_dirPath->setText(QCoreApplication::applicationDirPath()); ui->lineEdit_value->setValidator(new QIntValidator(1, 100)); ui->lineEdit_fps->setValidator(new QIntValidator(5, 50)); RecordWidget::~RecordWidget() delete ui; void RecordWidget::slot_timeChange(int time) ui->label_time->setText(QString("%1%2:%3%4").arg(time/60/10) .arg(time/60%10) .arg(time%60/10) .arg(time%10)); void RecordWidget::on_pushButton_startRecord_clicked() slot_timeChange(0); QScreen *pScreen = QGuiApplication::primaryScreen(); QRect rect = pScreen->availableGeometry(); _pFFmpegRecordManager->setFps(ui->lineEdit_fps->text().toInt()); _pFFmpegRecordManager->setWidthIn(rect.width()); _pFFmpegRecordManager->setHeightIn(rect.height()); _pFFmpegRecordManager->setWidthOut(rect.width()); _pFFmpegRecordManager->setHeightOut(rect.height()); _pFFmpegRecordManager->setValue(ui->lineEdit_value->text().toInt()); _pFFmpegRecordManager->slot_startEncoder(QString("%1/%2.mp4") .arg(ui->lineEdit_dirPath->text()) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh_mm_ss")), AV_PIX_FMT_BGRA); _pGrabWindowManager->slot_startGrabWindow(rect.x(), rect.y(), rect.width(), rect.height(), ui->lineEdit_fps->text().toInt()); ui->pushButton_startRecord->setEnabled(false); ui->pushButton_stopRecord->setEnabled(true); ui->pushButton_browser->setEnabled(false); ui->lineEdit_fps->setEnabled(false); ui->lineEdit_value->setEnabled(false); void RecordWidget::on_pushButton_stopRecord_clicked() _pGrabWindowManager->slot_stopGrabWindow(); _pFFmpegRecordManager->slot_stopEncoder(); ui->pushButton_startRecord->setEnabled(true); ui->pushButton_stopRecord->setEnabled(false); ui->pushButton_browser->setEnabled(true); ui->lineEdit_fps->setEnabled(true); ui->lineEdit_value->setEnabled(true); void RecordWidget::on_pushButton_browser_clicked() QString dir = QFileDialog::getExistingDirectory(0, "保存到文件夹", "."); if(dir.isEmpty()) return; ui->lineEdit_dirPath->setText(dir); 关于 海思Hi3559安装好sdk和编译器后运行编译器出现“bash: ...aarch64-himix100-linux-c++: No such file or directory” 的解决方法