<1>qt打包教程(不安装qt也可以用)
https://blog.csdn.net/u014453443/article/details/85837138?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
<2>qt常用的类型转换
(1)字节数组(char、uint8、int8)转QByteArray类
(2)QByteArray类转字节数组(char、uint8、int8)
(3)字节数组转hex字符串
(4)字节数组(char、uint8、int8)转QString
(5)QString转字节数组(char、uint8、int8)
(6)单个数字、字符串,互转
(7)QByteArray与QString互转
QByteArray类提供了类似数组的功能,但功能更强大,常用函数:
只读元素at(n)、读写元素[n]、追加元素append(可以追加QString、char*、char、QByteArray)、迭代器、元素存储区指针data()
1、字节数组转QByteArray类(字节数组是指uint8、int8、char的数组)
直接使用QByteArray的构造函数即可,
1. const char *str="abcde";
2. char u8_arr[3]={0xa1,0xC2,0x3E};
3. QByteArray qa1(str); //qa1,qa2为两个QBytearray类型的变量
4. QByteArray qa2(u8_arr,3);
QByteArray 的元素存储地址可以通过成员函数data()获得,使用*data可以访问QByteArray 的元素
注意:如果数组中有’\0’,那么构造QByteArray对象时,碰到数组的\0构造就停止了
2、QByteArray类转字节数组(char、uint8、int8)
直接*使用QByteArray的成员函数即可
1. QByteArray ba("abcd");
2. char *pArr = ba.data();
3、字节数组转hex字符串(字节数组是指uint8、int8的数组)
1. uint8 u8_arr[3]={0xF5,0x07,0xa5};
2. QByteArray qa2(u8_arr,3);//中转一下
3. QString qstr(qa2.toHex());
4. qDebug()<<qstr.toUpper();//输出字符串:F507A5
QByteArray的toHex()的返回值仍为QByteArray型,因为每一个字节都会变成2个hex字符,所以返回的QByteArray的长度是原来的两倍。
4、字节数组(char、uint8、int8)转QString
如果字节数组有字符串结尾符\0,则可以直接使用QString的构造函数构造QString对象。
如果字节数组没有\0,*可以先把字节数组转成QByteArray,然后用QByteArray构造QString,参考第1条
5、QString转字节数组(char、uint8、int8)
QString转成了char,也就相当于转成了字节数组,
参考:https://blog.csdn.net/lu_embedded/article/details/52465203
这篇文章提到了两种方法:
(1)QString中无中文:
1. QString str;
2. char *ch;
3. QByteArray ba = str.toLatin1(); // 这一行不可少
4. ch=ba.data();//不允许这样用:ch=str.toLatin1().data();
QString中有中文:避免乱码,需要使用QTextCodec
1. #include <QTextCodec>
2. QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));
3. QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
4. QByteArray ba = str.toLocal8Bit(); // toLocal8Bit 支持中文
注意:QString的toLatin1函数返回的QByteArray是带\0的
第三行不可少,如果直接这样转:ch=str.toLatin1().data(),会出错。原因应该是这样的:toLatin1的返回值是值传递,而不是引用传递,使用值传递来传返回值,返回值是位于内存栈上的,语句结束之后,返回值作为一个临时局部变量,被出栈,这时再使用.data()取指针,指针指向的位置已被出栈,不存在了,为了避免这种情况,就是把toLatin1的返回值使用局部变量甚至局部静态变量接收过来,例如这里的ba变量,toLatin1的返回值出栈消失了,但是ba还在,所以再使用ba.data()就可以获取一个有效指针。
(2)先将 QString 转为标准库中的 string 类型,然后将 string 转为 char *
1. QString filename;
2. std::string str = filename.toStdString();
3. const char* ch = str.c_str();
6、单个数字、字符串,互转
(1)数字转字符串两种方法:
①
1. int num = 1000;// 1000 = 0x03E8;
2. QString str = QString("%1").arg(num,4,16,(QChar)'0').toUpper();
这种方法可以把数组转为16进制样式”03E8”、10进制样式的字符串”1000”、8进制样式等
② QString::number(double n, char format = ‘g’, int precision = 6),
如QString str = QString::number(1000);//str=”1000”
(2)字符串转数字:
使用QString的成员函数即可:toInt、toDouble等
字符串的样式可通过形参指定,如
1. QString str = "123";
2. bool OK;
3. int a = str.toInt(&OK, 10);// a=123,OK=true
4. int b = str.toInt(&OK, 16);// b=0x123,OK=true
7、QString转QByteArray方法
QString str("hello");
QByteArray bytes = str.toUtf8(); // QString转QByteArray方法1
QString str("hello");
QByteArray bytes = str.toLatin1(); // QString转QByteArray方法2
QByteArray转QString方法
QByteArray bytes("hello world");
QString string = bytes; // QByteArray转QString方法1
QByteArray bytes("hello world");
QString string;
string.prepend(bytes); // QByteArray转QString方法2
qDebug() << string;
<3>透明按钮
QPushButton *bt =new QPushButton(this);
bt->setText(“ok”);
bt->move(200,100);
bt->setFlat(true);
<4>通过connect函数理解信号槽
connect函数的理解
connect(sender, signal,
receiver, slot,type);
sender:发出信号的对象
signal:发出的信号
receiver:接收信号的对象
slot:该对象接收到信号后的操作(执行的函数)
type:连接种类模式选择
信号槽,实际就是观察者模式。事件发生后,比如按钮检测到自己被点击了一下,它就会发出一个信号signal。这种发出类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,用自己的一个函数(成为槽(slot))来处理这个信号。也就是说,当信号发出时,被连接的槽函数会自动被回调。这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
<5>拓展补充
在编译共享库时,必须将其标记为导出。为了在客户端使用共享库,一些平台可能需要一个特殊的导入声明。
Qt 提供了两个特殊的宏:
Q_DECL_EXPORT
:当编译共享库时,必须将其添加到使用的符号声明。Q_DECL_IMPORT
:当编译一个(使用了该共享库)客户端时,必须将其添加到使用的符号声明。
补充:报错之一——LNK2019 解决办法
编译的时候,出现这样的情况,如图:
(moc_widget.obj👎 error: LNK2019: 无法解析的外部符号 “private: void cdecl Widget::on_pushButton_3_clicked(void)” (?on_pushButton_3_clicked@Widget@@AEAAXXZ),该符号在函数 “private: static void cdecl Widget::qt_static_metacall(class QObject ,enum QMetaObject::Call,int,void *)” (?qt_static_metacall@Widget@@CAXPEAVQObject@@W4Call@QMetaObject@@HPEAPEAX@Z) 中被引用)
这个问题大概率是你的槽函数的声明和实现没有匹配上,可以先:
1.进入文件夹,删除类似这样的文件夹.重新进行编译.
2.项目上面右击,清除,执行Qmake,构建.再来.
3.这是我这次遇到的情况,我之前直接通过按钮右击,转到槽,准备写槽函数,但是发现我的按钮没有命名(默认pushButton),然后我就直接删掉槽函数的实现部分,但是忘掉即使是通过转到槽这样的方式来写槽函数,在头文件中也会生成相应的声明,这时候去头文件把之前的那个声明删除就可以了.
牢记:槽函数的声明和实现要同生死共存亡.
<6>自定义信号槽
只有继承了QObject类的类,才具有信号槽的能力。凡是QObject类(不管是直接子类还是间接子类),都应该在第一行代码写上Q_OBJECT。不管是不是使用信号槽,都应该添加这个宏。
写法如下:
(1)头文件中声明信号
signals:
void Mysignal(); //返回值信号
(2)如何发送信号
connect(returnButton,&QPushButton::clicked,this,&MainWindow2::Sendslot);
void MainWindow2::Sendslot() //点击按钮,发送信号
{
emit Mysignal();
}
(3)处理子窗口的信号(这里以主窗口处理子窗口信号为例)
connect(&w2,&MainWindow2::Mysignal,this,&Widget::dealmainwindow2);
头文件中:signals:一个个函数名,返回值是 void(因为无法获得信号的返回值,所以也就无需返回任何值),参数是该类需要让外界知道的数据。
emit 是 Qt 对 C++ 的扩展,是一个关键字(其实也是一个宏)。emit 的含义是发出,即发出信号
<7>qt 中 QPixmap 类的使用及用 QLabel 显示图像
一般方法(图片显示于label)
ui->label->setPixmap(QPixmap::fromImage(image));
QLabel缩放时维持图像宽高比例不变:
ui->label>setPixmap(QPixmap::fromImage(image).scaled(ui->label->size(),
Qt::KeepAspectRatio,Qt::SmoothTransformation));
若要图像始终填充满QLabel,需要如下语句:
ui->label->setScaledContents(true);
补充: 利用 QLabel 显示 Mat 图像的一个方法为:(with OpenCV 3)
cv::Mat mat = cv::imread(“c:/dev/test.jpg”);
QImage image(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(image.rgbSwapped()));
<8>QT中定时器的使用方法
先创建一个QTimer对象,再将信号timeout()与相应的槽函数相连,然后调用start()函数。接下来,每隔一段时间,定时器便会发出一次timeout()信号。
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
//或写成:
if (myTimer->isActive() == false)
{
myTimer->start(100);
}
timer->stop(); //关闭定时器
<9>QWidget中信号槽用法
以下几种写法均可
(1)connect(ui->Open,SIGNAL(clicked()),this,SLOT(on_Open_clicked()));
(2)connect(ui->btn_open,&QPushButton::clicked,this,&serial::btn_open_port);
(3) btnClose = new QPushButton(this);
connect(btnClose,SIGNAL(clicked()),this,SLOT(close()));
总结:参数一写组件对象名(有ui->和直接定义两种写法)
参数二信号有不同写法
参数三this:在这个界面对应的类触发
参数四槽函数有不同写法(写成槽函数形式/写成某个类的一个方法均可)
注意:qt自带有一些定义好的槽函数,不需要在头文件中声明便可直接用,比如close(),hide()
对一个窗体调用close函数后,如果再调用show(),这个窗体又会被显示出来。
<10>多窗口切换
多窗口切换会用到自定义信号(见前文)
主窗口代码:
//处理子窗口的信号
connect(&w3,&Wave::Wavesignal,this,&Widget::dealwavewindow);
void Widget::dealmainwindow2()
{
//按钮回到主窗口
w2.hide();
this->show();
}
void Widget::showMainwindow2()
{
//按钮显示2窗口
w2.show();
}
解决中文乱码:
使用QString::fromLocal8Bit(“你好”);
使用QStringLiteral(“中国”);
<11>qt画图函数
paintEvent(QPaintEvent*)函数是QWidget类中的虚函数,用于ui的绘制,会在多种情况下被其他函数自动调用,比如update()时