当前位置: 首页 > article >正文

Qt入门笔记

目录

一、前言

二、创建Qt项目

2.1、使用向导创建

2.2、最简单的Qt应用程序

2.2.1、main函数

 2.2.2、widget.h文件

2.2.3、widget.cpp文件

2.3、Qt按键Botton

2.3.1、创建一个Botton

2.3.2、信号与槽

2.3.3、按键使用信号与槽的方法

2.4、文件Read与Write-QFile类

2.4.1、文件操作——Read文件

2.4.2、文件操作——Write文件

2.4.3、QTextStream读写文件

1、QTextStream方式读文件

2、QTextStream方式写文件

2.4.4、光标操作seek

2.5、文件选择对话框 QFileDialog类

 2.5.1、显示单(多)个对话框

 2.5.2、另存(创建)文件

2.5.3、显示单个对话框的另一种方式

2.6、文本text-textEdit类

2.6.1、textEdit的信号

2.6.2、QList

 2.6.3、ExtraSelection(文本字体颜色属性)

2.7、QComboBox选择条框

2.8、消息对话框QMessageBox

2.9、快捷键添加-QShortcut 

2.10、QT事件

2.10.1、利用事件制作自定义按键

2.10.2、自定义按键信号与槽

2.10.3、事件实现控制字体大小


一、前言

这个是用于学习QT入门的一个笔记。使制作一个QT小项目——记事本,所需要掌握的东西。逐渐熟悉每个类的基本用法,暴干2W多字,以后会继续更新!

二、创建Qt项目

2.1、使用向导创建

打开Qt Creator界面选择菜单栏[文件]新建工程

弹出New Project对话框,选择Qt Widgets Application

 点击Choose

 下一步默认即可

选择编译套件向导会默认添加一个继承自QMainWindow的类,可以在此修改类的名字和基类。默认的基类有QMainWindow、QWidget以及QDialog三个,我们可以选择QWidget(类似于空窗口),这里我们可以先创建一个不带UI的界面,继续下一步。后面的默认即可

2.2、最简单的Qt应用程序

2.2.1、main函数

#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();//相当于绘制函数,没有它窗口都看不见return a.exec();//用来启动应用程序的事件循环的。当你调用这个函数时,它会开始处理和分发事件,如用户的点击、键盘输入等
}
  • MainWindow:这是一个包含完整菜单栏、工具栏和状态栏的主窗口应用程序框架。它适合于更复 杂的应用程序,需要这些额外的用户界面元素来提供丰富的功能和交互
  • Widget:这通常是一个简单的窗口,没有内置的菜单栏、工具栏或状态栏。它适合于更简单或专用 的应用程序,不需要复杂的用户界面组件。
  • QApplication a(argc, argv); 这行代码的作用是创建一个 QApplication 类的
    实例。这是几乎每个 Qt 应用程序必须做的第一步,因为它负责管理应用程序的许多核心功能。

 2.2.2、widget.h文件

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget //MainWindow公有继承QMainWindow,QMainWindow继承Q_OBJECT
{Q_OBJECT//一个宏,继承Q_OBJECT或者集成它的子类需要加上public:Widget(QWidget *parent = nullptr);//构造函数~Widget();//析构函数private:Ui::Widget *ui;
};
#endif // WIDGET_H

2.2.3、widget.cpp文件

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)//初始化列表
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}
  • Widget::Widget(QWidget *parent) : QWidget(parent),ui(new Ui::Widget):
    代码 : QWidget(parent) 是初始化列表,用于调用基类 QWidget 的构造函数,并将 parent 传递给 它。 ui(new Ui::Widget) 是初始化类内部的 ui 成员变量,这是通过 new 关键字动态分配的。 Ui::Widget 是由 Qt Designer 工具生成的,用于处理用户界面。这种方式允许将用户界面的设计与后端 逻辑代码分离,有助于提高代码的可维护性和可读性。

2.3、Qt按键Botton

2.3.1、创建一个Botton

在Qt中创建一个按键是非常容易得事,只需要随便拖拖拉拉就可以了

我们可以修改它的按键颜色以及不同状态下(按下、点击......)的属性,比如颜色 

这里修改为黑色做个示例:这个就是修改后的样子

我们还可以修改按键不同状态下的颜色以及他的“外表”,我们就需要用到一点语法:

这里我们就是用照片来美化按键的UI

 先把照片放在一个文件夹里面,然后copy去工程文档里面,然后回到编辑,右键选择添加文件:

然后选择Qt里面的Resource File,一路默认会出现一下界面: 然后依次点击:

然后把照片全部添加进去:

 这里点击添加资源,选择对应要使用的照片即可,配合使用的语法:

QPushButton{border-image: url(:/icon/s1.png);}//默认状态为s1照片

QPushButton:hover{border-image: url(:/icon/s2.png);}//悬停状态为s2照片

QPushButton:pressed{border-image: url(:/icon/s3.png);}//按下状态为s3照片

2.3.2、信号与槽

简单来说信号就是触发槽,槽是一个执行的动作,信号就是触发槽的信号。

  • 信号 (Signals) :是由对象在特定事件发生时发出的消息。例如, QPushButton 有一个
    clicked() 信号,当用户点击按钮时发出。
  • (Slots) :是用来响应信号的方法。一个槽可以是任何函数,当其关联的信号被发出时,该槽函数 将被调用。

简单使用一下信号与槽:我们需要在类Widget中添加一下信号和槽的成员:

class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//类成员信号定义
signals:void mysignal();//无参类型信号void mysignalparams(int value);//有参类型信号//类成员槽定义
private slots:void myslot();//无参类型槽void myslotparams(int value);//有参类型槽private:Ui::Widget *ui;
};

 然后在.cpp文件中定义槽的函数:

//槽函数定义
void Widget::myslot()
{std::cout << "myslot" << std::endl;
}
//槽函数定义
void Widget::myslotparams(int value)
{std::cout << "myslotparams" << std::endl;std::cout << value << std::endl;
}
然后将信号和槽“连接起来(connect)”:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(this,SIGNAL(mysignal()),this,SLOT(myslot()));//将信号和槽联系起来connect(this,SIGNAL(mysignalparams(int)),this,SLOT(myslotparams(int)));//将信号和槽联系起来//代码触发信号emit mysignal();emit mysignalparams(99);
}

运行结果:

2.3.3、按键使用信号与槽的方法

方法一共有4种:

  1. Designer 中点击:
  2. 使用 QObject::connect(是否使用函数指针)
  3. 使用 C++11 Lambda表达式

 第一种:右键点击按键,选择转到槽:

然后就会自动跳转到.cpp文件中:我们定义好槽的函数内容即可

// 第一种方式按键响应函数
void MainWindow::on_pushButton_clicked()
{std::cout << "第一种方法按下响应" << std::endl;
}

第二种:使用 QObject::connect(是否使用函数指针)

我们需要在.h头文件中声明槽,第一种系统会自动帮我们声明

然后我们也是去.cpp文件中定义内容并且使用connect函数“连接” 信号与槽

第四种: 使用C++11 Lambda表达式

优点:不需要在头文件中声明槽函数

//第三方式:lambda表达式:QObject::connect(sender, &Sender::signal, [=]() { /* lambda body */ });QObject::connect(ui->pushButton_3, &QPushButton::clicked,[=](){std::cout << "第三种方法按下响应" << std::endl;});//不需要在h头文件中声明槽——响应函数

运行结果:依次点击按键,依次执行对应的槽函数,依次打印:

2.4、文件Read与Write-QFile类

QFile Qt 框架中用于文件处理的一个类。它提供了读取和写入文件的功能,支持文本和二进制文 件。
QFile 继承自 QIODevice ,因此它可以像其他 IO 设备一样使用。
主要功能
1. 文件读写 QFile 支持打开文件进行读取或写入操作
2. 文件信息 :可以检索有关文件的信息,如大小、修改日期等。
3. 文件操作 :提供了对文件进行重命名、移动、删除等操作的能力。
4. 错误处理 QFile 在操作文件时提供了错误处理机制,可以通过相应的函数检查和获取错误信息
  • open() :打开一个文件。需要指定模式(如只读、只写、读写等)。
  • close() :关闭文件
  • read() write() :用于读取和写入数据。
  • exists() :检查文件是否存在。
  • remove() :删除文件。
  • copy() :复制文件。
open(open_mode);
返回值:失败返回0,成功返回1open_mode:
QIODevice::NotOpen
QIODevice::ReadOnly//只读
QIODevice::WriteOnly//只写
QIODevice::ReadWrite//可读可写
QIODevice::Append
QIODevice::Truncate
QIODevice::Text//文本,\n默认修改为\r\n更好阅读
QIODevice::Unbuffered
QIODevice::NewOnly
QIODevice::ExistingOnly

这里的函数和Linux系统编程的函数大差不差,可以稍微参考一下:Linux系统编程
 

2.4.1、文件操作——Read文件

//点击按键读取函数
void Widget::on_pushButton_clicked()
{//1.打开文件//QFile file("D:/Qt/test.txt");//需要打开的文件的位置QFile file;file.setFileName("D:/Qt/test.txt");if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//打开失败{qDebug() << "open File error";}else{qDebug() << "open File success";}//2.读取文件char buf[100] = {'\0'};qint64 Read_count = 0;Read_count = file.read(buf, 100);if(Read_count != 0)// 读取成功返回读取到的字节数{std::cout << "Read :" << Read_count << std::endl;}else{std::cout << "Read error" << std::endl;}//3.输出文件内容qDebug() << buf;//输出文件内容//4.关闭文件file.close();
}

2.4.2、文件操作——Write文件

//点击按键写入函数
void Widget::on_pushButton_2_clicked()
{//1.打开文件//QFile file("D:/Qt/test.txt");QFile file;file.setFileName("D:/Qt/test.txt");file.open(QIODevice::WriteOnly | QIODevice::Text);//文件不存在会自动创建,文件存在会更换带掉其内容//2.写入文件file.write("Hello BOBEN!");//返回写入的数据的个数//3.关闭文件file.close();
}

Read和Write文件运行结果: 

2.4.3、QTextStream读写文件

QTextStream 的主要特性成一个表格。请看下表:
1、QTextStream方式读文件
//QTextStream方式读取文件槽
void Widget::on_pushButton_clicked()
{QFile file;file.setFileName("D:/Qt/test.txt");//需要打开的文件的存放位置if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//只读文本模式打开失败{qDebug() << "file open error";}QTextStream in(&file);//绑定文件in.setCodec("UTF-8");//设置字符// QString context = in.read(file.size());//一次性全部读取内容while(!in.atEnd())//分行读取  in.atEnd()——确认是否到文件底部,到了返回1,没有到返回0{QString context = in.readLine();//读取一行内容qDebug() << context;//打印一行内容qDebug() << "----";//打印一行内容}file.close();//关闭文件
}
2、QTextStream方式写文件
//QTextStream方式写入文件槽
void Widget::on_pushButton_2_clicked()
{QFile file;file.setFileName("D:/Qt/test.txt");//文件路径,不存在自动创建if(!file.open(QIODevice::WriteOnly | QIODevice::Text))文件不存在会自动创建,文件存在会更换带掉其内容{qDebug() << "file open error";}QTextStream out(&file);out.setCodec("UTF-8");out << "nihao Boben";file.close();
}

    2.4.4、光标操作seek

    这里的光标和我们电脑的光标实质上是一样的,可以理解为光标在哪里,文本就从那里开始操作(读 | 写):

    这里创造两个按键,并且都有自己的信号(点击)与槽,一个按键打开文件后读取函数(一行一行读取),读取完后不关闭文件,注意读取完后光标就处于文本的最后的地方了,如前面所说:可以理解为光标在哪里,文本就从那里开始操作(读 | 写),另一个按键则不需要打开文件了,可以直接读取内容,但是这个时候光标就处于文本的最后的地方,所以按键2根本读取不到内容,运行结果在后面!

    .h文件
    class Widget : public QWidget
    {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();QFile file;//将文本的QFile类作为成员使用private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();private:Ui::Widget *ui;
    };
    #endif // WIDGET_H.c文件
    //QTextStream方式读取文件槽
    void Widget::on_pushButton_clicked()
    {//QFile file;file.setFileName("D:/Qt/test.txt");//需要打开的文件的存放位置if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//只读文本模式打开失败{qDebug() << "file open error";}QTextStream in(&file);//绑定文件in.setCodec("UTF-8");//设置字符// QString context = in.read(file.size());//一次性全部读取内容while(!in.atEnd())//分行读取  in.atEnd()——确认是否到文件底部,到了返回1,没有到返回0{QString context = in.readLine();//读取一行内容qDebug() << context;//打印一行内容qDebug() << "----";//打印一行内容}//file.close();//关闭文件
    }void Widget::on_pushButton_3_clicked()
    {//file.setFileName("D:/Qt/test.txt");//需要打开的文件的存放位置//if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//只读文本模式打开失败//{//    qDebug() << "file open error";//}QTextStream in(&file);//绑定文件in.setCodec("UTF-8");//设置字符// QString context = in.read(file.size());//一次性全部读取内容while(!in.atEnd())//分行读取  in.atEnd()——确认是否到文件底部,到了返回1,没有到返回0{QString context = in.readLine();//读取一行内容qDebug() << context;//打印一行内容qDebug() << "----";//打印一行内容}file.close();//关闭文件
    }

    运行结果: 

    这个时候就需要使用光标移动函数了:

    seek(pace);  pace:光标位置

     所以我们只需要在按键2读取前加上一句代码可以让它可以读取到内容:

    void Widget::on_pushButton_3_clicked()
    {//file.setFileName("D:/Qt/test.txt");//需要打开的文件的存放位置//if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//只读文本模式打开失败//{//    qDebug() << "file open error";//}QTextStream in(&file);//绑定文件in.setCodec("UTF-8");//设置字符// QString context = in.read(file.size());//一次性全部读取内容file.seek(0);while(!in.atEnd())//分行读取  in.atEnd()——确认是否到文件底部,到了返回1,没有到返回0{QString context = in.readLine();//读取一行内容qDebug() << context;//打印一行内容qDebug() << "----";//打印一行内容}file.close();//关闭文件
    }

    运行结果: 

    2.5、文件选择对话框 QFileDialog类

    文件选择对话框就是和我们的电脑点开文件夹出现的窗口一样,类似于:

     2.5.1、显示单(多)个对话框

    qfileDialog.setFileMode(File_mode);

     示例:

    //浏览文件夹槽函数
    void Widget::on_pushButton_clicked()
    {QFileDialog qfileDialog;// 创建一个 QFileDialog 实例qfileDialog.setFileMode(QFileDialog::ExistingFile);// 设置对话框为打开文件模式ExistingFile(s),复数为可以打开多个文件qfileDialog.setNameFilter("*.txt");// 设置文件过滤器//其他使用过滤器:dialog.setNameFilter("Text files (*.txt);;Images (*.png *.jpg);;All files(*)");qfileDialog.exec();// 显示对话框QStringList qstrings = qfileDialog.selectedFiles();//返回选中的文件的位置for(QString str : qstrings)//链表遍历打印{qDebug() << str;//打印选中的文件位置}
    }

    运行结果:

     2.5.2、另存(创建)文件

    //另存文件槽函数
    void Widget::on_pushButton_2_clicked()
    {QString fileName = QFileDialog::getSaveFileName(this,tr("Save File"),"D:/QT/man.txt");QFile file;file.setFileName(fileName);//文件路径,不存在自动创建if(!file.open(QIODevice::WriteOnly | QIODevice::Text))//打开文件{qDebug() << "file open error";}QTextStream out(&file);out.setCodec("UTF-8");out << "666666666";file.close();
    }

    运行结果:就会得到一个新的.txt文件:

    2.5.3、显示单个对话框的另一种方式

    QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"),"D:/QT/",tr("Text(*.txt)"));

    2.6、文本text-textEdit类

    制作一个文本输入框一样很简单,也只需要和按键一样一拖即可实现:

    上面我们打开文件读取文件内容是将内容打印出来,这里我们可以打印出来在文本上:                  那我们就先要学习几个textEdit类里面简单的函数 :

    ui->textEdit->clear();//清除textEdit的内容
    ui->textEdit->setText(context);//在文本上显示出来(替换形式)
    ui->textEdit->append(context);//在文本上显示出来(追加形式)
    context属于QString类型

    然后我们就可以使用这几个函数和前面所学的实现,点击按键,跳出一个文件选择框,选择好文件后,将文件的内容显示在文本框中:

    //打开文件按键的槽函数
    void Widget::on_pushButton_clicked()
    {//返回选中文件的文件路径QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),"D:/Qt/",tr("Text (*.txt)"));QFile file;//定义一个QFile类定义一个文件//ui->textEdit->clear();//清除textEdit的内容file.setFileName(fileName);if(!file.open(QIODevice::ReadOnly | QIODevice::Text))//打开文件{qDebug() << "file open error";//打开文件失败打印信息}QTextStream in(&file);//使用QTextStream读取文件内容in.setCodec("UTF-8");//用UTF-8字符格式读取while(!in.atEnd()){QString context = in.readLine();// qDebug() << qPrintable(context);ui->textEdit->setText(context);//ui->textEdit->append(context);//在文本上显示出来}
    }

    2.6.1、textEdit的信号

    我们到UI界面右击文本,点击跳到槽,可以看看它有什么信号:

    这里使用上面这个箭头的作为演示,实现打印当前第几行第几列的功能: 

    //文本当前位置坐标发生变化信息所触发的槽
    void Widget::on_textEdit_cursorPositionChanged()
    {QTextCursor cursor = ui->textEdit->textCursor();//获取当前新的坐标//qDebug() << cursor.blockNumber()+1 <<","<< cursor.columnNumber() + 1;QString blockNum = QString::number(cursor.blockNumber()+1);//提取坐标中的列坐标QString columnNum = QString::number(cursor.columnNumber()+1);//提取坐标中的行坐标qDebug() << blockNum << columnNum;//打印信息
    }

    2.6.2、QList

    Qt 框架中, QList 是一个容器类,它在内部实现上类似于一个数组,但也提供了一些链表的特性。
    QList 的设计旨在提供一个在多数情况下既高效又方便的通用列表容器。用于存储元素列表。它提供了 丰富的功能,包括添加、移除、访问元素等。
    QList 的内部工作原理:
    1. 数组式存储 QList 在大多数情况下使用连续内存存储其元素,类似于数组。这意味着它提供了快 速的索引访问(通过下标操作符 [] ),以及相对高效的迭代性能。
    2. 动态调整大小:与静态数组不同, QList 可以动态增长和缩减,自动管理内存分配。
    3. 链表特性:虽然 QList 主要基于数组,但它也提供了一些链表的操作,比如在列表的开始或结束 处添加和移除元素。这些操作通常比在数组中间插入或删除元素更高效。
    4. 复制时共享内存 QList 使用一种称为 隐式共享 implicit sharing )或 写时复制 copy-onwrite)的技术。这意味着当你复制一个 QList 时,它不会立即复制所有元素,而是共享相同的数 据,直到你尝试修改其中一个列表,此时才进行实际的复制。这使得复制 QList 变得非常高效。

    基本用法:

    包含头文件:首先,你需要包含 QList 的头文件。

    #include <QList>

    创建 QList 实例:创建一个 QList 对象,并指定存储的元素类型。

    QList<int> list;

    添加元素:使用 append push_back 方法添加元素。

    list.append(1);
    list.append(2);
    list.append(3);

     访问元素:可以使用下标操作符或 at() 方法访问元素。

    int firstElement = list[0];
    int secondElement = list.at(1);

     遍历列表:使用迭代器或范围基的 for 循环遍历列表。

    for(int i = 0; i < list.size(); ++i) 
    { // size = sizeof(arr)/sizeof(arr[0])qDebug() << list[i];
    }
    // 或者使用范围基的 for 循环
    for(int item : list)
    {qDebug() << item;
    }

     移除元素:使用 removeAt removeOne clear 方法移除元素。

    list.removeAt(1); // 移除索引为 1 的元素
    list.removeOne(3); // 移除一个值为 3 的元素
    list.clear(); // 清空整个列表

     2.6.3、ExtraSelection(文本字体颜色属性)

    QTextEdit::ExtraSelection 是一个在 QTextEdit 中用来表示额外的文本选择和高亮的结构。

    如何工作: 

    • ExtraSelection 结构体 QTextEdit::ExtraSelection 是一个结构体,包含了两个主要成员:
      QTextCursor QTextCharFormat QTextCursor 表示在文本中的一个位置或者区间,而
      QTextCharFormat 用于定义这个区间的格式,比如背景颜色、字体等。
    • 设置 ExtraSelection :你可以创建一个或多个 ExtraSelection 对象,为它们设置相应的光标位 置和格式,然后通过 QTextEdit setExtraSelections 方法将这些对象应用到文本编辑器中。 这样,你可以对文本的特定部分应用特定的格式,而不影响其他文本。
    • 高亮当前行 :要高亮显示当前行,你需要在 cursorPositionChanged() 信号的槽函数中创建一个 ExtraSelection 对象。使用当前的 QTextCursor 对象(通过 textCursor() 方法获取)来确
      定当前行的位置,并设置背景颜色为你选择的高亮颜色。

     这里先使得文本当前行高光作为例子:

    //文本当前位置坐标发生变化信息所触发的槽
    void Widget::on_textEdit_cursorPositionChanged()
    {QTextCursor cursor = ui->textEdit->textCursor();//获取当前新的坐标//qDebug() << cursor.blockNumber()+1 <<","<< cursor.columnNumber() + 1;QString blockNum = QString::number(cursor.blockNumber()+1);//提取坐标中的列坐标QString columnNum = QString::number(cursor.columnNumber()+1);//提取坐标中的行坐标qDebug() << blockNum << columnNum;//打印信息//设置当前高亮QList<QTextEdit::ExtraSelection>  extraSelection;//制作一个QTextEdit::ExtraSelection类型的容器QTextEdit::ExtraSelection ext;//声明一个结构体//1、知道当前行ext.cursor = ui->textEdit->textCursor();QBrush qBrush(Qt::yellow);//2、调制颜色ext.format.setBackground(qBrush);ext.format.setProperty(QTextFormat::FullWidthSelection, true);//3、设置extraSelection.append(ext);//将结构体假如到容器里面去ui->textEdit->setExtraSelections(extraSelection);//设置}

    不仅有背景颜色的更改,还有更多其他的属性可以更改:

    这里使用改变字体大小来作为一个示例:

    //快捷键槽函数
    void Widget::test()
    {qDebug() << "test";//获取当前字体的信息QFont font = ui->textEdit->font();//获取字体大小int fontsize = font.pointSize();if(fontsize == -1)  return;//改变字体大小int newsize = fontsize +1;font.setPointSize(newsize);//设置字体大小ui->textEdit->setFont(font);
    }

    运行结果,触发槽后字体逐渐变大:

     

    2.7、QComboBox选择条框

    QComboBox Qt 框架中用于创建下拉列表的一个控件。
    它允许用户从一组选项中选择一个选项,并可以配置为可编辑,使用户能够在其中输入文本。
    QComboBox 提供了一系列方法来添加、删除和修改列表中的项,支持通过索引或文本检索项,并可以通过信号和槽机制来响应用户的选择变化。该 控件广泛应用于需要从多个选项中进行选择的用户界面场景,例如表单和设置界面。
    那么一个选择条框是什么样的呢?
    当然,它的生成一样相当简单,也是一拖即可:
    这个和按键一样,一样适用于和信号与槽配合使用,不同的是按键是按下的状态改变作为信号,这个是选择框选择的东西作为信号。我们搜索手册可以看看他的信号种类:

    接下来还是老样子,连接信号与槽,声明和定义槽:

    .c文件
    Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
    {ui->setupUi(this);//这里使用选中框变化的信号currentIndexChanged(int index) index选中内容的索引(从0开始)connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(oncurrentIndexChanged(int)));//连接信号与槽
    }Widget::~Widget()
    {delete ui;
    }//槽函数执行动作
    void Widget::oncurrentIndexChanged(int index)
    {qDebug() << index;qDebug() << ui->comboBox->currentText();//这里需要展现的内容都可以去手册查,看看自己需要什么,这里是打印选中的文本//ui->comboBox->currentText();这里返回的是Qstring类型//想要转换成const char*类型需要ui->comboBox->currentText().toStdString().c_str;
    }.h文件
    class Widget : public QWidget
    {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void oncurrentIndexChanged(int index);//声明槽函数private:Ui::Widget *ui;
    };
    #endif // WIDGET_H

     运行结果:

    2.8、消息对话框QMessageBox

    QMessageBox Qt 框架中用于显示消息框的一个类,它常用于向用户显示信息、询问问题或者报告错 误。以下是 QMessageBox 的一些主要用途:
    • 显示信息 :向用户显示一些信息性的消息。
    • 询问用户决策 :询问用户一个问题,并根据其回答做出相应的操作。
    • 报告错误 :向用户报告程序运行中的错误。

    消息对话框到底是啥样的呢? 

     那我们怎么才能创建生成一个对话框呢?我们可以打开手册查看这个类的成员用法:

     这里还是使用一个按键来触发制作一个对话框:

    //弹出对话框的按键的槽
    void Widget::on_pushButton_clicked()
    {int ret = QMessageBox::warning(this, tr("My Application"),//对话框标题tr("The document has been modified.\n""Do you want to save your changes?"),QMessageBox::Save | QMessageBox::Discard| QMessageBox::Cancel);//按键的名字switch (ret) //哪个按键按下了{case QMessageBox::Save:// Save was clickedqDebug() << "Save";break;case QMessageBox::Discard:// Don't Save was clickedqDebug() << "Discard";break;case QMessageBox::Cancel:// Cancel was clickedqDebug() << "Cancel";break;default:// should never be reachedbreak;}
    }

    运行结果:

    2.9、快捷键添加-QShortcut 

    Qt 中实现快捷键功能通常涉及到 QShortcut 类的使用。下面是一个简单的代码示例,展示了如何在 Qt 应用程序中为特定功能设置快捷键:
    这里使一个使用 Lambda表达式 的一个实例:
    // 创建一个快捷键 (Ctrl + N) 并关联到窗口
    QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+N"), &window);
    // 当快捷键被按下时,显示一个消息框
    QObject::connect(shortcut, &QShortcut::activated, [&]() 
    {QMessageBox::information(&window, "Shortcut Activated", "Ctrl+N waspressed");
    });

    我们可以看看QKeySequence函数里面的成员可以是什么,手册里面实在太多了,我们只看一部分好了:发现快捷键还可以操作文件,下面我们来写一个例子:

    这里我们也写一个简单的例子,快捷键触发槽函数打印信息:

    .c文件
    Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
    {ui->setupUi(this);QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+N"), this);//创建一个快捷键connect(shortcut,SIGNAL(activated()),this,SLOT(test()));//绑定信号与槽
    }Widget::~Widget()
    {delete ui;
    }//快捷键槽函数
    void Widget::test()
    {qDebug() << "test";
    }.h文件
    class Widget : public QWidget
    {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void test();//槽函数声明private:Ui::Widget *ui;
    };
    #endif // WIDGET_H

    运行结果:

    对于要对文件进行操作的话,我们需要在参数方面进行修改: 

    QShortcut *shortcut = new QShortcut(QKeySequence(tr("Ctrl+S",“File|Open”)), this);//创建一个快捷键然后还是进行绑定信号与槽,后面在槽函数内对文件进行操作即可

    2.10、QT事件

    事件处理过程:
    众所周知 Qt 是一个基于 C++ 的框架,主要用来开发带窗口的应用程序(不带窗口的也行,但不是主流)。 我们使用的基于窗口的应用程序都是基于事件,其目的主要是用来实现回调(因为只有这样程序的效率 才是最高的)。所以在Qt 框架内部为我们提供了一些列的事件处理机制,当窗口事件产生之后,事件会 经过: 事件派发 -> 事件过滤->事件分发->事件处理 几个阶段。 Qt窗口中对于产生的一系列事件都有默认 的处理动作,如果我们有特殊需求就需要在合适的阶段重写事件的处理动作 比如信号与槽就是一种
    事件( event )是由系统或者 Qt 本身在不同的场景下发出的。当用户按下 / 移动鼠标、敲下键盘,或者是 窗口关闭/ 大小发生变化 / 隐藏或显示都会发出一个相应的事件。一些事件在对用户操作做出响应时发出, 如鼠标/ 键盘事件等;另一些事件则是由系统自动发出,如计时器事件。
    每一个 Qt 应用程序都对应一个唯一的 QApplication 应用程序对象,然后调用这个对象的 exec()
    数,这样 Qt 框架内部的事件检测就开始了( 程序将进入事件循环来监听应用程序的事件 )。
    int main(int argc, char *argv[])
    {QApplication a(argc, argv);MainWindow* w = new MainWindow;w.show();return a.exec();
    }

     事件在Qt中产生之后,的分发过程是这样的:

    1. 当事件产生之后,Qt使用用应用程序对象调用 notify() 函数将事件发送到指定的窗口:
      [override virtual] bool QApplication::notify(QObject *receiver, QEvent *e);
    2. 事件在发送过程中可以通过事件过滤器进行过滤,默认不对任何产生的事件进行过滤。
      // 需要先给窗口安装过滤器, 该事件才会触发
      [virtual] bool QObject::eventFilter(QObject *watched, QEvent *event)
    3. 当事件发送到指定窗口之后,窗口的事件分发器会对收到的事件进行分类 :
      [override virtual protected] bool QWidget::event(QEvent *event);
    4. 事件分发器会将分类之后的事件(鼠标事件、键盘事件、绘图事件。。。)分发给对应的事件处理 器函数进行处理,每个事件处理器函数都有默认的处理动作(我们也可以重写这些事件处理器函 数),比如:鼠标事件:
      // 鼠标按下
      [virtual protected] void QWidget::mousePressEvent(QMouseEvent *event);
      // 鼠标释放
      [virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event);
      // 鼠标移动
      [virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event);

      我们可以去看看支持重写的事件有多少,我们可以去手册查看QWidget类的Protected Functions:(这里没有完全展现出来)

    这里我们挑几个出来重写一下test一下:

    .h文件class Widget : public QWidget
    {Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();public://声明事件处理函数void enterEvent(QEvent *event) override;//进入运行框函数重写void leaveEvent(QEvent *event) override;//离开运行框函数重写void wheelEvent(QWheelEvent *event) override;//进入运行框滚动滑轮函数重写void closeEvent(QCloseEvent *event) override;//关闭运行框函数重写void resizeEvent(QResizeEvent *event) override;//放大缩小运行框函数重写private:Ui::Widget *ui;
    };.c文件//进入运行框处理函数
    void Widget::enterEvent(QEvent *event)
    {qDebug() << "mouse enter";
    }
    //离开运行框处理函数
    void Widget::leaveEvent(QEvent *event)
    {qDebug() << "mouse leave";
    }
    //进入运行框滚轮滑动处理函数
    void Widget::wheelEvent(QWheelEvent *event)
    {qDebug() << event->angleDelta();}
    //关闭运行框处理函数
    void Widget::closeEvent(QCloseEvent *event)
    {int ret = QMessageBox::warning(this, tr("My Application"),tr("close the window\n""Do you want to close the window?"),QMessageBox::Ok | QMessageBox::No);switch(ret){case QMessageBox::Ok:event->accept();break;case QMessageBox::No:event->ignore();break;}}
    //放大缩小运行框处理函数
    void Widget::resizeEvent(QResizeEvent *event)
    {qDebug() << "oldSize:" << event->oldSize()<< "newSize:" << event->size();
    }
    

     运行结果:

    2.10.1、利用事件制作自定义按键

    我们在文件中新建一个类:我这里起名为Mybotton继承于Widget(注意第一个字母要大写) 

    .h文件#ifndef MYBOTTON_H
    #define MYBOTTON_H#include <QWidget>class Mybotton : public QWidget
    {Q_OBJECT
    public:explicit Mybotton(QWidget *parent = nullptr);protected:void leaveEvent(QEvent *event) override;//离开widget窗口void enterEvent(QEvent *event) override;//进入widget窗口signals:};#endif // MYBOTTON_H.c文件#include "mybotton.h"#include <QDebug>Mybotton::Mybotton(QWidget *parent) : QWidget(parent)
    {}void Mybotton::leaveEvent(QEvent *event)
    {qDebug() << "lll";
    }void Mybotton::enterEvent(QEvent *event)
    {qDebug() << "kkk";
    }

    然后因为我们是继承于Widget类,所以我们生成一个Widget:

    然后右键点击矩形,点击提升为我们刚才创建的类: 运行结果:

    2.10.2、自定义按键信号与槽

    这里可以回忆一下前面自定义信号与槽的使用:

    mybotton.hclass Mybotton : public QWidget
    {Q_OBJECT
    public:explicit Mybotton(QWidget *parent = nullptr);protected:void leaveEvent(QEvent *event) override;//离开widget窗口void enterEvent(QEvent *event) override;//进入widget窗口signals:void clicked();//声明信号};widget.cpp:Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
    {ui->setupUi(this);connect(ui->mybtn,&Mybotton::leaved,[=](){qDebug() << "myButton is leaved !";});connect(ui->mybtn,&Mybotton::entered,[=](){qDebug() << "myButton is entered !";});
    }mybotton.cpp:void Mybotton::leaveEvent(QEvent *event)
    {qDebug() << "lll";emit leaved();//触发信号
    }void Mybotton::enterEvent(QEvent *event)
    {qDebug() << "kkk";emit entered();
    }
    

     运行结果:

    2.10.3、事件实现控制字体大小

     首先我们要实现Ctrl+鼠标控制字体大小,我们需要重写鼠标滑动事件和键盘输入事件执行动作,两者合起来就可以实现了!

    我们新建一个类,基于QTextEdit类

    新建一个文本并且提升为MyTextEdit: 代码:

    mytextedit.h#ifndef MYTEXTEDIT_H
    #define MYTEXTEDIT_H#include <QTextEdit>class MyTextEdit : public QTextEdit
    {
    public:MyTextEdit(QWidget *parent);//需要添加代码的地方protected:void wheelEvent(QWheelEvent *e) override;void keyPressEvent(QKeyEvent *e) override;void keyReleaseEvent(QKeyEvent *e) override;private:bool ctrlKeyPressed = 0;//Ctrl是否被按下标志位};#endif // MYTEXTEDIT_Hmytextedit.c#include "mytextedit.h"#include <QWheelEvent>
    #include <QDebug>MyTextEdit::MyTextEdit(QWidget *parent) : QTextEdit(parent)
    {}void MyTextEdit::wheelEvent(QWheelEvent *e)
    {qDebug() << "wheelEvent";if(ctrlKeyPressed == 1){if(e->angleDelta().y() > 0){//放大字体qDebug() << "fangda";}else if(e->angleDelta().y() < 0){//缩小字体qDebug() << "suoxiao";}e->accept();//事件处理完成}else{QTextEdit::wheelEvent(e);//没有按下Ctrl默认怎么处理就怎么处理}
    }void MyTextEdit::keyPressEvent(QKeyEvent *e)
    {qDebug() << "keyPressEvent";if(e->key() == Qt::Key_Control){// qDebug() << "ctrl Pressed";ctrlKeyPressed = 1;}QTextEdit::keyPressEvent(e);
    }void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
    {qDebug() << "keyReleaseEvent";if(e->key() == Qt::Key_Control){// qDebug() << "ctrl Release";ctrlKeyPressed = 0;}QTextEdit::keyPressEvent(e);
    }
    

     运行结果:

    相关文章:

    Qt入门笔记

    目录 一、前言 二、创建Qt项目 2.1、使用向导创建 2.2、最简单的Qt应用程序 2.2.1、main函数 2.2.2、widget.h文件 2.2.3、widget.cpp文件 2.3、Qt按键Botton 2.3.1、创建一个Botton 2.3.2、信号与槽 2.3.3、按键使用信号与槽的方法 2.4、文件Read与Write-QFile类 2…...

    C语言每日一练——day_4

    引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第四天。&#xff08;连续更新中&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff09;是一种在编程竞赛中用…...

    下降路径最⼩和(medium)

    题目描述&#xff1a; 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列&#xff08…...

    redux_旧版本

    reduxjs/toolkit&#xff08;RTK&#xff09;是 Redux 官方团队推出的一个工具集&#xff0c;旨在简化 Redux 的使用和配置。它于 2019 年 10 月 正式发布&#xff0c;此文章记录一下redux的旧版本如何使用&#xff0c;以及引入等等。 文件目录如下&#xff1a; 步骤 安装依…...

    ⭐算法OJ⭐经典题目分类索引(持续更新)

    在编程竞赛和算法学习中&#xff0c;Online Judge&#xff08;OJ&#xff09;平台是程序员们磨练技能的重要工具。OJ平台上的题目种类繁多&#xff0c;涵盖了从基础数据结构到复杂算法的各个方面。为了更好地理解和掌握这些题目&#xff0c;对其进行分类是非常有必要的。这篇索…...

    python之使用scapy扫描本机局域网主机,输出IP/MAC表

    安装scapy库 pip install scapy -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple扫描本机局域网的所有主机&#xff0c;输出IP/MAC对于表 # -*- coding: UTF-8 -*- import netifaces from scapy.all import srp from scapy.layers.l2 import ARP, Ether import ipa…...

    Spring Boot中@Valid 与 @Validated 注解的详解

    Spring Boot中Valid 与 Validated 注解的详解 引言 在Spring Boot应用中&#xff0c;参数校验是确保数据完整性和一致性的重要手段。Valid和Validated注解是Spring Boot中用于参数校验的两个核心注解。本文将详细介绍这两个注解的用法、区别以及代码样例。 Valid注解 功能介…...

    18、TCP连接三次握手的过程,为什么是三次,可以是两次或者更多吗【高频】

    三次握手的过程&#xff1a; 第一次握手&#xff1a;客户端 向 服务器 发送一个 SYN&#xff08;也就是同步序列编号报文&#xff09;&#xff0c;请求建立连接。随后&#xff0c;客户端 进入 SYN_SENT 状态&#xff1b;服务器收到 SYN 之后&#xff0c;由 LISTEN 状态变为 SYN…...

    Ceph(2):Ceph简介

    1 Ceph简介 Ceph使用C语言开发&#xff0c;遵循LGPL协议开源。Sage Weil(Ceph论文发表者)于2011年创立了以Inktank公司主导Ceph的开发和社区维护。2014年Redhat收购inktank公司&#xff0c;并发布Inktank Ceph企业版&#xff08;ICE&#xff09;软件&#xff0c;业务场景聚焦云…...

    第二篇:CTF常见题型解析:密码学、逆向工程、漏洞利用、Web安全

    # 零基础小白入门CTF解题到成为CTF大佬系列文章 ## 第二篇&#xff1a;CTF常见题型解析&#xff1a;密码学、逆向工程、漏洞利用、Web安全 ### 引言 在CTF比赛中&#xff0c;题目类型多种多样&#xff0c;涵盖了网络安全领域的多个方向。掌握这些题型的解题方法&#xff0c;…...

    《Python基础教程》附录B笔记:Python参考手册

    《Python基础教程》第1章笔记&#x1f449;https://blog.csdn.net/holeer/article/details/143052930 附录B Python参考手册 Python标准文档是完整的参考手册。本附录只是一个便利的速查表&#xff0c;当你开始使用Python进行编程后&#xff0c;它可帮助你唤醒记忆。 B.1 表…...

    linux学习(十三)(shell编程(文字,变量,循环,条件,调试))

    Shell 编程 Shell 编程&#xff0c;也称为 shell 脚本&#xff0c;是 Linux作系统不可或缺的一部分。shell 脚本实质上是系统 shell 执行的程序。虽然它可能不如 C 或 C 等编译语言强大&#xff0c;但 shell 编程对于管理级任务、自动执行重复性任务和系统监控非常有效。 大多…...

    大模型微调中warmup(学习率预热)是什么

    大模型微调中warmup(学习率预热)是什么 在大模型微调中,添加warmup(学习率预热)是指在训练初期逐步增加学习率,避免直接使用高学习率导致参数震荡。 🔧 为什么需要warmup? 大模型参数敏感:预训练模型的参数已接近最优,初期用大学习率可能剧烈扰动参数(如“急刹车…...

    wireshark 如何关闭混杂模式 wireshark操作

    Fiddler和Wireshark都是进行抓包的工具&#xff1a;所谓抓包就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作&#xff0c;也用来检查网络安全。抓包也经常被用来进行数据截取等。黑客常常会用抓包软件获取你非加密的上网数据&#xff0c;然后通过分析&#…...

    ChatGPT4.5详细介绍和API调用详细教程

    OpenAI在2月27日发布GPT-4.5的研究预览版——这是迄今为止OpenAI最强大、最出色的聊天模型。GPT-4.5在扩大预训练和微调规模方面迈出了重要的一步。通过扩大无监督学习的规模&#xff0c;GPT-4.5提升了识别内容中的模式、建立内容关联和生成对于内容的见解的能力&#xff0c;但…...

    centos linux安装mysql8 重置密码 远程连接

    1. 下载并安装 MySQL Yum 仓库 从 MySQL 官方网站下载并安装 Yum 仓库配置文件。 # 下载MySQL 8.0的Yum仓库包 wget https://dev.mysql.com/get/mysql80-community-release-el7-5.noarch.rpm # 安装Yum仓库包 sudo rpm -ivh mysql80-community-release-el7-5.noarch.rpm2. 启…...

    AWS 如何导入内部SSL 证书

    SSL 证书的很重要的功能就是 HTTP- > HTTPS, 下面就说明一下怎么导入ssl 证书,然后绑定证书到ALB. 以下示例说明如何使用 AWS Management Console 导入证书。 从以下位置打开 ACM 控制台:https://console.aws.amazon.com/acm/home。如果您是首次使用 ACM,请查找 AWS Cer…...

    Unity DOTS从入门到精通之 自定义Authoring类

    文章目录 前言安装 DOTS 包什么是Authoring1. 实体组件2. Authoring类 前言 DOTS&#xff08;面向数据的技术堆栈&#xff09;是一套由 Unity 提供支持的技术&#xff0c;用于提供高性能游戏开发解决方案&#xff0c;特别适合需要处理大量数据的游戏&#xff0c;例如大型开放世…...

    一键换肤的Qt-Advanced-Stylesheets

    项目简介 能在软件运行时对 CSS 样式表主题&#xff08;包括 SVG 资源和 SVG 图标&#xff09;进行实时颜色切换的Qt项目。 项目预览&#xff1a; 项目地址 地址&#xff1a;Qt-Advanced-Stylesheets 本地编译环境 Win11 家庭中文版 Qt5.15.2 (MSVC2019) Qt Creator1…...

    golang 静态库 Undefined symbol: __mingw_vfprintf

    正常用golang编译一个静态库给 其他语言 调用&#xff0c;编译时报错 Error: Undefined symbol: __mingw_vfprintf 很是奇怪&#xff0c;之前用用golang写静态库成功过&#xff0c;编译也没问题&#xff0c;结果却是截然不同。 试了很多次&#xff0c;发现唯一的差别就是在 …...

    宝塔的ssl文件验证域名后,会在域名解析列表中留下记录吗?

    在使用宝塔面板进行SSL证书验证域名后&#xff0c;通常不会在域名解析列表中留下记录。验证过程中添加的TXT记录仅用于验证域名的所有权&#xff0c;一旦验证完成&#xff0c;就可以安全地删除这些记录&#xff0c;不会影响SSL证书的正常使用。根据搜索结果&#xff0c;DNS验证…...

    Linux 网络:skb 数据管理

    文章目录 1. 前言2. skb 数据管理2.1 初始化2.2 数据的插入2.2.1 在头部插入数据2.2.2 在尾部插入数据 2.2 数据的移除 3. 小结 1. 前言 限于作者能力水平&#xff0c;本文可能存在谬误&#xff0c;因此而给读者带来的损失&#xff0c;作者不做任何承诺。 2. skb 数据管理 数…...

    wireguard搭配udp2raw部署内网

    前言 上一篇写了使用 wireguard 可以非常轻松的进行组网部署&#xff0c;但是如果服务器厂商屏蔽了 udp 端口&#xff0c;那就没法了 针对 udp 被服务器厂商屏蔽的情况&#xff0c;需要使用一款 udp2raw 或 socat 类似的工具&#xff0c;来将 udp 打包成 tcp 进行通信 这里以…...

    Qwen/QwQ-32B 基础模型上构建agent实现ppt自动生成

    关心Qwen/QwQ-32B 性能测试结果可以参考下 https://zhuanlan.zhihu.com/p/28600079208https://zhuanlan.zhihu.com/p/28600079208 官方宣传上是该模型性能比肩满血版 DeepSeek-R1&#xff08;671B&#xff09;&#xff01; 我们实现一个 使用Qwen/QwQ-32B 自动生成 PowerPoi…...

    【Linux】使用问题汇总

    #1 ssh连接的时候报Key exchange failed 原因&#xff1a;服务端版本高&#xff0c;抛弃了一些不安全的交换密钥算法&#xff0c;且客户端版本比较旧&#xff0c;不支持安全性较高的密钥交换算法。 解决方案&#xff1a; 如果是内网应用&#xff0c;安全要求不这么高&#xf…...

    PostgreSQL17(最新版)安装部署

    PostgreSQL 17已与2024年9月26日正式发布&#xff01;&#xff01;&#xff01; 一、Postgres概述 官网地址&#xff1a;PostgreSQL: The world’s most advanced open source database Postgres作为最先进的开源数据库&#xff08; the latest version of the world’s most…...

    【AI大模型智能应用】Deepseek生成测试用例

    在软件开发过程中&#xff0c;测试用例的设计和编写是确保软件质量的关键。 然而&#xff0c;软件系统的复杂性不断增加&#xff0c;手动编写测试用例的工作量变得异常庞大&#xff0c;且容易出错。 DeepSeek基于人工智能和机器学习&#xff0c;它能够依据软件的需求和设计文…...

    【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台

    【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台 文章目录 准备工作连接设备RTMP概念ENCSHV2推流地址设置大疆Pocket 3直播设置总结 老铁们好&#xff01; 很久没写软文了&#xff0c;今天给大家带了一个干货&#xff0c;如上图&#xff0c;大疆Pocket 3加ENC编…...

    机器人交互系统 部署构建

    环境要求 Ubuntu 20.04 或更高版本ROS Noetic 或兼容版本Python 3.8 安装步骤 1. 安装ROS环境&#xff08;如未安装&#xff09; sudo apt update sudo apt install ros-noetic-desktop-full source /opt/ros/noetic/setup.bash2. 创建工作空间并克隆代码 mkdir -p ~/code…...

    Android Telephony 四大服务和数据网络控制面数据面介绍

    在移动通信和Android系统中,涉及的关键概念和服务以及场景案例说明如下: 一、概念 (一)Android Telephony 的四大服务 介绍Telephony Data 与 Android Data 的四大服务在Android系统中,与电话(Telephony)和移动数据(Data)相关的核心服务主要包括以下四类: 1. Tele…...