QT编程入门

常用数据

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别称转入函数转出函数描述
shortqint16arg或setNumtoShort2 字节长度,有符号短整型。
unsigned shortushort、quint16arg或setNumtoUShort2 字节长度,无符号短整型。
intqint32arg或setNumtoInt4 字节长度,有符号整型。
unsigned intuint、quint32arg或setNumtoUInt4 字节长度,无符号整型。
longarg或setNumtoLong有符号长整型,对于 32 位编程 long 是 4 字节长度,对于 64 位编程是 8 字节长度。
unsigned longulongarg或setNumtoULong无符号长整型,对于 32 位编程 unsigned long 是 4 字节长度,对于 64 位编程是 8 字节长度。
long longqlonglong、qint64arg或setNumtoLongLong8 字节长度,有符号长长整型。
unsigned long longqulonglong、quint64arg或setNumtoULongLong8 字节长度,无符号长长整型。
float默认情况下无arg或setNumtoFloat4 字节长度,单精度浮点数。
double默认情况对应 qrealarg或setNumtoDouble8 字节长度,双精度浮点数。

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 自定义控件

  1. 添加一个类 Qt设计师界面类 包含.h .cpp和.ui文件

  2. ui界面设计完成后 提升将基类名称填写正确 注意与.cpp文件内的类名相同,与文件名无关

  3. 封装信号和槽,将自定义控件内的控件之间连接起来,同时在可以将类添加对外接口,实现自定义控件与主界面的数据连接

  4. 主文件

      //设置和读取自定义控件的值
      connect(ui->btn_Set10,&QPushButton::clicked,[=](){
          ui->widget->setData(10);
        });
    connect(ui->btn_Read,&QPushButton::clicked,[=](){
        qDebug()<<ui->widget->getData();
    
            });
    
  5. 自定义控件内部连接

      //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);
    
    
  6. 自定义控件对外接口

    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;
    });
FormatResult
dd.MM.yyyy21.05.2001
ddd MMMM d yyTue May 21 01
hh:mm:ss.zzz14:13:09.042
h:m 😒 ap2: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图标就已经变了

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值