Qt学习笔记

什么是类和对象:

1.C++中的类是一种构造类型,与C语言的结构体类似(数据类型),但进行了一些扩展,类的成员不但可以是变量还可以是函数,通过类定义出来的变量也有特定的称呼叫做对象;

2.类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量,创建对象的过程也叫做类的实例化;

类的定义:

class 类名(首写字母是大写)

{

public: //如果不写关键字,默认类成员为public类型

公有的数据;

protected:

保护的数据;

private:

私有的数据;

};

cpp 复制代码
#include <iostream>

using namespace std;

class Dog
{
    public:
        string name;
        int age;
        void run(){
            cout<<"小狗的名字是:"<<name<<","<<"年龄是"<<age<<endl;
        }
};


int main()
{
    Dog dog1;
    //从栈中实例化对象
    dog1.name = "王才";
    dog1.age = 2;
    dog1.run();
    //从堆中实例化对象
    //从堆中实例化的对象必须使用delete关键字删除,否则会造成内存泄漏
    Dog *dog2 = new Dog;    //定义指向Dog类型的指针,使用new关键字在堆中分配空间,在堆内存中创建一个Dog类的对象
    dog2->age = 3;
    cout << dog2->age <<endl;
    //delete dog2;  //需要手动删除

    return 0;
}
/*执行结果

小狗的名字是:王才,年龄是2
3

*/    

构造函数与析构函数:

构造函数:定义了一个名称和类名相同但没有返回值的函数,构造函数在类被实例化的时候调用;

class Dog

{

public:

Dog();//构造函数

};

析构函数:对象实例化的时候,会调用构造函数,对象销毁时,会调用析构函数;

class Dog

{

public:

~Dog();//析构函数

};

在类实例化对象的时候,如果没有定义构造函数,则编译器会合成一个默认的构造函数。当有了对象后,如果没有定义析构函数,则编译器会合成一个默认的析构函数;

cpp 复制代码
#include <iostream>

using namespace std;

class Dog
{
public:
    Dog()       //构造函数定义
    {
        cout << "构造函数被执行" << endl;
    };
    ~Dog();
};

/* 作用域解析运算符 :: 在这里用于明确指出~Dog()这个析构函数属于Dog类,它将析构函数的定义与Dog类关联起来 */
Dog::~Dog()     //析构函数定义,可以在类定义外定义析构函数
{
    cout << "析构函数被执行" << endl;
}


int main()
{
    /* 会先调用构造函数,接着调用析构函数 */
   //Dog dog1;    //在栈中实例化类

    /* 在堆中实例化类,如果没有手动delete对象,则不会调用析构函数,只会调用构造函数 */
   Dog *dog2 = new Dog;     //在堆中实例化类
   delete dog2; //执行了该语句后才会调用析构函数
    return 0;
}
/*执行结果

构造函数被执行
析构函数被执行

*/ 

类的继承:

创建类的时候,并不需要创建全新的数据和成员函数,我们可以指明这个新类继承现有类的成员;

继承类的对象与成员对基类成员的访问权限:

1.共有继承时基类各成员属性保持不变,基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected,而不能访问private成员,派生类的对象只能访问基类中的public成员;

2.保护继承时基类各成员属性均变成protected,基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected,而不能访问private成员,派生类的对象不能访问基类中的任何成员;

3.私有继承时基类各成员属性均变成private,基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected,而不能访问private成员,派生类的对象不能访问基类中的任何成员;

cpp 复制代码
#include <iostream>

using namespace std;

//基类,也叫父类
class Animal
{
public:
    string name;
    int age;
    void run()
    {
        cout << "狗的年龄:" << age << endl;
    }
};

//派生类,也叫子类
class Dog : public Animal   //此时为公有继承,改变关键字public更改继承方式
{

};

int main()
{
    Dog Dog1;
    Dog1.age = 3;
    Dog1.run();
    return 0;
}
 
/*执行结果

狗的年龄:3

*/

函数重载:

在同一作用域内,声明几个功能类似的同名函数,并且这些同名函数的参数个数、参数类型或者参数顺序不同,或者函数返回类型不同,那么就叫函数重载;

cpp 复制代码
#include <iostream>

using namespace std;

class Dog
{
public:
   void getweight(int weight)
   {
      cout << "int类型狗的体重:" << weight << endl;
   }

   void getweight(double weight)
   {
      cout << "double类型狗的体重:" << weight << endl;
   }

};

int main()
{
    Dog Dog1;
    Dog1.getweight(10);
    Dog1.getweight(10.2);
    return 0;
}
/*执行结果

int类型狗的体重:10
double类型狗的体重:10.2

*/

以上是C++基础------------------------------------------------------------------------------------

Qt中的快捷键:

头文件和源文件的切换,F4

对齐代码,ctrl + a ctrl + i

运行项目,ctrl + r

查看类型层次,ctrl + shift + T

Qt信号槽连接模型:

发送者(对象)->信号(函数)->接收者(对象)->槽(函数)

发送者连接一个动作信号作用于接收者然后执行槽函数;

例:UI上面的一个按钮(发送者)执行点击动作,作用于mainwindow(接受者)执行关闭函数(槽);

自定义信号和槽:

1.信号只需要定义不需要声明,但是槽需要定义加声明否则会报错;

2.同一个信号可以连接多个不同的槽;

在构造函数中实例化对象,this的作用:

在这个对象实例化的场景中,this就代表当前对象的内存地址;

cpp 复制代码
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    school = new School(this);  //在构造函数中实例化对象
    student = new Student(this); /*创建Student类的实例(student对象)时,将当前MainWindow对象的地址作为参
                                   数传递给Student类的构造函数。this是当前正在被创建或初始化的MainWindow对象的内存地址。*/
    connect(school, SIGNAL(sendMessages()), student, SLOT(ComeBackToClass()));  //创建信号槽的连接
    emit school->sendMessages();    //发送信号的关键字
}

样式表的使用:

在.ui文件中选中想要修改的目标,右键选择更改样式表,在帮助手册索引style,然后选择sytlesheet(小写),参考手册添加样式表内容;

.qss文件的使用:

是对应.qrc文件下创建的子文件(右键.qrc创建.qss),该文件存放所修改样式的代码,样式的修改代码可以写在源文件中,也可以写在.qss文件中;

需要在mainwindow文件中写下面的代码来找到.qss文件

cpp 复制代码
 QFile file(":/style.qss");

 /* 判断文件是否存在 */
 if (file.exists() ) {
 /* 以只读的方式打开 */
 file.open(QFile::ReadOnly);
 /* 以字符串的方式保存读出的结果 */
 QString styleSheet = QLatin1String(file.readAll());
 /* 设置全局样式 */
 qApp->setStyleSheet(styleSheet);
 /* 关闭文件 */
 file.close();

使用radioButton控件,单选按钮:

同一按钮组中的选择是互斥的,可通过选中按钮划分到不同的按钮组改变互斥的情况;

选中按钮组,取消勾选互斥选项(exclusive),使同一按钮组中可以选中多个按钮;

复选按钮:

在.ui文件中放置CheckBox控件,选中该控件在属性栏勾选三态(tristate)选项即可开启选中(checked)/未选中(unchecked)

/半选中(partiallyChecked)三种状态(不常用);

margin&padding(外边距与内边距):

样式表内容:

cpp 复制代码
QPushButton{
margin:50px;                        //外边框50像素点宽度
background-color:#CDCDB4;           //背景颜色(rgb表中的十六进制数对应的颜色)
border-width:50px;                  //边框宽度
border-color:#458B00                //边框颜色 
border-style:solid;                 //固态填充边框颜色
padding:100px;                      //内边框宽度,即字符到外边框的距离
}

执行结果:

在help中查找stylesheet(注意是小写的)中的Qt Style Sheets Reference,在其中找到控件的属性;

margin&padding(外边距与内边距):

样式表内容:

QPushButton{

margin:50px;

background-color:#CDCDB4;

border-width:50px;

border-color:#458B00

border-style:solid;

padding:100px;

}

水平布局与垂直布局(QHBoxlayout&QVBoxlayout):

在布局属性界面调整layoutSpacing(同一布局下控件的间隔距离)和layoutStretch(同一布局下控件拉伸比例)的数值,在控件属性界面调整sizePolicy(内容可在帮助文档中查看)的数值;

若想要Widget内的控件随Widget的拉伸同步变化,需在Widget的源文件中添加 this->setLatout(ui->horizontalLayout);

分裂器(QSplitter):

在Containers中选择两个Widget控件,放置在一个分裂器中,在分裂器的属性中调整下面的内容,

1.orientation:设置方向,可设置水平方向和垂直方向;

2.opaqueResize:为false(不勾选)时,在拖动的时候会显示一条灰色的线条(可通过在样式表中改变分裂器背景颜色改变线条颜色),在拖动到位并释放鼠标后再显示分割线。默认为true,实时更新子控件大小;

3.childrenCollapsible:为true时,用户可以将子部件的大小调整为;

注意:只调整了.ui 文件的控件布局、属性,未修改任何.cpp/.h 代码,且右键.ui文件执行 "Compile" 无效,需要手动构建(Build)。

由于嵌入式屏幕有限,很少用到这个;

手动构建(小锤子)(Build):

手动构建的核心使用场景:自动构建失效、需要清除缓存、切换构建环境、排查构建错误。自动构建是运行的一部分;

隔离弹簧(QSpacerltem):

在QSpacerltem的属性:

orientation:方向属性,可设置水平或垂直方向;

sizeType:大小属性,如fixed、expanding;

sizeHint:缺省大小,也就是默认大小;

注意:隔离弹簧是放置在布局Latouts控件中的;

QLineEdit(可输入文本的对话框):

可输入文本,例如密码的输入GUI,通过改变ecohModee属性可以将输入的文本隐藏;

创建Dialog项目如何变成圆角矩形:

由于QDialog没有radius的属性,可以在Dialog上面加一个有radius属性的比如Frame,将Dialog改为

//无边框

setWindowFlag(Qt::FramelessWindowHint);

//透明属性

setAttribute(Qt::WA_TranslucentBackground);

将Frame改为圆角矩形,将二者大小改为相同即可。

滚动视觉效果:

scorllArea控件,样式表如何更改参考stylesheet中的Reference中的内容,包括水平滑块、垂直滑块、滑块两端的箭头的样式;

面板切换效果(QTabWidget + ListView):

两个控件通过槽联系ui->tabWidget->setCurrentIndex(currentRow),QTabWidget的Tabposition属性改变标签的位置,ListView的focusPolicy属性是否显示item的上的边框;

QTabWidget stylesheet:

QTabWidget{border:none} //无边框

QTabBar::tab{width:0px;heigh:0px} //隐藏标签

ListView stylesheet:

QListView{background-color:#dddddd;border:none}

QListView::item{height:50px} //点击框的高度

QListView::selected{background-color:white;color:black} //点击框中背景颜色和文字颜色

listWidget控件:

在.ui文件中双击该控件添加item或在源文件中执行下面操作,

ui->listWidget->addItem("张三"); //在widget源文件中添加item,

ui->listWidget->takeItem(0); //移除项

ui->listWidget->insertItem(0,"张三"); //插入项,从所选项的前面插入

对Ui::Dialog *ui;的解释:

Dialog是在创建项目时由用户选择的基类,编译器会生成对应的初始化相应控件代码;

ui是指向Ui::Dialog这个类的指针,在Dialog的构造函数中会进行ui的初始化,即 ui = new Ui::Dialog; 这一步骤通过ui指针,就可以调用Ui::Dialog类的setupUi函数来完成用户界面的设置,以及访问其中与各个控件对应的成员变量,进而实现对用户界面控件的操作。

在调用函数时将当前对象作为参数传递给setupUi函数 ui->setupUi(this);

对于Ui::Dialog这个类,随着对dialog.ui文件进行添加控件操作,Ui::Dialog这个类会增加相应控件的成员变量和相关设置代码:

在Forms文件夹下创建多个类时注意:

ui->setupUi(this);在哪个类的源文件中注释掉这句,在运行后才能单独显示没有注释这句的类的控件;

例如:

创建Widget和QQitem(类名)这两个类,想要在widget的源文件下调用qqitem,首先要在widget的源文件中声明 class QQItem;

创建这个类的指针 QQItem *qqItem = new QQItem(QIcon(":/on.png"), "在线", "张三"); 才是合法的,同时还要包含头文件 #include "qqitem.h",指针保存 QQItem 对象的内存地址,方便后续操作该对象;

执行 QQItem *qqItem = new QQItem(QIcon(":/on.png"), "在线", "张三");

步骤1:new 关键字在堆上为 QQItem 对象分配足够的内存空间(大小由 QQItem 类定义决定)

步骤2:new 关键字调用 QQItem 对应的带参构造函数,将传入的图标、文字等参数赋值给对象的成员变量,完成对象初始化(保留配置成果)

步骤3:new 关键字将堆上 QQItem 对象的内存起始地址作为返回值

步骤4:将该内存地址赋值给指针 qqItem(指针保存地址,方便后续操作对象)

步骤5:构造函数执行完毕,完成使命并"退场",后续无法访问

后续操作:通过 qqItem 保存的地址,找到堆上已初始化完成的 QQItem 对象,使用它的配置成果(如绑定到 QListWidget、修改属性等)

文本读写流程:

1.打开文件->打开文本QFileDialog::getOpenFileName返回的时一个字符串,包括路径+文件名,使用open()方法打开文本;

2.读写文本

readAll(),readLine(),write()

3.关闭文本

close()

对于this->update()的解释:

非常重要

this->update() 通常用于请求重绘当前的 QWidget 或其子类对象所代表的区域。例如在文字轮播的ui设计中,每次文字偏移量的改变都需要调用这句代码对当前区域进行重绘;

.ui文件对控件的提升(promot to):

"提升" 是指将 Qt Designer 中从标准控件库拖放的普通控件,替换为用户自定义的控件类。替换包括名称的替换和控件功能的改变,是一种自定义行为。

比如想在.ui文件中放置QChartView,但是没有这个控件,但是QChartView这个类继承GraphicsView这个类,.ui中有GraphicsView这个控件,就可以放置GraphicsView这个控件然后右键对这个控件提升为QChartView;

Qt中的命名空间:

是一种分组机制,避免不同类成员中存在相同的命名而冲突。

QT_CHARTS_USE_NAMESPACE是一个预处理宏,用于简化在使用Qt Charts模块时对命名空间的引用,就可以直接使用Qt Charts 模块中的类,而无需显式写出QtCharts命名空间前缀;

tcpSocket = new QTcpSocket(this);

在构建对象时向所构建对象的构造函数传入this这个参数,表示当前类对象作为所构建对象的父对象,因为当父对象被销毁时,它会递归销毁所有子对象。这样可以避免内存泄漏,不需要你手动调用 delete tcpSocket。

程序异常:

存在有些指针还在使用但立刻被删除的情况导致程序异常,可以使用deleteLater()方法(Schedules this object for deletion);

TCP通信:

客户端和服务端的socket是用来收发数据的,服务端的server是用来监听是否有客户端需要连接的;

I.MX6U交叉编译Qt项目(使用命令行):

1.在交叉编译前要在虚拟机上执行下面的指令,配置好针对 ARM Cortex-A7 架构的交叉编译环境,让你能直接编译出可在 NXP i.MX 开发板上运行的程序;

source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

2.先在.pro目录下执行 qmake 命令(该命令是Qt专属的Makefile生成器),然后在该目录下执行 make 命令(该命令基于Makefile文件工作);make clean 命令删除 make 命令生成的可执行文件;

3.拷贝文件到开发板,在虚拟机上执行:

scp 文件 用户名@ip地址:路径

拷贝文件夹:

scp -r 文件夹 用户名@ip地址:路径

Qt使用开发板上的按键:

开发板的内核驱动会给开发板上的按键编码(在内核设备树的源码中查看编码),而在Qt平台也对键盘上的按键进行编码,在Qt的编程中去操作与内核驱动相同编码的键盘按键,再烧写到开发板之后就会操作编码相同的开发板上的按键;

在nat网络模式下不同的网络段实现主机与虚拟机的tcp通信:

在虚拟机的Nat设置中添加主机的端口号2222,在Winscp的登录页面主机名填写主机的回环ip127.0.0.1,端口号写2222,利用主机回环 IP + 端口转发,让主机通过 NAT 间接访问虚拟机;

相关推荐
mango_mangojuice2 小时前
Linux学习笔记 1.19
linux·服务器·数据库·笔记·学习
Leekwen2 小时前
生命的选题
学习·思考·生活·认知高度·认知带宽
xhbaitxl2 小时前
算法学习day31-贪心算法
学习·算法·贪心算法
进阶小白猿3 小时前
Java技术八股学习Day29
学习
闫记康3 小时前
linux配置ssh
linux·运维·服务器·学习·ssh
BlackWolfSky3 小时前
鸿蒙中级课程笔记6—使用ArkWeb开发
笔记·华为·harmonyos
浅念-3 小时前
C语言——双向链表
c语言·数据结构·c++·笔记·学习·算法·链表
lxl13074 小时前
学习C++(5)运算符重载+赋值运算符重载
学习
ruxshui4 小时前
个人笔记: 星环Inceptor/hive普通分区表与范围分区表核心技术总结
hive·hadoop·笔记