常用数据
0特殊的十六进制
1.十六进制数值转字符
1.1 0x31变为"31"
1.1.1 QByteArray原数据
//QByteArray转十六进制格式显示"1">>"31" 0x06>>"06" 10>>"0A"
QByteArray data;
QString ret(data.toHex().toUpper());//toUpper()大写
QString ret(data.toHex());
QString MainWindow::ByteArrayToHexString(QByteArray data){
QString ret(data.toHex().toUpper());int len = ret.length()/2;//插入空格
for(int i=1;i<len;i++)
{
ret.insert(2*i+i-1," ");
}
return ret;
1.1.2 int或char等常见数值
int data=1512; //"05e8"
QString strsend48503=QString("%1").arg(data,4,16,QLatin1Char('0'));//int型或char型都可
data,//原数据
4, //一共要多少字符
16, //数据进制
QLatin1Char('0')//左侧不足位补什么字符
方法2
int m=0x31;
QString string;
string=QString::number(m,16);//31
1.2 0x31变为"1"
1.2.1 QByteArray原数据
QByteArray byte;
byte.resize(2);
byte[0]=0x31;
byte[1]=0x32;
QString string =byte; // string="12"
1.2.2 int或char等常见数值
int m=0x31;
QString string;
string[0]=m;
qDebug()<<string; //"1"
char ms[]={0x31,0x31,0x31,0x31,0x31};
string=ms;
qDebug()<<string; //"11111"
2十六进制字符转数值
2.1 "31"变为0x31
2.1.1 QByteArray原数据
先转为Qstring吧
或者用于计算的话可以直接使用QByteArray计算,使用数组索引的方式QByteArray与普通char一样用
char ch=0x0C;
QByteArray string;
string.resize(5);
string[0]=0x01; //01
string[1]=ch; //0C
string[2]=++ch; //0D
string[3]=ch&0xF0; //00
string[4]=ch|0xF0; //FD
qDebug()<<string.toHex().toUpper(); //"010C0D00FD"
2.1.2 QString
这个比较麻烦,只能用逐个字节比对的方式
/*
描述:把两个十六进制字符一个十六进制字节
'a','A'>>0xAA
*/
char charToHex(char H,char L)
{
if((H >= '0') && (H <= '9'))
H-='0';
else if((H >= 'A') && (H <= 'F'))
H=H-'A'+10;
else H='*';
if((L >= '0') && (L <= '9'))
L-='0';
else if((L >= 'A') && (L <= 'F'))
L=L-'A'+10;
else L='*';
return ((H&0x0F)<<4)|(L&0x0F);
}
/*
描述:把一个十六进制字符串转化为十六进制数数组
"01 15 26 581512">>{0x01,0x15,0x26,0x58,0x15,0x12}
*/
char* dataTypeConversion::hexStr_To_Hexchar(QString data)
{ //"19885984ac418df"
static char re[200];
for(int re_num=0;re_num<200;re_num++)
{re[re_num]=0;}
int Lenth,cnt=0;
data.remove(' '); //删除字符串中的空格
data=data.toUpper();
Lenth=data.length(); //获取长度
if(Lenth%2==1)
{
data+="0";
Lenth++;
}
std::string ch = data.toStdString();
const char*p = ch.c_str();
char high = 0, low = 0;
int i=0;
for (cnt=0; cnt<Lenth; cnt+=2)
{
high = p[cnt];
low = p[cnt+1];
re[i++]=charToHex(high,low);
}
return re;
}
2.2 "1"变为0x31
2.2.1 QByteArray原数据
QString ret(data.toHex().toUpper());//转为16进制大写 QByteArray.toHex() 转为十六进制字符 '1'>>"31"
/*
描述:把一个十六进制字符串转化为十六进制数数组
"123456">>{0x31,0x32,0x33,0x34,0x35,0x36}
*/
//mode :2显示0x 0:显示空格
QString dataTypeConversion::strToHexstr(QByteArray data,int mode)
{
QString ret(data.toHex().toUpper());//转为16进制大写 QByteArray.toHex() 转为十六进制字符 '1'>>"31"
int len = ret.length()/2;
if(mode==2)
{
ret.insert(0,"0X");
for(int i=1;i<len;i++)
{
ret.insert(4*i+i-1,",0X");//编写格式
}
}
else {
for(int i=1;i<len;i++)
{
ret.insert(2*i+i-1," ");//编写格式
}
}
return ret;
}
2.2.2 QString
数值上直接把QString作为数组计算即可
1.数据类型转化
1.1QByteArray
1.1.1 QByteArray>>QString
QByteArray bytes("hello world汉字");
QString string = bytes; //方法1 直接等于
qDebug()<<string;
string = QString(bytes); //方法2用构造函数
qDebug()<<string;
string.prepend(bytes); //方法3 拼接 三种方法效果除拼接功能外数据一样,汉字显示正常
qDebug()<<string;
//对于本地化编码的字符串,可以用 QString::fromLocal8Bit 函数将字符串源转为 QString 对象;对于 UTF-8 编码的字符串,可以用 QString::fromUtf8 函数实现转换。如果要反过来转换,就 用对应的 to*** 函数。通常情况下有这些函数就够用了。
1.1.2QByteArray>>String
QString string;
std::string str;
str = string.toStdString();
1.1.3QByteArray>>char *
char *ch; //不能定义成ch[n],数组和指针不一样;
QByteArray byte;
ch = byte.data();
1.1.4QByteArray>>unsigned char*(无变化字符)
1.1.5QByteArray>>unsigned char*(十六进制字符)
1.1.6QByteArray>>int
QByteArray bytes("1234");
bool ok; //转换成功为真
int string = bytes.toInt(&ok,10);//1234
bytes=("1A");
bytes.toInt(&ok,10);//错误
bytes=("1A");
bytes.toInt(&ok,16); //26
1.2QString
1.2.1QString >>QByteArray
QString str("hello");
QByteArray bytes = str.toUtf8(); // QString转QByteArray方法1
QString str("hello");
QByteArray bytes = str.toLatin1(); // QString转QByteArray方法2
1.2.2QString >>String
QString string;
std::string str;
str = string.toStdString();
1.2.3QString >>char *
QString string;
char *ch;
ch = string.toLatin1.data();
1.2.4QString >>unsigned char*(无变化字符)
1.2.5QString >>unsigned char*(十六进制字符)
1.2.6QString >>int
QString string="FFAB";
bool ok;
int uch = string.toInt(&ok, 16);//十六进制FFAB=十进制65451 打印显示65451
string="1234";
uch = string.toInt(&ok, 10)+5;//转换结果为1234 加入一个计算得1239
//第二个参数是进制
基本类型 | Qt别称 | 转入函数 | 转出函数 | 描述 |
---|---|---|---|---|
short | qint16 | arg或setNum | toShort | 2 字节长度,有符号短整型。 |
unsigned short | ushort、quint16 | arg或setNum | toUShort | 2 字节长度,无符号短整型。 |
int | qint32 | arg或setNum | toInt | 4 字节长度,有符号整型。 |
unsigned int | uint、quint32 | arg或setNum | toUInt | 4 字节长度,无符号整型。 |
long | 无 | arg或setNum | toLong | 有符号长整型,对于 32 位编程 long 是 4 字节长度,对于 64 位编程是 8 字节长度。 |
unsigned long | ulong | arg或setNum | toULong | 无符号长整型,对于 32 位编程 unsigned long 是 4 字节长度,对于 64 位编程是 8 字节长度。 |
long long | qlonglong、qint64 | arg或setNum | toLongLong | 8 字节长度,有符号长长整型。 |
unsigned long long | qulonglong、quint64 | arg或setNum | toULongLong | 8 字节长度,无符号长长整型。 |
float | 默认情况下无 | arg或setNum | toFloat | 4 字节长度,单精度浮点数。 |
double | 默认情况对应 qreal | arg或setNum | toDouble | 8 字节长度,双精度浮点数。 |
1.3String
1.3.1String>>QByteArray
1.3.2String>>QString
1.3.3String>>char *
1.3.4String>>unsigned char*(无变化字符)
1.3.5String>>unsigned char*(十六进制字符)
1.3.6String>>int
1.4char *
1.2.1char *>>QByteArray
char *ch="145aBc汉字";
QByteArray byte;
byte = QByteArray(ch); //显示"145aBc\xE6\xB1\x89\xE5\xAD\x97"
1.2.2QString
char *ch="145aBc汉字";
QString string= QString(QLatin1String(ch));//"145aBc?±\u0089?\u00AD\u0097"
1.2.2String
1.2.4unsigned char*(无变化字符)
1.2.5unsigned char*(十六进制字符)
1.2.6int
1.5unsigned char*(无变化字符)
1.2.1QByteArray
1.2.2QString
unsigned char uch;
QString string = QString::number(uch,16);
1.2.2String
1.2.4char*(无变化字符)
1.2.5unsigned char*(十六进制字符)
1.2.6int
1.6unsigned char*(十六进制字符)
1.7int
1.7.1 int>>QByteArray
/*int转QByteArray
1584转为 0x15,0x84*/
QByteArray dataTypeConversion::intToByte(int i)
{
QString intToQString=QString("%1").arg(i,4,16,QLatin1Char('0'));
//qDebug()<<intToQString;
QByteArray QStringTovalueQByte = intToQString.toLocal8Bit();
QByteArray valueQByteToHex = QByteArray::fromHex(QStringTovalueQByte);
//qDebug()<<valueQByteToHex.toHex();
return valueQByteToHex;
}
1.7.1.1字符串形式
QByteArray arr;
arr+="//串口配置\r\n";
arr+=QString("comboBoxBaud=%1\r\n").arg(12);
1.7.1.2数值形式
1.2 数值
1.2.1 int转十六进制字符
QString strsend48503=QString("%1").arg(ui->spinBox_485_03IDAddr->value(),4,16,QLatin1Char('0'));//int型或char型都可
1.基本信息
1.1创建的默认程序
1.1.1 main.c
#include "mainwindow.h"
#include <QApplication> //应用程序类
//argc 命令行变量的数量
//*argv[] 命令行变量数组
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //QT中有且只有一个本对象
MainWindow w; //创建一个自定义窗口对象
w.show(); //窗口对象显示
return a.exec();//a.exec 进入消息循环机制 阻塞代码
}
1.1.2 .pro
QT+= core gui #QT包含的模块 core核心模块 gui图形模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets #4版本以上加入 widgets 控件模块
TARGET = untitled1 #目标 生成的exe程序名称
TEMPLATE = app #模板 应用程序
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++11
SOURCES += \ #源文件
main.cpp \
mainwindow.cpp
HEADERS += \ #头文件
mainwindow.h
FORMS += \
mainwindow.ui
...
1.1.3 mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
//构造函数
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) //初始化列表语法
{
ui->setupUi(this);
}
//析构函数
MainWindow::~MainWindow()
{
delete ui;
}
1.1.4 mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow> //当前基类
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT //提供QT中的信号和槽的机制
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
1.2 快捷键
命名规范
类名首字母大写,单词和单词之间首字母大写
函效名、变量名称。。。首字母小写,单词和单词之间首字母大写
常用快捷键
运行ctrl+R
编译 ctrl+B
帮助文档 F1
注释ctrl + /
字体缩放ctrl+鼠标滚轮
整行代码移动ctrl+shift++ ↑或者↓
查找 ctrl+f
自动对齐ctrl+i
同名之间的.h和.cpp切换 ctrl+F4
1.3 基本控件接口
按钮 QPushButton*btn=new QPusheutton
设置父窗口 btn->setParent(this)
显示文本 btn->setText(“aaa”)
移动 btn->move(x,y)
窗口大小 resize(宽,高)
设置固定大小 setFixedSize(宽,高)
设置窗口标题 setWindowTitle(标题名)
1.4 QT打印
头文件:#include
方法:
qDebug()<<"文本"<<endl;
1.4.1 根据数据类型自动打印
short Data_Len_11=-59;
qDebug()<<QString::number(Data_Len_11);
static QString number(int, int base=10);
static QString number(uint, int base=10);
static QString number(long, int base=10);
static QString number(ulong, int base=10);
static QString number(qlonglong, int base=10);
static QString number(qulonglong, int base=10);
static QString number(double, char f='g', int prec=6);
1.5 信号和槽(slots)
1.5.1 示例
connect 进行链接
参数1 信号发送者(指针)
参数2 发送的信号(信号地址)
参数3 信号的接收者(指针)
参数4 处理槽函数(槽函数地址)
connect (mybtn,&MyPushButton::clicked,this,&MyPushButton::closs); //实现MyPushButton类创建的对象mybtn发生clicked时,关闭窗口
connect(btn,&QPushButton::clicked,this,&QWidget::close);//同效果
1.5.2自定义信号槽
需求:
Teacher 类 student类
ClassIsover 下课,老师发送自定义信号,饿了
学生响应饿了的信号,并且请老师吃饭
//信号
class teacher : public QMainWindow
{
Q_OBJECT
public:
explicit teacher(QWidget *parent = nullptr);
signals:
//自定义信号写法
//1、返回void
//2、信号只需要声明,不需要实现
//3、信号可以发生重载
void hungry();
public slots:
};
//自定义的槽函数
class student : public QMainWindow
{
Q_OBJECT
public:
explicit student(QWidget *parent = nullptr);
signals:
//自定义的槽函数 写到public slots下或全局函数 或public下,或者lambda表达式 (匿名函数?)
public slots:
//1、返回void
//2、需要声明,也需要实现
//3、允许重载
void treateat();
};
void student::treateat()
{
qDebug()<<"请老师吃饭";
}
//H文件
class MyWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MyWindow(QWidget *parent = nullptr);
~MyWindow();
student * st;
teacher * te;
void classIsover();
private:
Ui::MyWindow *ui;
};
//cpp文件
MyWindow::MyWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyWindow)
{
ui->setupUi(this);
te=new teacher(this);//此处作为成员,使得构建函数结束后对象还是存在 若前加teacher *将成为局部变量,构架函数结束后会被释放
st=new student(this);
connect(te,&teacher::hungry,st,&student::treateat);
classIsover();
}
void MyWindow::classIsover()
{
//自定义触发信号 emit
emit te->hungry();
}
有参数信号槽
//student类声明中添加
void treateat(QString foodName);
//student添加成员函数重载
void student::treateat(QString foodName)
{
//会导致foodName下显示时带有双引号
//qDebug()<<"请老师吃饭,吃"<<foodName;
//去掉双引号
//先调用.toutf8()转为QByteArray 类型,在调用.data()转为char *
qDebug()<<"请老师吃饭,吃"<<foodName.toUtf8().data();
}
//teacher类声明添加信号 函数重载
void hungry(QString foodName);
//主要运行函数:
//有参信号槽连接
//指针->地址
//函数指针 -> 函数地址
void(teacher::*teacherSignal)(QString)=&teacher::hungry; //teacherSignal是一个teacher类下的指向teacher::hungry的函数指针
//(QString) 是参数列表
void(student::*studentSlot)(QString)=&student::treateat;
connect(te,teacherSignal,st,studentSlot);
classIsover();
断开信号槽连接
disconnect(te,teacherSignal,st,studentSlot);
信号连接信号
//信号连接信号
QPushButton *btn=new QPushButton(this);
this->resize(600,400);
btn->setText("下课");
void(teacher::*teacherSignal2)()=&teacher::hungry; //teacherSignal是一个teacher类下的指向teacher::hungry的函数指针
void(student::*studentSlot2)()=&student::treateat;
connect(te,teacherSignal2,st,studentSlot2);
connect(btn,&QPushButton::clicked,te,teacherSignal2);
//多个信号可以连接同一个信号槽
//信号和槽函数的参数必须一一对应,参数个数可以不一致,信号的个数要大于等于槽函数个数(逻辑就是多给的可以不用)
//当自定义信号和槽发生重载之后,要利用函数指针明确指出函数地址
1.5.3 Lambda 表达式
Lambda表达式属于自定义槽函数的一种
Lambda表达式用于定义并创建匿名的函数对象
Lambda 的语法形式如下:
[函数对象参数] (操作符重载函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}
可以看到,Lambda 主要分为五个部分:[函数对象参数]、(操作符重载函数参数)、mutable 或 exception 声明、-> 返回值类型、{函数体}.
[函数对象参数]
标识一个 Lambda 表达式的开始,这部分必须存在,不能省略。函数对象参数是传递给编译器自动生成的函数对象类的构造
函数的。函数对象参数只能使用那些到定义 Lambda 为止时 Lambda 所在作用范围内可见的局部变量(包括 Lambda 所在类
的 this)。函数对象参数有以下形式:
-
空。没有任何函数对象参数。
-
=。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
-
&。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式(相当于是编译器自动为我们按引用传递了所有局部变量)。
-
this。函数体内可以使用 Lambda 所在类中的成员变量。
-
a。将 a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要修改传递进来的拷贝,可以添加 mutable 修饰符。
-
&a。将 a 按引用进行传递。
-
a,&b。将 a 按值传递,b 按引用进行传递。
-
=,&a,&b。除 a 和 b 按引用进行传递外,其他参数都按值进行传递。
-
&,a,b。除 a 和 b 按值进行传递外,其他参数都按引用进行传递。
(操作符重载函数参数)
标识重载的 () 操作符的参数,没有参数时,这部分可以省略。参数可以通过按值(如: (a, b))和按引用 (如: (&a, &b)) 两种
方式进行传递。
mutable 或 exception 声明
这部分可以省略。按值传递函数对象参数时,加上 mutable 修饰符后,可以修改传递进来的拷贝(注意是能修改拷贝,而不是
值本身)。exception 声明用于指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw(int)。
-> 返回值类型
标识函数返回值的类型,当返回值为 void,或者函数体中只有一处 return 的地方(此时编译器可以自动推断出返回值类型)
时,这部分可以省略。
{函数体}
标识函数的实现,这部分不能省略,但函数体可以为空。
//lambda表达式
//[=] 作用在范围内所有可见的局部变量
//[&] 引用传递,有时出现问题,引用btn进入只读状态
//推荐使用lambda表达式 : [=](){}
//[变量名] 只有该变量能用
//lambda表达式相当于你在某个函数体内定义了一个变量,当该函数内有直接新定义的函数体时,由于该函数内的变量新函数内不可使用,
// 加入lambda表达式可用
connect(btn,&QPushButton::clicked,this,[=]()
{
//btn->setText("aaa");//btn不在connect包含的函数体内 []内加=即可
btn->setText("aaa");
});
//mutab1e 关键字
//加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
QPushButton *myBtn=new QPushButton (this);
QPushButton * myBtn2=new QPushButton (this);
myBtn->move(200,150);
myBtn2->move(300,150);
int m=10;
connect(myBtn,&QPushButton::clicked,this,[m]()mutable {m=20;qDebug()<<m;});
connect(myBtn2,&QPushButton::clicked,this,[=](){qDebug()<<m;});
qDebug()<<m;
//以上的现象是 按下按键1 打印20 按下按键2 打印10
//即mutable 使得传入的m的值可以改变,同时{}结束后M的值有变回去,即mutable改变的是传入值的拷贝
//->返回值+类型
int n=10;
n=[]()->int {return 100000;}();
qDebug()<<"n="<<n;
//利用Lambda表达式实现点击按钮关闭窗口
//点击btn2按钮实现关闭窗口
QPushButton * myBtn3=new QPushButton (this);
myBtn3->move(400,150);
myBtn3->setText("关闭窗口");
connect(myBtn3,&QPushButton::clicked,this,[=]()
{
this->close();
});
从connect看lambda表达式,connect的第四个参数槽函数需要传递进地址,lambda表达式就相当于不需要从别处引入函数地址,直接在connect参数列表中写函数体,[]内用于向函数体传递参数,{}内写入具体函数实现
connect(myBtn3,&QPushButton::clicked,this,[=]() { this->close();}); //this可以省略
connect(myBtn3,&QPushButton::clicked,[=]() { this->close();});
总结:
1.常用使用:
[=](){}
2.加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
3.返回值
n=[]()->int{return 100000;}();
1.5.3 mutable使用
如果connect内想更改传递进来的变量,需要使用mutable关键字
/*正常使用格式*/
connect(serial,&QSerialPort::readyRead,this,[=](){
//.....
});
/*mutable使用格式*/
connect(serial,&QSerialPort::readyRead,this,[=]()mutable //mutable加上才能更改传进来的变量
{
//.....
});
1.6 菜单栏
1.6.1设置菜单栏和工具栏
1.菜单栏 头文件#include
//菜单栏 只有一个
QMenuBar * bar =menuBar(); //只能有一个 所以不用new
//将菜单栏设置到窗口中
setMenuBar(bar);
//设置菜单
QMenu *fileMenu = bar->addMenu("文件");
QMenu *editMenu = bar->addMenu("编辑");
//添加菜单项
QAction *newFile=fileMenu->addAction("新建");
//添加分割线
fileMenu->addSeparator();
//添加菜单项
QAction *openFile=fileMenu->addAction("打开");
2.工具栏 头文件 #include
//工具栏 可以有多个
QToolBar *toolbar=new QToolBar(); //能有多个 所以用new
//将工具栏设置到窗口中
//addToolBar(toolbar);//默认在上面
addToolBar(Qt::LeftToolBarArea,toolbar);//设定到左边 所有枚举都在Qt:: 作用域下
//只允许左右停靠
toolbar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//关闭浮动
//toolbar->setFloatable(false);
//设置移动
toolbar->setMovable(false);//关闭移动,工具栏不可拖动
//工具栏中添加小控件
QPushButton *btn=new QPushButton("按钮1",this);
toolbar->addWidget(btn);//按钮放入工具栏
//工具栏中添加菜单项
toolbar->addAction(newFile);
//添加分割线
toolbar->addSeparator();
toolbar->addAction(openFile);
1.6.2 状态栏和铆接部件
1.状态栏 头文件 #include
标签 头文件 #include
//状态栏 只有一个
QStatusBar* status= statusBar();//只能有一个 所以不用new
//将状态栏放入窗口中
setStatusBar(status);
//放入标签
QLabel * staLabel=new QLabel("左侧信息",this);
//将标签放入状态栏
status->addWidget(staLabel);//从左往右放
QLabel * staLabel2=new QLabel("右侧信息",this);
status->addPermanentWidget(staLabel2);//从右往左放
2.铆接部件 头文件 #include
核心部件 头文件 #include
铆接部件的位置是相对于核心部件的
//状态栏 只有一个
QStatusBar* status= statusBar();
//将状态栏放入窗口中
setStatusBar(status);
//放入标签
QLabel * staLabel=new QLabel("左侧信息",this);
//将标签放入状态栏
status->addWidget(staLabel);//从左往右放
QLabel * staLabel2=new QLabel("右侧信息",this);
status->addPermanentWidget(staLabel2);//从右往左放
//铆接部件 浮动窗口
QDockWidget *dock=new QDockWidget("铆接部件",this);
//放入窗口内
addDockWidget(Qt::BottomDockWidgetArea,dock);
//设置停靠位置
dock->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);
//核心部件 只能有一个
QTextEdit *edit=new QTextEdit(this);
setCentralWidget(edit);
1.7 资源文件
1.将资源导入到项目下
2.添加文件 ->Qt->Qt Recourse File
3.起名称 res,生成res.grc文件
4.右键-open in editor用编辑的方式打开
5.添加前缀名/
6.添加文件
7.资源文件 使用方式“:+前缀名+文件名”
1.8 对话框
1.8.1 自定义对话框
头文件 #include
对话框分类
1.模态对话框 //不可以对其他窗口进行操作
2.非模态对话框 //可以对其他窗口进行操作
connect( ui->actionnew,&QAction::triggered ,[=](){ //actionnew新建菜单栏或工具栏
//对话框分类
//模态对话框 //不可以对其他窗口进行操作
//非模态对话框 //可以对其他窗口进行操作
//模态对话框
// QDialog dlg(this);
// dlg.resize(120,60);
// dlg.exec(); //阻塞
//非模态对话框
// QDialog dlg2(this); //由于在函数内(堆区) 函数结束后就没了
// dlg2.resize(120,60);
// dlg2.show();
QDialog *dlg2=new QDialog(this); //用指针方式创建在栈区
dlg2->resize(120,60);
dlg2->show();
dlg2->setAttribute(Qt::WA_DeleteOnClose); //55号属性 由于在栈区 只有文件关闭后内存才释放,为防止关闭前多次弹出对话框导致的内存浪费,设为关闭即释放
qDebug()<<"弹出对话框";});
两种对话框的不同仅在于显示方式,模态对话框dlg.exec(); //阻塞非模态对话框 dlg2.show();
1.8.2 系统对话框
都是模态
1.Qt 的内置对话框大致分为以下几类:
QColorDialog:选择颜色;
QFileDialog:选择文件或者目录;
QFontDialog:选择字体;
QInputDialog:允许用户输入一个值,并将其值返回;
QMessageBox:模态对话框,用于显示信息、询问问题等;
QPageSetupDialog:为打印机提供纸张相关的选项;
QPrintDialog:打印机配置;
QPrintPreviewDialog:打印预览;
QProgressDialog:显示操作过程。
2.头文件 #include
3.QMessageBox:: 对话框功能(参数…); 返回数据类型 StandardButton
参数1:父窗口;参数2:窗口标题;参数3:提示信息;参数4:按键类型 参数5:默认激活按键
参数4中可以改变按钮的名称,同时可以改变按钮数量A|B|C就会弹出3个 A|B就是两个
//QMessageBox 模态对话框
//错误提示对话框
connect( ui->actioncritical ,&QAction::triggered ,[=](){
QMessageBox::critical(this,"错误","critical文本");
});
//信息提示对话框
connect( ui->actioninfro ,&QAction::triggered ,[=](){
QMessageBox::information(this,"信息","information文本");
});
//询问 二选一
//QMessageBox 参数1:父窗口;参数2:窗口标题;参数3:提示信息;参数4:按键类型 参数5:默认激活按键
connect( ui->actionques ,&QAction::triggered ,[=](){
if(QMessageBox::Save== QMessageBox::question(this,"询问","question文本",QMessageBox::Save|QMessageBox::Cancel|QMessageBox::Close,QMessageBox::Close))
{
qDebug()<<"保存";
}
else {
qDebug()<<"放弃";
}
});
//警告
connect( ui->actionwarn ,&QAction::triggered ,[=](){
QMessageBox::warning(this,"警告","warning");
});
1.7.2.1 QInputDialog
允许用户输入一个值,并将其值返回;
1.头文件:
#include <QMessageBox>
#include <QDir>
bool ok;
QString text = QInputDialog::getText(this, tr("请输入按钮文本"),
tr("按钮"), QLineEdit::Normal,
QDir::home().dirName(), &ok);
if (ok && !text.isEmpty())
{
qDebug()<<text;
this->setText(text);
}
1.8.3 其他对话框
1.8.3.1 文件选取对话框
1.头文件 #include
2.QFileDialog::getOpenFileName(参数…); 返回数据类型 Qtring
参数1:父窗口;参数2:显示信息;参数3:默认路径;参数4:文件类型过滤
//文件对话框
connect( ui->actionopen ,&QAction::triggered ,[=](){
//参数1:父窗口;参数2:显示信息;参数3:默认路径;参数4:文件类型过滤
QString fileName =QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\Administrator\\Desktop\\QT\\05\\Dialog","(*.cpp)");
qDebug()<<fileName; //带路径的文件名
});
1.8.3.2 颜色对话框
1.头文件 #include
2.QColorDialog::getColor(QColor(255,0,0)); 返回数据类型 QColor
//颜色对话框
connect( ui->actioncolor ,&QAction::triggered ,[=](){
QColor color = QColorDialog::getColor(QColor(255,0,0));
if (color.isValid()) {
qDebug()<<color.red()<<color.green()<<color.blue(); //打印颜色
}
};
1.8.3.3 字体对话框
1.头文件 #include
2.QFontDialog::getFont(&ok,QFont(“仿宋”,36)); 返回数据类型 QFont
connect( ui->actionfont ,&QAction::triggered ,[=](){
bool ok;//标记选择的字体是否存在
//参数1:布尔量;参数2:QFont
//QFont 参数1:默认字体;参数2:字号
QFont font=QFontDialog::getFont(&ok,QFont("仿宋",36));
qDebug()<<"字体"<<font.family().toUtf8().data()<<"字号"<<font.pointSize()<<"是否倾斜"<<font.italic()<<"是否加粗"<<font.bold();
});
1.9 常用控件
1.9.1 按钮控件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJK14NL9-1600760844863)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1571097962141.png)]
1.添加图片[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-43CCkc8k-1600760844864)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1571098010998.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aMAJdekB-1600760844865)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1571098040453.png)]
3.Radio button 单选 默认窗口下所有单选按钮都是一个组,即只有一个有效,可以选择Containers下的Group Box控件做分组
ui->radioButton_nan->setChecked(true);//设置单选框默认选中
1.9.1.1 QPushButton
1.设定显示文本 this->setText(text);
2.读取显示文本 this->text()
3.获取关闭打开状态
connect(ui->pushButton_ON,&QPushButton::toggled,[=](bool clicked){
if(clicked){ //打开
ui->pushButton_ON->setText("关闭串口");
}
else{
ui->pushButton_ON->setText("打开串口");
}
});
1.9.1.2 CheckBox 复选按钮
2.状态及返回值:选中是2,不选中是0 tristate选中后 半选中是1 全选中是2 不选是0
connect(ui->checkBox,&QCheckBox::stateChanged,[](int state){
qDebug()<<"state="<<state;//选中是2,不选中是0 tristate选中后 半选中是1 全选中是2 不选是0
});//int state 信号有一个参数,槽函数也加一个参数
2.设定状态
ui->checkBoxHexDis->setCheckState(Qt::Checked)
ui->checkBoxHexDis->setCheckState(Qt::CheckState(filearr.toInt()));//枚举强制类型转换
//Qt::Unchecked 0 The item is unchecked.
//Qt::PartiallyChecked 1 The item is partially checked. Items in hierarchical models may be partially checked if some, but not all, of their children are checked.
//Qt::Checked 2 The item is checked.
枚举类型本身就是int类型的。
所以,c++中,int转换为枚举类型,直接强制转换就可以。
类似于下面这样:
OrderDataEntity::ENUM_ORDER_DELIVERY_TYPE( 2 )
OrderDataEntity::ENUM_ORDER_DELIVERY_TYPE这个是枚举类型。
1.9.1.3 tool button控件
1.设置点击后不自动弹回
QAbstractButton checkable
2.tool button控件 主要显示图片 toolbuttonStyle选择图片和文本的相对位置
autoRaise 打钩后按钮边框隐藏,鼠标移动到该位置时出现边框。
1.9.2 ltem Widgets(Item-Based)
1.9.2.1 List Widgets
1.每个项都称为 QListWidgetitem *item=new QListwidgettem(“aaa”)
ui->ListWidgt->addutem(item)
2.设置对齐item->setTextAlignment(at::AligniCenter);
3.一次性加入所有数据
QStringList list;
list<<“锄禾日当午”<<“汗滴禾下土”<<”谁知盘中餐<<”粒粒皆辛苦”;
ui->listwidget->addltems(list);
// listWidget
QListWidgetItem * item=new QListWidgetItem("锄禾日当午"); //单独的一项
ui->listWidget->addItem(item); //加入至列表
QStringList List; //多个一起,因为每个项其实都是一个QStringList
List<<"123"<<"456"<<"789";
item->setTextAlignment(Qt::AlignHCenter);//对齐方式
ui->listWidget->addItems(List); //显示多个项
1.9.2.2 tree Widgets
1.设置头 ui->treeWidget->setHeaderLabels(QStringList()<<“英雄”<<“介绍”);
2.添加根节点
QTreeWidgetItem * treeitem_L=new QTreeWidgetItem(QStringList()<<“力量”);
ui->treeWidget->addTopLevelItem(treeitem_L);
3.添加子节点
QStringList heroL1,heroL2;
heroL1<<“刚被猪”<<“前排坦克,能在吸收伤害的同时造成可观的范围输出”;
QTreeWidgetItem *L1=new QTreeWidgetItem(heroL1);
treeitem_L->addChild(L1);
//treeWidget
//设置头
ui->treeWidget->setHeaderLabels(QStringList()<<"英雄"<<"介绍");
//treeWidget每个项都称为 QTreeWidgetItem
QTreeWidgetItem * treeitem_L=new QTreeWidgetItem(QStringList()<<"力量");
QTreeWidgetItem * treeitem_M=new QTreeWidgetItem(QStringList()<<"敏捷");
QTreeWidgetItem * treeitem_Z=new QTreeWidgetItem(QStringList()<<"智力");
//添加根节点
ui->treeWidget->addTopLevelItem(treeitem_L);
ui->treeWidget->addTopLevelItem(treeitem_M);
ui->treeWidget->addTopLevelItem(treeitem_Z);
QStringList heroL1,heroL2;
QStringList heroM1,heroM2;
QStringList heroz1,heroz2;
heroL1<<"刚被猪"<<"前排坦克,能在吸收伤害的同时造成可观的范围输出";
heroL2<<"船长"<<"前排坦克,能肉能输出能控场的全能英雄";
heroM1<<"月骑"<<"中排物理输出,可以使用分裂利刃攻击多个目标";
heroM2<<"小鱼人"<<"前排战士,擅长偷取敌人的属性来增强自身战力";
heroz1<<"死灵法师"<<"前排法师坦克,魔法抗性较高,拥有治疗技能";
heroz2<<"巫医"<<"后排辅助法师,可以使用奇特的巫术诅咒敌人与治疗队友";
//添加子节点
QTreeWidgetItem *L1=new QTreeWidgetItem(heroL1);
QTreeWidgetItem *L2=new QTreeWidgetItem(heroL2);
treeitem_L->addChild(L1);
treeitem_L->addChild(L2);
QTreeWidgetItem *M1=new QTreeWidgetItem(heroM1);
QTreeWidgetItem *M2=new QTreeWidgetItem(heroM2);
treeitem_M->addChild(M1);
treeitem_M->addChild(M2);
QTreeWidgetItem *z1=new QTreeWidgetItem(heroz1);
QTreeWidgetItem *z2=new QTreeWidgetItem(heroz2);
treeitem_Z->addChild(z1);
treeitem_Z->addChild(z2);
1.9.2.3 table widgets
1.设置列 ui->tableWidget->setColumnCount(3);
2.设置水平表头 ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<“姓名”<<“性别”<<“年龄”);
3.设置行 ui->tableWidget->setRowCount(5);
4.设置正文 ui->tableWidget->setItem(0,0,new QTableWidgetItem(“亚瑟”));
//tableWidget
//设置列
ui->tableWidget->setColumnCount(3);
//设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<<"性别"<<"年龄");
//设置行数
ui->tableWidget->setRowCount(5);
//设置具体内容
ui->tableWidget->setItem(0,0,new QTableWidgetItem("亚瑟"));
QList<QString> namelist;
namelist<<"亚瑟"<<"妲己"<<"安琪拉"<<"赵云"<<"关羽";
QStringList sexList;
sexList<<"男"<<"女"<<"女"<<"男"<<"男";
for(int i=0;i<5;i++)
{
int col=0;
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(namelist[i]));
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(sexList.at(i)));
//int 转QString
ui->tableWidget->setItem(i,col++,new QTableWidgetItem(QString::number(18+i)));
}
//读取
QString tabeDate[ui->tableWidgetCOPY->rowCount()][ui->tableWidgetCOPY->columnCount()];
for(int i=0; i<ui->tableWidgetCOPY->rowCount(); i++)
{
for(int j=0; j<ui->tableWidgetCOPY->columnCount(); j++)
{
tabeDate[i][j] = ui->tableWidgetCOPY->item(i, j)->text();
}
}
1.9.3 显示控件
1.9.3.1 QTextEdit
1.多行可改字体和颜色
2.更改颜色
QPalette palette = ui->lineEdit->palette();
const QColor &color = QColorDialog::getColor(palette.color(QPalette::Background), this);
if (color.isValid()) {
palette.setColor(QPalette::Highlight, color);
ui->lineEdit->setPalette(palette);
}
此处:palette.setColor(QPalette::Highlight, color);
QPalette::Highlight // 被选中后文字的背景色.
QPalette::HighlightText // 被选中后文字的前景色.
QPalette::Text // 文字的前景色
QPalette::Base // QTextEdit的背景色, 默认是白色的.
3.更改字体
4.设置光标至文件末尾
QTextCursor tmpCursor = ui->textRe->textCursor();
tmpCursor.movePosition(QTextCursor::Left, QTextCursor::MoveAnchor, 4);
ui->textRe->setTextCursor(tmpCursor);
ui->textRe->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
5.读取
ui->textEdit_Re->toPlainText()
6.从光标处添加文本
ui->textRe->append(str);//str内容添加到光标之后 自动回车
使用添加文本需在添加之前使用过
ui->textRe->document()->setMaximumBlockCount(1000);//设置显示可添加次数
1.9.3.2 QSpinBox
数字输入显示
prefix //数字显示的前缀
suffix //数字显示的后缀
minimum //数值范围的最小值
maximum //数值范围的最大值
singlestep //设置步长,即调整按钮单步改变值
vlaue //当前显示值
displayInegerBase //QSpinBox的特有属性,显示整数使用的进制
decimals //QDoubleSpinBox的特有属性,显示数值小数的位数
1.9.4 其他控件
1.各种多选窗口更改窗口标签名称 currentitemText
例下拉框的各种操作
ui->setupUi(this);
//设置stackedWidget窗口默认界面
ui->stackedWidget->setCurrentIndex(0);
//下拉
ui->comboBox->addItem("9600");
ui->comboBox->addItem("19200");
ui->comboBox->addItem("115200");
//定位到某个选项
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("115200");
3…Stacked Widget控件运行时没有切换按钮,需要使用其他控件控制显示切换
ui->stackedWidget->setCurrentIndex(0);
4.Label可以显示图片
//利用Label 显示图片
ui->labelimage->setPixmap(QPixmap("://Icon/play.png"));
//利用Label 显示动图
QMovie *movie=new QMovie("://Icon/aa.gif");
ui->labelgif->setMovie(movie);
//播放movie图片
movie->start();
1.9.5 自定义控件
-
添加一个类 Qt设计师界面类 包含.h .cpp和.ui文件
-
ui界面设计完成后 提升将基类名称填写正确 注意与.cpp文件内的类名相同,与文件名无关
-
封装信号和槽,将自定义控件内的控件之间连接起来,同时在可以将类添加对外接口,实现自定义控件与主界面的数据连接
-
主文件
//设置和读取自定义控件的值 connect(ui->btn_Set10,&QPushButton::clicked,[=](){ ui->widget->setData(10); }); connect(ui->btn_Read,&QPushButton::clicked,[=](){ qDebug()<<ui->widget->getData(); });
-
自定义控件内部连接
//QSpinBox 移动 QSlider跟着动 void (QSpinBox::*spinSignal)(int)=&QSpinBox::valueChanged; connect(ui->spinBox,spinSignal,ui->verticalSlider,&QSlider::setValue); //QSlider 移动 QSpinBox跟着动 connect(ui->verticalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
-
自定义控件对外接口
void smallWidget::setData(int val) { ui->spinBox->setValue(val); //也有改变的信号 } int smallWidget::getData() { return ui->spinBox->value(); }
class smallWidget : public QWidget
{
Q_OBJECT
public:
explicit smallWidget(QWidget *parent = nullptr);
~smallWidget();
void setData(int val);
int getData();
private:
Ui::smallWidget *ui;
};
7.自定义控件需要注意信号的问题,示例鼠标左键单击事件
改写了一个函数:mouseReleaseEvent,在鼠标点击自定义控件后发射信号
类声明在signal下添加函数声明,只需声明,不需要函数实现,返回值void,命名不要与原类重复,出现了不触发槽的问题。
添加鼠标点击事件
class ClickedLabel : public QLabel
{
Q_OBJECT
signals:
void My_licked();// 信号
public:
...
protected:
void mouseReleaseEvent( QMouseEvent* ); //鼠标点击事件
private:
QString m_str;
};
类实体中加入信号触发函数
void ClickedLabel::mouseReleaseEvent(QMouseEvent *evt)
{
emit this->My_licked(); //emit关键字用于发出信号
}
2.进阶
2.1 事件处理
2.1.1 捕获QLabel中的鼠标事件
1.新建一个QLabel子类 右键工程>>Add new >>c++>>C++ Class>>Base class(QLable)
2.将mylable中的#include换为QLabel(H),父类继承换为QLabel(Cpp+H),
3.主界面的QLable提升为自定义的QLable
4.H文件添加
class MyLable : public QLabel
{
Q_OBJECT
public:
explicit MyLable(QWidget *parent = nullptr);
//鼠标进入
void enterEvent(QEvent *);
//鼠标离开
void leaveEvent(QEvent *);
//鼠标按下
void mousePressEvent(QMouseEvent *ev) ;
//鼠标释放
void mouseReleaseEvent(QMouseEvent *ev) ;
//鼠标移动
void mouseMoveEvent(QMouseEvent *ev) ;
signals:
public slots:
};
5.cpp文件添加
#include <QMouseEvent>
MyLable::MyLable(QWidget *parent) : QLabel(parent)
{
this->setMouseTracking(true);//设置鼠标追踪,加上之后就可以不按下也有移动
}
//鼠标进入
void MyLable::enterEvent(QEvent *)
{
qDebug()<<"鼠标进入";
}
//鼠标离开
void MyLable::leaveEvent(QEvent *)
{
qDebug()<<"鼠标离开";
}
//鼠标按下
void MyLable::mousePressEvent(QMouseEvent *ev)
{
//设置只有鼠标左键按下
//Qt::LeftButton
//Qt::RightButton
//Qt::MidButton
if(ev->button()==Qt::LeftButton)
{qDebug()<<"左键";}
if(ev->button()==Qt::RightButton)
{qDebug()<<"右键";}
if(ev->button()==Qt::MidButton)
{qDebug()<<"中键";}
QString str=QString("鼠标按下 X=%1 Y=%2").arg(ev->x()).arg(ev->y()); //格式化输入
qDebug()<<str;
}
//鼠标释放
void MyLable::mouseReleaseEvent(QMouseEvent *ev)
{
QString str=QString("鼠标释放 X=%1 Y=%2").arg(ev->x()).arg(ev->y()); //格式化输入
qDebug()<<str;
}
//鼠标移动
void MyLable::mouseMoveEvent(QMouseEvent *ev)
{
//由于鼠标运动与其他事件不同,需要使用多种按键判断
if(ev->buttons() & Qt::LeftButton)//包含左键按下
{qDebug()<<"左键移动";}
if(ev->buttons() & Qt::RightButton)//包含右键按下
{qDebug()<<"右键移动";}
QString str=QString("鼠标移动 X=%1 Y=%2").arg(ev->x()).arg(ev->y()); //格式化输入
qDebug()<<str;
}
6.其中比较重要的点
6.1 鼠标事件头文件#include
6.2 设置鼠标追踪 this->setMouseTracking(true);//,加上之后就可以不按下也有移动
6.3鼠标移动和其他事件在区分左右按键有不一样
ev->buttons() & 左值 同时获取多个按键状态
6.4 按键状态
//Qt::LeftButton
//Qt::RightButton
//Qt::MidButton
6.5 QString 格式化输入
QString str=QString(“鼠标移动 X=%1 Y=%2”).arg(ev->x()).arg(ev->y()); //格式化输入
2.1.2 定时器事件一
1.定时器事件
//定时器事件
void timerEvent(QTimerEvent *);
//定时器事件
void Widget::timerEvent(QTimerEvent *tim)
{
...
}
2.启动定时器
ID_Timer1=startTimer(1000);
ID_Timer2=startTimer(2000); //开启一个新的定时器 startTimer是有返回值的 返回值就是用来区分不同定时器的ID
3.区分不同定时器
void Widget::timerEvent(QTimerEvent *tim)
{
if(tim->timerId()==ID_Timer1)
{
...
}
}
4.实例H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
//定时器事件
void timerEvent(QTimerEvent *);
int ID_Timer1;
int ID_Timer2;
private:
Ui::Widget *ui;
};
5.实例cpp
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//启动定时器 参数1:int,间隔(ms);
ID_Timer1=startTimer(1000);
ID_Timer2=startTimer(2000); //开启一个新的定时器 startTimer是有返回值的 返回值就是用来区分不同定时器的ID
}
Widget::~Widget()
{
delete ui;
}
//定时器事件
void Widget::timerEvent(QTimerEvent *tim)
{
if(tim->timerId()==ID_Timer1)
{
static int num;
ui->label_2->setText(QString::number(num++));
}
else {
if(tim->timerId()==ID_Timer2)
{
static int num2;
ui->label_3->setText(QString::number(num2++));
}
}
}
2.1.3 定时器类
1.头文件:#include “QTimer”
2.创建类
QTimer *timer =new QTimer(this);
3.启动停止
timer->start(500);//启动 ms
timer->stop(); //定时器关
4.事件触发
connect(timer,&QTimer::timeout,[=](){
static int num =1;
ui->label_3->setText(QString::number(num));
});
5.实例
//利用Qtimer定时器类 实现定时
QTimer *timer =new QTimer(this);
timer->start(500);//启动 ms
connect(timer,&QTimer::timeout,[=](){
static int num =1;
ui->label_3->setText(QString::number(num));
});
//timer->stop(); //定时器关
2.1.4事件分发器
1.bool event(QEyent *e)
5.2 e->type())所有Qt中的事件
5.3事件分发器中可以做事住的拦截操作,如果用户进行了拦截,在对应的事件里返回true代表自己处理事件
2.1.5 事件过滤器
步骤1给控件安装事件过滤器
ui->label->installEventFilter(this);
步骤2重写ventFilter事件
bool Widget:eventFilter(QObiect *obj,QEvent*e );
3 文件读写
3.1 简单读写
1.头文件
#include <QFile> //文件
#include <QTextCodec> //编码
2.读
ui->lineEdit->setText(filePath);
QTextCodec *codec = QTextCodec::codecForName("gbk"); //编码格式
//文件内容放入textEdit
QFile file(filePath);
//设置打开方式
file.open(QIODevice::ReadOnly);//只读方式打开
QByteArray arr;
//arr=file.readAll();
//显示arr
// ui->textEdit->setText(codec->toUnicode(arr)); //以gbk编码方式显示
//默认支持的格式是utf-8
//方法二
while(!file.atEnd())
{
arr+=file.readLine();
}
ui->textEdit->setText(codec->toUnicode(arr));
file.close();
3.写
file.open(QIODevice::Append);//从文件尾开始写
file.write("12345asdf忽必烈没事的");///汉字乱码
file.close();
4.获取当前路径
QDir::currentPath();
4 音效
QSound *sound=new QSound ;
sound->play();
QString
QString & append(const QString & str)
append 追加子串到字符串尾部。
QString & prepend(const QString & str)
prepend 将子串加到字符串头部。
bool startsWith(const QString & s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
startsWith 判断字符串(如 "abcd")是否以某个子串(如 s 是 "ab")打头,cs 指判断时大小写是否敏感 ,返回 bool。
bool endsWith(const QString & s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
endsWith 判断字符串(如 "abcd")是否以某个子串(如 s 是 "cd")结尾,cs 指判断时大小写是否敏感,返回 bool。
bool contains(const QString & str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
contains 判断字符串对象里是否包含子串 str ,参数 cs 指判断时大小写是否敏感,后面函数的 cs 都是一个意思,不重复说了。
int count(const QString & str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
count 对字符串对象里子串 str 出现的次数做统计,返回出现次数,如果没出现就返回 0。
int indexOf(const QString & str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
indexOf 从 from 指定的序号开始查询子串 str,返回查到的第一个 str 子串起始位置序号。查不到就返回 -1 。
int lastIndexOf(const QString & str, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
lastIndexOf 默认从字符串尾部开始向前查询,设置 from 之后,从 from 开始的位置向前查询子串 str,返回最先匹配的 str 子串起始位置序号(搜索区间 0 ~ from ,子串起始序号最接近 from)。查不到就返回 -1 。
QString & insert(int position, const QString & str)
insert 是将子串 str 插入到 position 序号位置,子串 str 插入后的起始序号就是 position 。
QString & remove(int position, int n)
remove 从 position 开始的位置移除掉 n 个字符,如果 n 比 position 位置开始的子串长度大,后面的就会被全部移除。
QString & remove(const QString & str, Qt::CaseSensitivity cs = Qt::CaseSensitive)
这个重载的 remove 函数将匹配的所有子串 str 都从字符串里面移除掉,拿来消除空格之类的字符比较好使。
QString & replace(int position, int n, const QString & after)
replace 将从 position 序号开始的 n 个字符的子串替换成 after 字符串。
QString & replace(const QString & before, const QString & after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
这个重载的 replace 将字符串里出现的所有子串 before 全部替换为新的 after。
QStringList split(QChar sep, SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
QStringList split(const QString & sep, SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
split 用字符或子串 sep 切分当前字符串内容,然后将切分的所有子串以 QStringList 列表形式返回,可以从返回的列表提取各个子串。behavior 是分隔模式,是否保留空白字符区域等。
QString section(QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault) const
QString section(const QString & sep, int start, int end = -1, SectionFlags flags = SectionDefault) const
section 函数首先将字符串按照字符或子串 sep 分成段落,类似 split 划分,但 section 只返回第 start 段到第 end 段之间的内容。如果没指定 end 就一直包含到最后。flags 参数影响划分行为,如大小写敏感、是否忽略空白区域等。
QString left(int n) const
left 返回字符串左边 n 个字符构成的子串。
QString right(int n) const
right 返回字符串右边 n 个字符构成的子串。
QString mid(int position, int n = -1) const
mid 返回从 position 位置开始的 n 个字符构成的子串。不设置 n 的话就包含到末尾。
QString & fill(QChar ch, int size = -1)
fill 用字符 ch 填充当前字符串,如果不指定 size ,就把所有的字符都填成 ch 字符。如果指定正数 size,字符串长度被重置为 size 大小,里面依然全是 ch 字符。
QString repeated(int times) const
将当前字符串重复拼接 times 次数,返回新的重复串。
QString trimmed() const
trimmed 剔除字符串头部和尾部的空白字符,包括 '\t', '\n', '\v', '\f', '\r', ' ' 。 字符串中间的空白不处理。
QString simplified() const
simplified 剔除字符串里出现的所有空白字符,包括 '\t', '\n', '\v', '\f', '\r', ' ' 。 两端和中间的都剔除。
void truncate(int position)
文件封装
EXE在其他电脑使用
首先需要添加环境变量:计算机右键属性->高级属性->环境变量(n)->系统变量中的Path->编辑->新建(例:D:\Qt\Qt5.12.0\5.12.0\mingw73_64\bin),就是找bin文件夹
在exe所在文件夹,文件夹下最好只有一个exe文件,Shift右键在此处打开命令窗口输入 windeployqt 可执行程序名 例:windeployqt COM.exe,完成后再把相关文件放回去
强制数据类型转换
const_cast | 去const属性 |
---|---|
static_cast | 静态类型转换,如int转换成char |
dynamic_cast | 动态类型转换,如子类和父类之间的多态类型转换 |
reinterpret_cast | 仅仅重新解释类型,但没有进行二进制的转换 |
//! 该运算符用来修改类型的const或volatile属性(除了const 或volatile修饰之外,type_id和expression的类型是相同的)
const_cast<type_id>(expression)
//! 该运算符把expression转换为type-id类型(没有运行时类型检查来保证转换的安全性)
static_cast<type-id>(expression)
//! 该运算符把expression转换成type-id类型的对象(Type-id 必须是类的指针、类的引用或者void*)
dynamic_cast<type-id>(expression)
//! reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。
reinterpret_cast<type-id>(expression)
显示当前日期时间
实例:
QTimer *timer = new QTimer(this); //用于显示当前日期
timer->start(1000); //每秒更新一次
connect(timer, &QTimer::timeout,[=](){
QDateTime time = QDateTime::currentDateTime();//获取系统现在的时间
QString str = time.toString("hh:mm:ss zzz"); //设置显示格式
qDebug()<<str;
});
Format | Result |
---|---|
dd.MM.yyyy | 21.05.2001 |
ddd MMMM d yy | Tue May 21 01 |
hh:mm:ss.zzz | 14:13:09.042 |
h:m 😒 ap | 2:13:9 pm |
读写Excel
1.pro文件添加
CONFIG += qaxcontainer
2.头文件
#include <ActiveQt/QAxObject>
3.读取文件流程
建立进程并打开文件,获取表格属性
//建立excel进程并获取表格总行列数
QAxObject excel("Excel.Application"); //建立进程
excel.setProperty("Visible",false); //不知道
QAxObject *workbooks = excel.querySubObject("WorkBooks"); //后面操作都在这里面
QString initFile=QDir::currentPath(); //文件当前路径
initFile+="/debug/Table.xlsx";
//initFile+="/Table.xlsx";
workbooks->dynamicCall("Open (const QString&)",initFile); //打开文件
QAxObject *workbook = excel.querySubObject("ActiveWorkBook");//获取活动工作簿
QAxObject *worksheet=workbook->querySubObject("WorkSheets(int)",1);//第一个工作表
QAxObject *used_range = worksheet->querySubObject("UsedRange");
QAxObject *rows = used_range->querySubObject("Rows");
QAxObject *columns = used_range->querySubObject("Columns");
int row_start = used_range->property("Row").toInt(); //获取起始行
int column_start = used_range->property("Column").toInt(); //获取起始列
int row_count = rows->property("Count").toInt(); //获取行数
int column_count = columns->property("Count").toInt(); //获取列数
qDebug()<<"起始行:"<<row_start<<"起始列:"<<column_start<<"行数:"<<row_count<<"列数:"<<column_count;
读取文件
QAxObject *rangeData = worksheet->querySubObject("Cells(int,int)",row,1); //获取cell的值 row,1是坐标
QString DataVal = rangeData->dynamicCall("Value2()").toString(); //转格式
Data[row-1]=DataVal; //取出
关闭文档结束excel线程
//关闭文档结束excel线程
workbooks->dynamicCall("Close(Boolean)",false); //关闭文档
excel.dynamicCall("Quit(void)"); //退出excel线程
//delete excel; //若创建excel时使用指针则需要删除指针 QAxObject *excel = new QAxObject(this);
4.改写文件
建立进程并打开文件,获取表格属性同上
改写文件
QAxObject *cell = worksheet->querySubObject("Cells(int,int)", row, 1);
cell->setProperty("Value", Data[row-1]); //设置单元格值
保存文件
excel.setProperty("DisplayAlerts", false);/*不显示任何警告信息,如果为true,那么关闭时会出现类似“是否保存对某某文件的更改”*/
workbook->dynamicCall("Save()"); //保存活动工作簿文件 这句不能错
//关闭文档结束excel线程
workbooks->dynamicCall("Close(Boolean)",false); //关闭文档
excel.dynamicCall("Quit(void)"); //退出excel线程
5.汇总例程
void MainWindow::writeToFile(QString *Data,QString *name,int len)
{
//建立excel进程并获取表格总行列数
QAxObject excel("Excel.Application");
excel.setProperty("Visible",false);
QAxObject *workbooks = excel.querySubObject("WorkBooks");
QString initFile=QDir::currentPath();
initFile+="/debug/Table.xlsx";
//initFile+="/Table.xlsx";
workbooks->dynamicCall("Open (const QString&)",initFile);
QAxObject *workbook = excel.querySubObject("ActiveWorkBook");//获取活动工作簿
QAxObject *worksheet=workbook->querySubObject("WorkSheets(int)",1);//第一个工作表
int row_count=Data->length();
//将表格内容读取并提取至程序内
for(int row=1;row<row_count+1;row++)
{
QAxObject *cell = worksheet->querySubObject("Cells(int,int)", row, 1);
cell->setProperty("Value", Data[row-1]); //设置单元格值
cell = worksheet->querySubObject("Cells(int,int)", row, 2);
cell->setProperty("Value", name[row-1]); //设置单元格值
qDebug()<<row<<Data[row-1]<<" "<<name[row-1];
}
excel.setProperty("DisplayAlerts", false);/*不显示任何警告信息,如果为true,那么关闭时会出现类似“是否保存对某某文件的更改”*/
workbook->dynamicCall("Save()"); //保存活动工作簿文件
//关闭文档结束excel线程
workbooks->dynamicCall("Close(Boolean)",false); //关闭文档
excel.dynamicCall("Quit(void)"); //退出excel线程
}
void MainWindow::readfromFile(QString *Data,QString *name,int len)
{
//建立excel进程并获取表格总行列数
QAxObject excel("Excel.Application");
excel.setProperty("Visible",false);
QAxObject *workbooks = excel.querySubObject("WorkBooks");
QString initFile=QDir::currentPath();
initFile+="/debug/Table.xlsx";
//initFile+="/Table.xlsx";
workbooks->dynamicCall("Open (const QString&)",initFile);
QAxObject *workbook = excel.querySubObject("ActiveWorkBook");//获取活动工作簿
QAxObject *worksheet=workbook->querySubObject("WorkSheets(int)",1);//第一个工作表
QAxObject *used_range = worksheet->querySubObject("UsedRange");
QAxObject *rows = used_range->querySubObject("Rows");
QAxObject *columns = used_range->querySubObject("Columns");
int row_start = used_range->property("Row").toInt(); //获取起始行
int column_start = used_range->property("Column").toInt(); //获取起始列
int row_count = rows->property("Count").toInt(); //获取行数
int column_count = columns->property("Count").toInt(); //获取列数
qDebug()<<"起始行:"<<row_start<<"起始列:"<<column_start<<"行数:"<<row_count<<"列数:"<<column_count;
//依据表格大小重新定义缓存区数组大小
Data->resize(row_count);
name->resize(row_count);
//将表格内容读取并提取至程序内
for(int row=row_start;row<row_count+1;row++)
{
QAxObject *rangeData = worksheet->querySubObject("Cells(int,int)",row,1); //获取cell的值
QAxObject *rangeName = worksheet->querySubObject("Cells(int,int)",row,2); //获取cell的值
QString DataVal = rangeData->dynamicCall("Value2()").toString();
QString NameVal = rangeName->dynamicCall("Value2()").toString();
Data[row-1]=DataVal;
name[row-1]=NameVal;
qDebug()<<row<<Data[row-1]<<" "<<name[row-1];
delete rangeData;delete rangeName;
}
//关闭文档结束excel线程
workbooks->dynamicCall("Close(Boolean)",false); //关闭文档
excel.dynamicCall("Quit(void)"); //退出excel线程
}
显示曲线 chart
1.基本显示
1.pro文件添加
QT += charts
2.要使用chart的文件的H文件添加
#include <QChartView>
#include <QLineSeries>
#include <QPieSeries>
QT_CHARTS_USE_NAMESPACE
3 ui文件界面添加Widget控件或者Graphics View控件,并提升为QChartView
提升时Widget基类选QWidget,Graphics View基类选GraphicsView。如果在mainwindow构造函数中使用chart,只要mainwindow.h中有步骤二的文件就不用关心提升时的操作,若没有包含文件会导致一直报错。
4.显示
最终实现显示的是
ui->graphicsView->setChart(c);
//ui->graphicsView 是被提升的控件
//setChart 用于显示
//c 是一个QChart的指针 里面放着QLineSeries类型的曲线数据
从定义顺序来看
QLineSeries* line1 = new QLineSeries(); //用于存放图形数据
for(double x=0;x<10;x+=0.1)
{
line1->append(x,sin(x)); //写入数据
}
QChart* c = new QChart(); //显示的图像参数
c->addSeries(line1); //填入图像数据
ui->graphicsView->setChart(c);//显示图像
基本组成
坐标轴-QAbstractAxis:
图表中,一般都有 X、Y 坐标轴,复杂一些的还带有 Z 轴。对应到 Qt 的图表也有 X、Y 轴对象。但是今天,我们先不展开介绍。如果我们不创建轴坐标对应的对象,可以使用 Qt 的默认轴对象。后面我们会介绍用法。
系列-QAbstractSeries:
不论是曲线、饼图、棒图还是其他图表,其中展示的内容本质都是数据。一条曲线是一组数据,一个饼图也对应一组数据。在 Qt Charts 中,这些一组组的数据被称作系列。对应不同类型的图表 Qt 提供了不同的系列。系列除了负责存储、访问数据,应该还提供了数据的绘制方法,比如折线图和曲线图分别对应 QLineSerie 和 QSPLineSerie。我们可以用不同的系列达到不同的展示目的。
图例-Legend:
类似于 Excel,Qt Charts 中也提供了图例,并且还可以显示或者隐藏图例。
图表-QChart:
Qt 提供了 QChart 类来封装前面所说的内容,比如坐标轴、系列、图例等。QChart 承担了一个组织、管理的角色。QChart 派生自 QGraphicsObject,因此它实际上是一个图元 item。我们可以从 QChart 获取到坐标轴对象、数据系列对象、图例等等,并且可以设置图表的主题、背景色等样式信息。
视图-QChartView:
负责 QChart 的展示。QChart 本身只负责图表内容的组织、管理。图表的展示由视图负责,这个视图就是 QChartView。QChartView 派生自 QGraphicsView,只是它专门提供了几个面向 QChart 的接口,比如 setChart(QChart*)等。
XY轴
1.自动显示曲线所有值 (XY)
connect(timer,&QTimer::timeout,[=](){
static int num=0;
num++;
//*line1<<QPointF(num,num/10);
line1->append(num,num/10);
//方案一:有多少数被放进去自己知道
// lineChart->axes(Qt::Horizontal).first()->setRange(0, num);
// lineChart->axes(Qt::Vertical).first()->setRange(0, num/10+1);
//方案二:读取
QList<QAbstractAxis*> listxAxis = lineChart->axes(Qt::Horizontal,line1); //X轴
QList<QAbstractAxis*> listyAxis = lineChart->axes(Qt::Vertical,line1);//Y轴
QValueAxis* xAxis=dynamic_cast<QValueAxis*>(listxAxis[0]);
QValueAxis* yAxis=dynamic_cast<QValueAxis*>(listyAxis[0]);
qDebug()<<xAxis->max()<<xAxis->min()<<yAxis->max()<<yAxis->min()<<listxAxis.size();
xAxis->setMax(num);
yAxis->setMax(num/10+1);
});
m_serieslist[m_SeriesNum]->attachAxis(axisX); //将数值与XY轴连接起来
m_serieslist[m_SeriesNum]->attachAxis(axisY);
方案2的重点在与读取已放入的数据,axes函数,由参数决定读取哪个轴axes(Qt::Horizontal,line1); //X轴,axes(Qt::Vertical,line1);//Y轴 line1是哪条曲线。读取的轴数据默认是QList QAbstractAxis*的,使用时转为QValueAxis或者 QDateTimeAxis。
2.显示指定区域
同上
2.1 X值域不变,Y值域变
2.2 Y值域不变,X值域变
3.实时的修改显示的区间
//用来读取已有XY轴的,还不会用
QList<QAbstractAxis *> XY=lineChart->axes(Qt::Horizontal|Qt::Vertical);
点击图例隐藏曲线
不知道原理 有三个函数 使用时调用connectMarkers即可实现
void connectMarkers(); //连接
void disconnectMarkers(); //断开连接
void handleMarkerClicked(); //连接后执行的函数
都写入Mychart下
void Mychart::connectMarkers()
{
// Connect all markers to handler
const auto markers = m_Chart->legend()->markers();
for (QLegendMarker *marker : markers) {
// Disconnect possible existing connection to avoid multiple connections
QObject::disconnect(marker, &QLegendMarker::clicked,
this, &Mychart::handleMarkerClicked);
QObject::connect(marker, &QLegendMarker::clicked, this, &Mychart::handleMarkerClicked);
}
}
void Mychart::disconnectMarkers()
{
const auto markers = m_Chart->legend()->markers();
for (QLegendMarker *marker : markers) {
QObject::disconnect(marker, &QLegendMarker::clicked,
this, &Mychart::handleMarkerClicked);
}
}
void Mychart::handleMarkerClicked()
{
QLegendMarker* marker = qobject_cast<QLegendMarker*> (sender());
Q_ASSERT(marker);
switch (marker->type())
{
case QLegendMarker::LegendMarkerTypeXY:
{
// Toggle visibility of series
marker->series()->setVisible(!marker->series()->isVisible());
// Turn legend marker back to visible, since hiding series also hides the marker
// and we don't want it to happen now.
marker->setVisible(true);
// Dim the marker, if series is not visible
qreal alpha = 1.0;
if (!marker->series()->isVisible())
alpha = 0.5;
QColor color;
QBrush brush = marker->labelBrush();
color = brush.color();
color.setAlphaF(alpha);
brush.setColor(color);
marker->setLabelBrush(brush);
brush = marker->brush();
color = brush.color();
color.setAlphaF(alpha);
brush.setColor(color);
marker->setBrush(brush);
QPen pen = marker->pen();
color = pen.color();
color.setAlphaF(alpha);
pen.setColor(color);
marker->setPen(pen);
break;
}
default:
{
qDebug() << "Unknown marker type";
break;
}
}
}
小技巧
ui->graphicsView->setRenderHint(QPainter::Antialiasing);//设置视图抗锯齿
lineChart->createDefaultAxes();//根据数据集,自动创建坐标轴,坐标轴的区间恰好完全容纳已有的数据集
axisX->setTickCount(100);//网格
将QT默认控件提升为自定义控件
以Weight控件提升为自定义的父类为QChartView的MychartView为例。
1、Weight的基类还是QWeight,因此提升时的基类选择QWeight。
2、类名称与自己的类保持一致。
3、最重要的一点,需要自己的类提供接口,构造函数。
在UI文件中关于weight控件的代码如下
widget = new MychartView(centralwidget);
widget->setObjectName(QString::fromUtf8("widget"));
centralwidget是一个new QWidget(MainWindow);,因此需要自己的类提供一个接口,形式如下
MychartView(QWidget *parent = 0);
//构造函数
MychartView::MychartView(QWidget *parent) :
QChartView(parent), m_isTouching(false)
{
setRubberBand(QChartView::RectangleRubberBand); //图表要用鼠标区域放大缩小必须要这句
}
保存配置文件
使用配置文件(.ini)
INI文件格式(Initialization File)是某些平台或软件上的配置文件的非正式标准,以节(section)和键(key)构成,被用来对操作系统或特定程序初始化或进行参数设置。常用于微软Windows操作系统,但除了windows现在很多其他操作系统下面的应用软件也有.ini文件。读写INI文件的示例如下:
/*** 写入配置文本 ***/
//QSettings构造函数的第一个参数是ini文件的路径,第二个参数表示针对ini文件,第三个参数可以缺省
CustomPlot::~CustomPlot()
{
QSettings *IniWrite = new QSettings("config_S.ini", QSettings::IniFormat);
//数值输入 IniWrite->setValue("spinBox_485_03IDAddr",ui->spinBox_485_03IDAddr->value());
//单选框 IniWrite->setValue("checkBoxHexDis",ui->checkBoxHexDis->checkState());
//下拉 IniWrite->setValue("comboBox",ui->comboBox->currentIndex());
//文本 IniWrite->setValue("lineEdit_485_10RegData_HEX",ui->lineEdit_485_10RegData_HEX->text());
IniWrite->setValue("spinBox_Check_Frist_Data",ui->spinBox_Check_Frist_Data->value());
delete IniWrite;
delete ui;
}
/*** 读取配置文件***/
void CustomPlot::Get_Conf()
{
QSettings *iniRead = new QSettings("config_S.ini", QSettings::IniFormat);
//数值输入 ui->spinBox_485_03IDAddr->setValue(iniRead->value("spinBox_485_03IDAddr").toInt());
//单选框 ui->checkBoxHexDis->setCheckState(Qt::CheckState(iniRead->value("checkBoxHexDis").toInt()));
//下拉 ui->comboBox_2->setCurrentIndex(iniRead->value("comboBox_2").toInt());
//文本 ui->lineEdit_485_10RegData_HEX->setText(iniRead->value("lineEdit_485_10RegData_HEX").toString());
ui->checkBox_Check_Frist->setCheckState(Qt::CheckState(iniRead->value("checkBox_Check_Frist").toInt()));
delete iniRead;
}
生成的config.ini文件内容如下:
[General]
passwd=123456
lockTime=4
如果调用setValue函数时,已经存在了同名的key,那么新的值会覆盖原来的值。
设置子窗口,及子窗口关闭后自动释放内存
可以新建一个UI文件,之后在MainWindows中包含H文件,创建窗口时注意不要使用static等变量方式创建,要使用new指针创建。
void MainWindow::ToolMenu_CRC_Check_Task()
{
Form *CRC_Check_Window=new Form;
CRC_Check_Window->show();
CRC_Check_Window->setAttribute(Qt::WA_DeleteOnClose);//关闭窗口后立刻释放内存
qDebug()<<"CRC Check";
}
之后运行 ToolMenu_CRC_Check_Task 函数,就会出现新窗口
更改标题
setWindowTitle("CRC校验");
error: no matching member function for call to ‘connect’
包括connect之外的函数也可能会出现这种错误,目前遇到的一种错误,例:
//出错函数
connect(ui->spinBox_HEX,&QSpinBox::valueChanged,[=](){
});
//QSpinBox::valueChanged函数声明
Q_SIGNALS:
void valueChanged(int);
void valueChanged(const QString &);
这样的信号连接格式是没问题的,但是QSpinBox::valueChanged函数有重载,编译器不知道用哪种重载,就会出现这个错误。我们使用的是 void valueChanged(const QString &);格式,因此在connect中使用强制类型转换
//强制类型转换后
connect(ui->spinBox_HEX,static_cast<void (QSpinBox::*)(const QString &)>(&QSpinBox::valueChanged),[=](){
});//static_cast<void (QSpinBox::*)(const QString &)>(&QSpinBox::valueChanged)
父窗口向子窗口传递参数
两边数据类型都为QByteArray为例
主要思想是通过信号和槽函数传递数据
继承关系为父窗口文件要有子窗口的H文件,和父窗口控制创建子窗口一样,也就是说传递参数的前提是父窗口可以传递子窗口,因为connect中需要知道父窗口和子窗口两个的对象。
1、父窗口文件中创建一个带参数的信号
2、子窗口中创建一个和父窗口信号参数相同的槽函数
3、父窗口函数中创建完成子窗口后加入connect函数,将父窗口的信号和子窗口的槽函数。
4、父窗口函数在适当时机发出信号,子窗口即自动运行槽函数。
源码:这里的子窗口是一个继承 QWidget 的对象,和父窗口的MainWindow有一定区别。
子窗口:
/*H文件*/
class Translation_MOD_Data : public QWidget
{
Q_OBJECT
//...
private slots:
void getStr(QByteArray);//2、子窗口中创建一个和父窗口信号参数相同的槽函数
};
/*cpp文件*/
//2、子窗口中创建一个和父窗口信号参数相同的槽函数
void Translation_MOD_Data::getStr(QByteArray str)
{
Word=str;
qDebug()<<Word.length()<<Word;
}
父窗口
/*H文件*/
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
signals:
void RE_Word(QByteArray);//1、父窗口文件中创建一个带参数的信号
}
/*cpp文件*/
#include "translation_mod_data.h"//为了可以创建子窗口需要调用子窗口的H文件
void MainWindow::ToolMenu_Translation_MOD_data_Task()
{
//先创建一个子窗口
Translation_MOD_Data *Translation_MOD_Data_Window =new Translation_MOD_Data;
Translation_MOD_Data_Window->show();
Translation_MOD_Data_Window->setAttribute(Qt::WA_DeleteOnClose);
//3、父窗口函数中创建完成子窗口后加入connect函数,将父窗口的信号和子窗口的槽函数。注意括号数量和参数
connect(this,SIGNAL(RE_Word(QByteArray)),Translation_MOD_Data_Window,SLOT(getStr(QByteArray)));
}
void MainWindow::Send_Signl()
{
QByteArray re_Datas=QByteArray("123456");
//父窗口函数在适当时机发出信号,子窗口即自动运行槽函数。
emit RE_Word(re_Datas);
}
窗口置顶
connect(ui->pushButton_Window_Topping,&QPushButton::clicked,[=](){
static bool Top_EN=false;
if(!Top_EN)
{
Top_EN=true;
ui->pushButton_Window_Topping->setText("取消置顶");
Qt::WindowFlags m_flags = windowFlags();
setWindowFlags(m_flags | Qt::WindowStaysOnTopHint); //窗口置顶
show(); //没有这个会直接隐藏
}else{
Top_EN=false;
ui->pushButton_Window_Topping->setText("窗口置顶");
Qt::WindowFlags m_flags = NULL;
setWindowFlags(m_flags); //窗口不置顶
show();//没有这个会直接隐藏
}
});
/*窗口置顶*/
Qt::WindowFlags m_flags = windowFlags();
setWindowFlags(m_flags | Qt::WindowStaysOnTopHint); //窗口置顶
show(); //没有这个会直接隐藏
/*窗口取消置顶*/
Qt::WindowFlags m_flags = NULL;
setWindowFlags(m_flags); //窗口不置顶
show();//没有这个会直接隐藏
Qt实现模糊搜索
1.UI界面拖入一个combox和lineEdit
2…h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void FuzzySearch(); //添加将两个控件结合起来的函数
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
3…cpp文件
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QCompleter>
#include <QListView>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
FuzzySearch();
}
MainWindow::~MainWindow()
{
delete ui;
}
//将两个控件结合起来的函数
void MainWindow::FuzzySearch()
{
QStringList wordList;
wordList << "alpha" << "omega" << "omicron" << "zeta";
ui->comboBox->addItems(wordList);
ui->comboBox->setView(new QListView());
ui->comboBox->setEditable(true);
ui->comboBox->setLineEdit(ui->lineEdit);
ui->comboBox->setMaxVisibleItems(5);//下拉列表显示item数
QCompleter *pCompleter = new QCompleter(wordList, this);
ui->lineEdit->setCompleter(pCompleter);
pCompleter->setCaseSensitivity(Qt::CaseInsensitive);
ui->comboBox->setCompleter(pCompleter);
ui->lineEdit->clear();
}
可提升的自定义类
可以直接新增现有文件或者重新新建名为Fuzzy_Search的类
1.H文件
#ifndef FUZZY_SEARCH_H
#define FUZZY_SEARCH_H
#include <QComboBox>
#include <QListView>
#include <QLineEdit>
class Fuzzy_Search : public QComboBox
{
public:
explicit Fuzzy_Search(QWidget *parent = nullptr);
~Fuzzy_Search();
//自定义功能
void Link_List();//链接列表进入备选
void Add_List(QStringList AddList);//新增项
void Clear_List();//清除项
void Set_List(QStringList SetList);//清除原有项并新增
private:
QStringList List;
QLineEdit *lineEdit=new QLineEdit;
};
#endif // FUZZY_SEARCH_H
2.Cpp文件
#include "fuzzy_search.h"
#include <QCompleter>
#include <QListView>
#include <QLineEdit>
#include <QComboBox>
Fuzzy_Search::Fuzzy_Search(QWidget *parent):QComboBox (parent)
{
// QStringList wordList;
// wordList << "alpha" << "omega" << "omicron" << "zeta";
// this->addItems(wordList);
this->setView(new QListView());
this->setEditable(true);
this->setLineEdit(lineEdit);
this->setMaxVisibleItems(5);//下拉列表显示item数
// QCompleter *pCompleter = new QCompleter(wordList, this);
// lineEdit->setCompleter(pCompleter);
// pCompleter->setCaseSensitivity(Qt::CaseInsensitive);
// this->setCompleter(pCompleter);
lineEdit->clear();
}
void Fuzzy_Search::Link_List()
{
//链接
QCompleter *pCompleter = new QCompleter(List, this);
lineEdit->setCompleter(pCompleter);
pCompleter->setCaseSensitivity(Qt::CaseInsensitive);
this->setCompleter(pCompleter);
lineEdit->clear();
}
void Fuzzy_Search::Add_List(QStringList AddList)
{
List<<AddList; //新增项加入列表,由于Link_List链接的是List,所以必须将新增项加入List才能出现在备选中
this->addItems(List);
Link_List();
}
void Fuzzy_Search::Clear_List()
{
List.clear();
this->clear();
Link_List();
}
void Fuzzy_Search::Set_List(QStringList SetList)
{
Clear_List();
Add_List(SetList);
}
Fuzzy_Search::~Fuzzy_Search()
{
}
3.UI内拖入QCombox控件,提升为Fuzzy_Search。这时候项是空的,需要新增。
修改窗口图标和应用程序图标
1、窗口图标
放入任意图片,
QString StrPath=QApplication::applicationDirPath();//获取exe文件所在文件夹
StrPath+="/Icon.ico";//加入图片相对于exe文件路径
setWindowIcon(QIcon(StrPath));//可执行程序图标
2、修改应用程序图标
创建一个ico后缀的图片,注意不要用其他格式文件直接改后缀名,有生成工具。
新建一个myapp.rc的资源文件(名称可以自定义),通过文本编辑器,修改资源文件内容为 IDI_ICON1 ICON DISCARDABLE “test.ico”,其中"test.ico"与实际的图片名称一致
拷贝myapp.rc和test.ico到qt的项目中
修改pro文件,增加资源文件
RC_FILE = myapp.rc
执行qmake,然后再次编译!!!!!!执行qmake很重要!!!!
不执行会报错,错误和不标准的.ICO文件一样,缺少.o文件
编译完成之后生成的exe图标就已经变了