首先,信号与槽是Qt的基础,信号(Signal)就是触发情况下发出去的事件,槽(Slot)则是信号接收方,即对信号响应的函数。同C++一样,有public、 private、protected 的类状态。
信号与槽的关联:
QObject::connect(sender,SIGNAL(signal()),reciever,SLOT(slot()));
或者
connect(sender,SIGNAL(signal()),reciever,SLOT(slot()));
sender 表示信号发送方,比如一些控件,push button被点击,后会发送一个clicked()信号
signal() 表示信号,slot()表示槽函数。
reciever 表示信号的接受方,比如在使用 this 指针,就是在本界面内的 slot 函数,也表示所在界面内的响应槽函数。
实例:
//**************在 .h 中的 widget 类中*********//
#ifndef WIDGET_H
#define WIDGET_H
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void pushbutton_event();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
//**************在Cpp文件中*************//
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QObject::connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(slot()));//关联操作
}
Widget::~Widget()
{
delete ui;
}
void Widget::pushbutton_event()//槽函数
{
ui->label->setText("pushbutton 被按下");
}
void Widget::on_pushButton_clicked()//这样做是从gui界面直接转到的槽,就不需要在.h中进行了
{
ui->label->setText("pushbutton 被按下222");
}
QString str1 = "welcome";
str1.append("to");
QString str2;
str2.sprintf("%s","you");
QString str3;
str3 =QString("%1 was bron in %2").arg("John").arg(1998);
QString str4 = "welcome";
QString str5 = "to";
str4.insert(7,str5); //在前面位置前,插入字符串
qDebug()<<str4;
str4.prepend(str5); //在str4 字符串的开头插入字符串
qDebug()<<str4;
str4.replace("we",str5); //使用 str5 字符串代替 str4 的指定字符
qDebug()<<str4;
QString str6 = " welco \t mm ";
qDebug()<<str6.trimmed();//去掉字符串两端的空白字符
输出:
“welcometo”
“towelcometo”
“totolcometo”
“welco \t mm”
“welco mm”
/****查询字符串数据*****/
QString str8 = "welcome to you!";
qDebug()<<str8.startsWith("welcome",Qt::CaseSensitive);//判断字符串的开头是不是参数一,参数二是多大小写敏感(默认是敏感的),返回bool
qDebug()<<str8.startsWith("you",Qt::CaseInsensitive);//
qDebug()<<str8.endsWith("you!",Qt::CaseSensitive);//判断结尾字符
qDebug()<<str8.contains("to",Qt::CaseSensitive);//判断“to”字符在str8中出现过没有,返回bool
输出:
true
false
true
true
/*******字符串的转换***********/
QString str9 = "125";
QString str10 = "0xab";
bool ok;
int hex = str9.toInt(&ok,16);//参数1用于判断转换是否成功,参数2指定转换的类型,16即是 十六进制,基数为16
int dec = str9.toInt(&ok,10);//十进制,默认也是十进制,基数为10
int dec2 = str10.toInt(&ok,0);//二进制转整形,基数为0
//toDouble(),toFloat(),toLong(),toLongLong(),一样的
qDebug()<<hex<<" "<<dec<<" "<<dec2;
QByteArray ba1 = str9.toLatin1();//返回一个Latin1-1(ISO8859-1)编码的8位字符串,这个用于在进行串口传输数据时,需要进行此种转换才行
QByteArray ba2 = str9.toUtf8();//返回一个utf-8编码的字符串(utf-8是ASCII码的超集,它支持真个Unicode子集)
QByteArray ba3 = str9.toLocal8Bit();//返回一个系统本地(locale)编码的8位字符串
qDebug()<<ba1<<" "<<ba1.data()<<" "<<ba2 <<" "<<ba3;
输出:
293 125 171
“125” 125 “125” “125”
//QList类
QList<QString> list;
{
QString str("welcome to you!");
list<<str;//赋值
}//限制作用域
qDebug()<<list;
属于链式列表,以非连续的内存快保存数据,且该类型不能用下表访问,只能用迭代器访问
面对很大的列表进行插入操作时,QLinkedList类的效率要比QList高很多。
注意:在一个QVector的前部或者中间位置进行插入操作的速度是很慢的,原因是这样的操作的将会当值内存中的大量数据被移动。
QVector 是可以通过下标进行访问数据的,也可以使用迭代器访问。
Java风格迭代器遍历容器
下面以QList为例,其他类型的使用一致。
对于每一个容器类,Qt提供了类型的 Java 风格迭代器数据类型,即 只读迭代器类 和 读写迭代器类 相比 STL 风格迭代器,Java 风格的使用更加方便,但是存在轻微的性能消耗。
注意:Java 风格的迭代点 位于 列表元素项 之间,要么在第一个数据前,要么在两个相邻数据项之间,要么在最后一个数据的后面
/*******Java 风格 只读迭代器**********/
QList<int> list_int;
{
list_int<<1<<2<<3<<4;
}
QListIterator<int> i(list_int);//以该 list_int 为遍历对象,初始化一个迭代器对象i,此时迭代点位于 list_int 列表第一个数据项的前面,即QListIterator属于向后遍历的函数
for(;i.hasNext();) //使用 hasNext() 函数检查当前迭代点的后面是否存在数据项
{
qDebug()<<i.next();// next() 函数 是使迭代点跳过其后面的数据项,即此时迭代点位于第一个数据项和第二个数据项之间,并返回跳过的数据
}
i.toBack();//将迭代点移动到最后一个数据项的后面
for(;i.hasPrevious();)//检查当前迭代点的前面是否存在数据项,与hasNext()相对
{
qDebug()<<i.previous();//previous() 函数 是使迭代点跳过其前面的数据项,即此时迭代点位于倒数第一个数据项和倒数第二个数据项之间,并返回跳过的数据
}
i.toFront();//将迭代点移动到第一个数据项的前面
qDebug()<<i.peekNext();//返回迭代点后的一个数据项,但是不移动迭代点
qDebug()<<i.peekPrevious();//返回迭代点前的一个数据项,但是不移动迭代点,位于第一个数据前,返回的该数据前的数据就是列表的最后一项(轮回型)
if(i.findNext(3))//向后 逐个遍历检查时候存在数据项为3的。返回bool
{
qDebug()<<"存在3";
}
else if (i.findPrevious(2))//向前 逐个遍历检查时候存在数据项为3的。返回bool
{
qDebug()<<"存在2";
}
/*******Java 风格 读写迭代器**********/
QList<int> list_int_0;
QMutableListIterator<int> n(list_int_0);//以该 list_int_0 为读写对象,创建一个读写迭代器n
for(int j=0;j<10;j++)
{
n.insert(j);// insert() 函数 插入数据到list_int_0;
}
for(n.toFront();n.hasNext();)//初始迭代点到列表开头
{
qDebug()<<n.next();
}
for(n.toBack();n.hasPrevious();)
{
if(n.previous()%2==0) //需要注意的是 previous() 的操作中涉及到了使迭代点向前移动一次
{
n.remove();//删除迭代点 前 的数据项
}
else
{
n.setValue(n.peekNext()*10);//重新设定迭代点 前 的数据
}
}
for(n.toFront();n.hasNext();)
{
qDebug()<<n.next();
}
STL 风格 只读与读写迭代器
Qt 同样为STL 提供了只读和读写的迭代器,需要注意的是 只读迭代器 要比 读写迭代器 运行速度快很多,故尽量多使用只读。
与 Java 风格的区别在于 STL 的迭代点事指向数据项自身的
QList<int> list_int_1;
for(int i=0;i<10;i++)
{
list_int_1.insert(list_int_1.end(),i);// 从列表的最后项开始插入,insert(),指定 插入的位置 与 待插入的值
}
QList<int>::Iterator m; //定义个读写迭代器,注意这是个指针
for( m = list_int_1.begin() ; m != list_int_1.end() ; ++m )
{
qDebug()<<(*m);// 获取 m 迭代指针所指的内容
*m = (*m)*10;
}
QList<int>::const_iterator d;//定义一个只读迭代器,同样属于指针
for(d = list_int_1.constBegin();d != list_int_1.constEnd(); ++d)
{
qDebug()<<*d;
}
QMap
QMap 存储的数据形式是一个键对应一个值,并且按照键Key的顺序存储数据。
QMap 提供了 QMap
存储一键多值的数据时,也可使用 QMultiMap
这个 Key 表示一个关键词的意思
QHash
QHash 以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,QHash就成为了最好的选择。
QHash 也可以存储 一键多值 形式的数据,它的子类 QMultiHash
Java 风格迭代器遍历容器
这里以 QMap 为例,QHash用法和 QMap 相似,相比之下 QHash 的查找速度会快些
QMap<QString,QString> map; //创建一个QMap存储器对象
//存储城市与区号
map.insert("beijing","111");//插入一键一值的操作
map.insert("shanghai","101");
map.insert("chengdu","100");
QMapIterator<QString,QString> i(map);//创建一个QMap的 只读迭代器
for(;i.hasNext();)
{
i.next();
qDebug()<<i.key()<<" : "<<i.value();//打印迭代点后的数据的项的 key 和 value
}
QMutableMapIterator<QString,QString> im(map); //创建一个QMap的 读写迭代器
if(im.findNext("111")) //找到对应值得项,
{
im.setValue("110");
} /*** Java 迭代器 没有提供寻找 key 的函数,所以通过寻找值来确定 ***/
//再次遍容器
QMapIterator<QString,QString> doc(map);//创建一个QMap的 只读迭代器
for(;doc.hasNext();)
{
doc.next();
qDebug()<<doc.key()<<" : "<<doc.value();//打印迭代点后的数据的项的 key 和 value
}
STL 风格迭代器遍历容器
QMap<QString,QString> map2; //创建一个QMap存储器对象
//存储城市与区号
map2.insert("beijing","111");//插入一键一值的操作
map2.insert("shanghai","101");
map2.insert("chengdu","100");
QMap<QString,QString>::const_iterator n;//创建一个只读迭代器
for(n=map2.constBegin();n != map2.constEnd();++n)
{
qDebug()<<" "<<n.key()<<":"<<n.value();
}
QMap<QString,QString>::iterator nm;//创建一个读写迭代器
nm = map2.find("beijing");
if(nm != map2.end())
{
nm.value()="110";
}
QMap<QString,QString>::const_iterator n2;//创建一个只读迭代器,输出
for(n2=map2.constBegin();n2 != map2.constEnd();++n2)
{
qDebug()<<" "<<n2.key()<<":"<<n2.value();
}
QVariant类
相当于一种多变类型,它可以等于任何类型,用于存储,读取时只需要进行转化一次就行
QVariant v(709);
qDebug()<<v.toInt();
QVariant v1("welcome to you!");
qDebug()<<v1.toString();
QMap<QString,QVariant> map;
map["int"] = 709;
map["double"] = 709.709;
map["QString"] = "welcome to you!";
map["color"] = QColor(255,0,0);
qDebug()<<map["int"]<<" :"<<map["int"].toInt();
qDebug()<<map["double"]<<" :"<<map["double"].toDouble();
qDebug()<<map["QString"]<<" :"<<map["QString"].toString();
qDebug()<<map["color"]<<" :"<<map["color"].value<QColor>();
/***
这样使用 value()函数进行转换是因为 QVariant 类型是属于QtCore模块的类,所以它没有QtGui模块中的数据类型(如QColor、QImage以及QPixmap等)提供转换函数,所以需要通过value()函数来操作
***/
QStringList lst;
{
lst<<"A"<<"B"<<"C"<<"D";
}
QVariant v2(lst);
if(v2.type()==QVariant::StringList)//type() 函数类确定QVariant当前所存储的数据类型
{
QStringList list = v2.toStringList();
for(int i=0;i<list.size();i++)
{
qDebug()<<list.at(i);
}
}
注意:这样使用 value()函数进行转换QColor类型是因为 QVariant 类型是属于QtCore模块的类,所以它没有QtGui模块中的数据类型(如QColor、QImage以及QPixmap等)提供转换函数,所以需要通过value()函数来操作。
vertical layout (垂直)
horizontal layout (水平)
Grid layout (网格)
Form layout (窗体)
Buttons类控件
包括:
push button、tool button、radio button、check button、command link button 、dialog button box