QT知识梳理

一、Qt简介

  1. Qt历史

Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。

Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc)),以及一些宏,Qt很容易扩展,并且允许真正地组件(控件)编程。

Qt包括多达500个以上的C++类,还替供基于模板的collections,serialization,file,I/O device,directory management,date/time类。甚至还包括正则表达式的处理功能。

  1. QObject   

QT项目中使用的类基本分为两种,一种为自定义的C++的类,另一种则为QObject类。QObject是所有Qt对象的基类。它的最主要特征是关于对象间无缝通信的机制:信号与槽。

QObject 以对象树的形式组织起来。当为一个对象创建子对象时,子对象会自动地添加到父对象的children()列表中。父对象拥有子对象的所有权,比如父对象可以在自己的析构函数中删除它的孩子对象。使用findChild()或findChildren()通过名字和类型查询孩子对象。

  • QT项目目录介绍
  1. pro文件

pro文件是qmake的工程文件(project),通常我们也视他为qt项目的配置文档。

pro文档中的变量:

  • QT变量:QT是声明组件模块的变量,默认包含core和gui模块,可用QT+=...来增加要用到的模块,或用QT-=...来去掉用不到的模块。
  • TARGET变量:是目标文件名变量,默认为项目文件名。
  • TEMPLATE变量:指定构建类型,常用的有:
  1.  app:  构建应用; 
  2.  lib:   构建动态库或静态库;
  3.  subdir:构建子目录项目。
  • SOURCES变量:列出源文件
  • HEADERS变量:指定头文件
  • FORMS变量:指定项目中的UI文件
  • CONFIG变量:
  1. 默认包含qt与C++版本 
  2. release:构建Release版本; 
  3. debug: 构建Debug版本;
  4. debug_and_release:同时构建Release和Debug版本; 
  5. warn_on:显示警告信息; 
  6. warn_off:关闭警告信息。
  1. mainwindow.ui

UI设计界面,可以直接通过拖拽控件来设计UI界面,系统根据界面会自动生成xml文档,程序员很难手动修改值。

  1. mainwindow.h与mainwindow.cpp
  • mainwindow.h:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {

class MainWindow;   //根据ui文件生成的类,和下面的MainWindow不是一个类

}

class MainWindow : public QMainWindow

{

    Q_OBJECT        //添加QT对象属性的宏 要是继承QObject的类,必须调用这个宏

public:

    explicit MainWindow(QWidget *parent = 0);      //继承QObject的类 在构造函数中都要指定父节点参数 因为有父节点时对象才能被自动删除

    ~MainWindow();

private:

    Ui::MainWindow *ui;        //指向界面文件生成的UI对象的指针

};

#endif // MAINWINDOW_H

  • mainwindow.cpp:

#include "mainwindow.h"

#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :

    QMainWindow(parent),           //初始化父类

    ui(new Ui::MainWindow)         //创建ui对象

{

    ui->setupUi(this);             //设置ui的父对象  UI对象与当前的窗口产生关联

}

MainWindow::~MainWindow()

{

    delete ui;     //删除UI对象  因为UI对象没有继承QObject 并没有被QT管理

}

  1. main.cpp解读

#include "mainwindow.h"

#include <QApplication>

//QApplication管理了各种各样的应用程序的广泛资源,比如默认的字体和光标。

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);    //a是这个程序的QApplication对象,必须创建,是该程序应用的对象。

    MainWindow w;        //创建一个窗口,默认是只创建不显示

    w.show();           //将窗口显示出来

    return a.exec();  //通过a对象执行程序

}

二、UI初识

  1. UI设计步骤
  • 拖拽想要的控件至指定位置
  1. label标签控件:可以显示文本信息
  2. push_button:普通按钮
  • 更改objectName,以供代码操作使用
  • 在代码中使用ui指针找到指定控件的objectName并进行操作
  • 添加信号和槽等候用户操作
  1. objectName的起名

使用 控件名_功能名 进行起名

例如:label_name,pushButton_submit等;

三、信号与槽(Signal & Slots)

  1. 信号与槽是QT提供的任意两个(QObject)对象之间的通信机制,常用来完成界面操作的响应。
  • 信号:是可以看作是一个请求或者一个动作的标志。
  • 槽:其实就是一个处理函数,是在对象中声明为slots:之下的函数及其实现,其类似于回调函数一样。槽是一个对象对他感兴趣的对象的某个时间做出处理。
  • 其信号槽工作的过程是:当一个对象发射一个信号的时候,则和其连接的对象的槽函数进行处理,等槽函数处理完成之后退出并执行接下来的内容。
  1. 信号与槽的使用

connect(sender, SIGNAL(send()), receiver, SLOT(receive()))

  • sender:发送信号的对象的指针
  • send():sender对象发送的信号
  • receiver:接收信号的槽对象的指针
  • receive():receiver用来接收send()信号的槽函数

使用步骤:

  • 创建一个函数作为槽函数(在声明处使用访问权限 slots:进行修饰),并完成实现
  • 在槽函数中编写接到信号后的一系列处理(改文本等)
  • 在MainWindow的构造函数中使用connect函数进行信号与槽的连接
  • 依次在connect函数中 指定信号发送者,设定触发发送信号的方式,指定接收者,设定已定义好的槽函数
  1. 定义槽函数

访问权限 slots: 

                  槽函数声明

private slots

void change();

  1. 自定义信号

signals:

                  信号函数声明(信号函数不可以被实现)

  1. 发送信号

emit 信号函数

  1. 信号和槽的参数传递
  • 当信号与槽函数的参数数量相同时,它们参数类型要完全一致。
  • 当信号的参数与槽函数的参数数量不同时,只能是信号的参数数量多于槽函数的参数数量,且左边相同数量的参数类型应一致,信号中多余的参数会被忽略。

四、QT中的字符串操作(QString)

可以使用qDebug()进行输出测试,需导入<QDebug>头文件,用法与cout类似。

  1. 拼接

QString s1 = "hello ";

QString s2 = "world";

s1 += s2;

s1.append(" farsight");

  1. 格式化

s1.sprintf("%s %d","哈哈",100);

s1 = QString("%1 was born in %2").arg("小明").arg(1900);

  1. 移除空白字符
  • 移除两端空白字符

s1 = " hello           good        farsight   ";

s1 = s1.trimmed();

  • 移除两端空白字符,使用单个空格代替字符串中间的空白字符

s1 = "  hello           good        farsight  ";

s1 = s1.simplified();

  1. 查询(Qt::CaseInsensitive大小写不敏感,Qt::CaseSensitive大小写敏感)
  • 查询开头 大小写不敏感

QString s1 = "Welcome to you!";

qDebug()<<s1.startsWith("welcome", Qt::CaseInsensitive);

  • 查询开头 参数2默认为大小写敏感

qDebug()<<s1.startsWith("welcome");

  • 查询结尾

qDebug()<<s1.endsWith("you!", Qt::CaseSensitive);

  • 包含  参数2默认为大小写敏感

qDebug()<<s1.contains("to");

mid 截取字符串

参数1为起始下标位置,参数2为截取个数

Split 根据所给字符串格式分割字符

分割结果为QStringList,可变历

  1. 其他操作
  • insert()              在原字符串指定位置插入另一个字符串
  • prepend()          在原字符串开头插入另一个字符串
  • replace()           用指定的字符串替换原字符串中的某些字符
  • 比较 > < >= <= ==
  • 字符串转换   toInt() toDouble() toFloat() toLong() toLongLong()

五、QT常用widget与其常用成员函数

  1. widget通用属性
  • enabled:控件是否有效(灰色状态)
  • geometry:有x,y,宽度,高度属性,是窗口默认显示的坐标和大小 锚点
  • minimumSize和maximumSize:设置窗口的最小和最大尺寸
  • Palette为窗口样式,从窗口的文本颜色到激活非激活状态下窗口的显示方式都有,可以自行在设计师界面或者代码中调整
  • font为字体菜单,选择窗口默认字体和大小
  • cursor设置鼠标位于窗口中时的显示方式,包括默认状态,选中,等待等。
  1. 标签 Label

Label一般用于显示一个提示性的字符串,或者显示图片或电影

  • void setText(QString);                                设置label框内的文本
  • void hide();                                                  隐藏label框
  • void clear();                                                 清空label框内所有内容
  • void setToolTip(QString);                          设置信息提示
  • void setToolTipDuration(int);                   设置信息提示的持续时间,单位是毫秒
  • void setAlignment(Qt::Alignment);          设置label框的对齐格式
  1. 单行输入框 LineEdit

LineEdit可以提供文本输入(单行)

  • void setPlaceholderText(QString)             设置提示字
  • void setText(QString)                                  设置编辑框内的文本
  • void setReadOnly(bool)                               把设置编辑框为只读模式,无法进行编辑.
  • void setEnabled(bool)                                 设置是否激活行编辑框,作用和3类似
  • bool isModified()                                          判断文本是否被修改
  • QString displayText()                                   返回显示的文本
  • QString selectedText()                                返回被选中的文本
  • QString text()                                               返回输入框的当前文本
  • void setMaxLength(int)                              设置文本的最大允许长度
  • void setEchoMode(QLineEdit::模式)                设置文本显示模式,password为黑点

六、对话框(Dialog)

  1. 创建对话框
  • 项目中新创建文档
  • 选择模板为Dialog...
  • 在槽函数中创建自定义对话框的对象,在堆空间中创建,可以依托于某个父组件
  • 使用show函数显示
  1. 模态和非模态对话框
  • 模态对话框:即在没有关闭之前,不能再与同一个应用程序的其它窗口进行交互,比如新建项目时弹出的对话框。

dialog->setModal(true);

  • 非模态对话框:可以在同一程序中与他交互,如查找替换对话框,默认的对话框为非模态。

dialog->setModal(false);

  1. QT自带标准对话框
  1. 标准文件对话框 QFileDialog类

打开标准文件对话框并返回用户选中的文件

QString QFileDialog::getOpenFileName

(

         QWidget* parent = 0,                                       //标准文件对话框的父窗口

         const QString& caption = QString(),            //标准文件对话框的标题名

         const QString& dir = QString(),                     //指定默认的目录,若此处有文件,则文件将是默认选中的文件

         const QString& filter = QString(),                 //过滤器,名称+(),括号里是文件的过滤规则,如*.c,多过滤器之间用;;隔开,默认是无过滤

         QString* selectFilter = QString(),                   //用户选中的参数4中的过滤器将通过参数5返回

         Options option = 0                                             //选择显示文件名的格式,默认是显示目录和文件名

);

  1. 标准颜色对话框 QColorDialog类

QColor getColor

(

         const QColor &initial = Qt::white,                //默认选中的颜色

         QWidget *parent = 0,                                       //父窗口

         const QString &title = QString(),                   //标题名

         ColorDialogOptions options = 0                    //参数

);

  1. 标准字体对话框 QFontDialog类

QFont getFont(

         bool *ok,                                                              //用户是否选择确定

         const QFont &initial,                                       //默认字体

         QWidget *parent = 0,                                     //父窗口

         const QString &title = QString(),                   //标题

         FontDialogOptions options = 0                      //参数

);

  1. 标准输入对话框  QInputDialog类
  • 标准字符串输入对话框

QString getText(

         QWidget *parent,                                                               //父窗口

         const QString &title,                                                          //标题

         const QString &label,                                                         //输入提示

         QLineEdit::EchoMode echo = QLineEdit::Normal,    //QLineEdit 输入模式

         const QString &text = QString(),                                    //QLineEdit 默认显示的内容

         bool *ok = 0,

         Qt::WindowFlags flags = 0,                                               //窗口类型

         Qt::InputMethodHints inputMethodHints = Qt::ImhNone               //输入类型

);

  • 标准条目选择对话框

QString getItem(

         QWidget *parent,

         const QString &title,

         const QString &label,

         const QStringList &items,                                       //所有的条目

         int current = 0,                                                            //默认显示的条目索引

         bool editable = true,                                                  //条目是否可编辑

         bool *ok = 0,

         Qt::WindowFlags flags = 0,

         Qt::InputMethodHints inputMethodHints = Qt::ImhNone

);

  • 标准int类型输入对话框

int getInt(

         QWidget *parent,

         const QString &title,

         const QString &label,

         int value = 0,                                                                 //默认显示值  QSpinBox

         int minValue = -2147483647,                                 //允许输入最小值

         int maxValue = 2147483647,                                  //允许输入最大值

         int step = 1,                                                                  //步进值

         bool *ok = 0,

         Qt::WindowFlags flags = 0

);

  • 标准double类型输入对话框

double getDouble(

         QWidget *parent,

         const QString &title,

         const QString &label,

         double value = 0,

         double minValue = -2147483647,

         double maxValue = 2147483647,

         int decimals = 1,                                                         //精度,小数点后保留位数

         bool *ok = 0,

         Qt::WindowFlags flags = 0

);

  1. 消息对话框 QMessageBox类
  • Question消息框

int question(

         QWidget *parent,

         const QString &title,

         const QString& text,                                                   //消息内容

         StandardButton button0,                                        //对话框包含的按钮

         StandardButton button1                                          //默认焦点所在按钮

);

  • infomation消息框

StandardButton information(

         QWidget *parent,

         const QString &title,

         const QString& text,

         StandardButton button0,

         StandardButton button1 = NoButton

);

  • Warning消息框

int warning(

         QWidget *parent,

         const QString &title,

         const QString& text,

         StandardButton button0,

         StandardButton button1

);

  • Critical消息框

int critical(

         QWidget *parent,

         const QString &title,

         const QString& text,

         StandardButton button0,

         StandardButton button1

);

  • About消息框

void about(

         QWidget *parent,

         const QString &title,

         const QString &text

);

  • AboutQt消息框

void aboutQt(

         QWidget *parent,

         const QString &title = QString()

);

7.自定义消息框

QMessageBox customMsg;

customMsg.addButton();                                //添加按钮

customMsg.setWindowTitle();                     //设置标题

customMsg.setText();                                       //设置消息内容

customMsg.setIconPixmap();                        //设置显示图片

customMsg.exec();                                            //显示并执行消息框

customMsg.clickedButton();                          //获得选中按钮的指针

七、主窗口

  1. QActon 动作类   菜单和工具栏内的具体条目,负责完成具体功能
  • 构造函数

QAction(

         const QIcon &icon,                                  //图标

         const QString &text,                               //名字

         QObject* parent                                       //父窗口

);

  • 设置快捷键

void setShortcut(const QKeySequence &shortcut);//参数传递QString

  1. QMenu 菜单类

QMenuBar菜单栏类,窗口默认创建,调用主窗口函数QMenuBar *menuBar() const 获得当前窗口的QMenuBar对象

  • 向QMenuBar对象添加菜单  

 QMenu *addMenu(const QString &title)

  • 向菜单QMenu对象中添加QAction             

void addAction(QAction *action)

  1. QToolBar 工具栏类
  • QToolBar工具栏类:调用主窗口函数 QToolBar *addToolBar(const QString &title) 创建QToolBar对象
  • 向QToolBar对象添加QAction对象  void addAction(QAction *action)

八、事件

  1. 鼠标事件
  • 需导入头文件<QMouseEvent>
  • 事件函数
  1. void mousePressEvent(QMouseEvent* e);                       //当鼠标按下
  2. void mouseReleaseEvent(QMouseEvent* e);                   //当鼠标释放
  3. void mouseMoveEvent(QMouseEvent* e);                      //当鼠标移动
  4. void mouseDoubleClickEvent(QMouseEvent* e);           //当鼠标双击
  • 实时跟踪鼠标移动的位置将QWidget::setMouseTracking(bool enable) 设置为true
  • e的属性
  1. e.x()获取鼠标的x轴坐标
  2. e.y()获取鼠标的y轴坐标
  3. e.button()获取是哪个按键触发事件
  1. 键盘事件
  • 需导入头文件<QKeyEvent>
  • 事件函数
  1. void keyPressEvent(QKeyEvent* e);                                    //当键盘中的某个键被按下
  1. 定时事件
  • 需导入头文件<QTimerEvent>
  • 事件函数
  1. void timerEvent(QTimerEvent* e);                                     //定时事件
  • 启动定时器

int startTimer(                                                                         //返回值定时器id 

         int interval,                                                                    //定时器时间,默认为毫秒

         Qt::TimerType timerType = Qt::CoarseTimer          //定时器精度

);

  • 暂停定时器

void killTimer(int id);                                                              //停止指定id的定时器

九、文件

  1. QFile读写文本文件
  • 创建对象QFile(const QString &name);
  • 打开文件bool open(OpenMode flags);  
    1. ReadOnly
    2. WriteOnly
    3. ReadWrite
    4. Append
    5. Truncate
  • 写文件qint64 write(const char *data, qint64 len);
  • 读文件qint64 read(char *data, qint64 maxlen);
  • 复制文件 bool copy(const QString &newFile);
  1. 字符流,适合操作纯文本文件,传输以字符为单位,速度相对较快
  • 创建对象explicit QTextStream(QIODevice *device);
  • 读文件QTextStream &operator>>(QString &s);
  • 写文件QTextStream &operator<<(const QString &s);
  • 格式化函数

         qSetFieldWidth(int width)                                  设置字段宽度

         qSetPadChar(QChar ch)                                      设置填充字符

         qSetRealNumberPercision(int precision)         设置实数精度

  • 流操作符
  • bin    设置读写的整数为二进制
  • oct   设置读写的整数为八进制
  • dec   设置读写的整数为十进制
  • hex 设置读写的整数为十六进制
  • showbase          强制显示进制前缀
  • forcesign           强制显示符号 + -
  • forcepoint         强制显示小数点
  • noshowbase     不显示进制前缀
  • noforcesign      不显示符号
  • left                     居左
  • right                   居右
  • center               居中
  • endl                   换行
  • flush                   清理缓存
  1. 字节流,适合操作非纯文本文件,传输以字节为单位,速度相对较慢
  • 创建对象         explicit QDataStream(QIODevice *);
  • 读文件     QDataStream &operator>>(char *&str);
  • 写文件     QDataStream &operator<<(const char *str);

  1. QDir 目录操作
  • 创建对象 QDir(const QString &path = QString());
  • 查找目录内的子元素 QStringList entryList(Filters filters = NoFilter, SortFlags sort = NoSort) const;
  • 参数1:过滤器
  1. QDir::Dirs          按照过滤方式列出所有目录
  2. QDir::AllDirs     不考虑过滤方式列出所有目录
  3. QDir::Files         所有文件
  4. QDir::Drives     所有磁盘驱动器(UNIX系统无效)
  5. QDir::Hidden   所有隐藏文件
  • 参数2:排序规则
  1. QDir::Name              按照名字排序
  2. QDir::Time                按照修改时间排序
  3. QDir::Size          按照文件大小排序
  4. QDir::Type                 按照文件类型排序
  5. QDir::DirsFirst 目录优先排序
  6. QDir::DirsLast  目录最后排序
  7. QDir::Reversed         反序
  8. QDir::IgnoreCase     忽略大小写方式排序
  9. QDir::LocaleAware  使用当前本地排序方式排序
  1. QFileInfo 文件信息类
  • 创建对象QFileInfo(const QString &file); 参数要求是文件的绝对路径+文件名
  • 获得各种信息
  • QDateTime created() const;   获得创建时间
  • qint64 size() const;                    获得文件大小
  • bool isFile() const;                     判断是否为文件
  • bool isDir() const;                      判断是否是目录
  • bool isReadable() const;           是否可读
  • bool isWritable() const;            是否可写
  • bool isExecutable() const;        是否可执行

十、数据库操作

QT += sql

  1. QSqlDatabase数据库连接对象
  • 添加数据库驱动,创建数据库连接

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

  • 设置主机名  

db.setHostName(主机名);

  • 设置数据库名,sqlite产生的文件名

db.setDatabaseName(数据库名.db);

  • 打开数据库

db.open();

  • 关闭数据库

db.close();

  1. QSqlQuery数据库操作对象
  1. 通用操作
  • 创建数据库操作对象

QSqlQuery query

  • 预设要执行的sql语句,需要传参的位置用?占位

query.prepare(sql语句);

  • 为设定好的sql语句传入具体参数,参数位置与具体值

query.bindValue(位置,值);

  • 执行sql语句,返回执行是否成功

query.exec();   

  1. 增 删 改
  • Sql语句复习
  • 实现步骤
QSqlQuery query;
    query.prepare("insert into persons(name) values(?)");
    query.bindValue(0,"张三");
return query.exec();
 
 
  • Sql语句复习
  • query.next() 

判断查询结果中是否有下一条,有则返回true并指向下一行,没有则返回false

  • query.record()

获取查询记录,并通过调用value()函数获得记录中的字段值

  • 实现步骤
QSqlQuery query;
vector<Person> persons;
    query.prepare("select * from person where age between ? and ?");
    query.bindValue(0,20);
    query.bindValue(1,30);
    bool ok = query.exec();
    while(query.next())
    {
        Person p(
                    query.record().value("name").toString(),
                    query.record().value("id").toInt(),
                    );
        persons.push_back(p);
    }
return ok;

十一、线程

  1. 线程使用
  • 定义线程类继承QThread,
  • 重写run函数,在run函数中编写线程要执行的逻辑
  • 在run函数中通过自定义信号发送消息至主窗口
  • 由窗口类编写的槽函数接收并处理信号
  • 启动和停止线程,start()  terminate()
  1. 互斥锁 QMutex类

在一般情况下,创建一个线程是不能提高程序的执行效率的,所以要创建多个线程。但是多个线程同时运行的时候可能调用线程函数,在多个线程同时对同一个内存地址进行写入,由于CPU时间调度上的问题,写入数据会被多次的覆盖,所以就要使线程同步。

线程互斥锁是实现线程同步的一种办法,在一个线程修改变量时加锁,则其他变量阻塞,等待加锁的变量解锁后再执行。

创建QMutex类对象

  • 在线程需要改变变量前使用QMutex类对象.lock()加锁
  • 在修改之后QMutex类对象.unlock();解锁

注意:必须解锁,不然则会发生死锁现象,线程无法继续

十二、网络编程

QT += network

  1. TCP

 

  • TCP服务端

#include <QTcpServer>

#include <QTcpSocket>

  • 创建QTcpServer对象
  • 为服务设置监听方式(listen)与端口
  • 连接新客户端的连接信号 SIGNAL(newConnection())
  • 在槽函数中获取新连接过来的客户端套接字对象                                                           client = server->nextPendingConnection();
  1. 读取客户端发来的消息:
  • 将客户端连接 预备读取 信号 SIGNAL(readyRead())
  • 通过客户端对象调用readAll()函数读取所有客户端发送过来的消息
  1. 向客户端发送消息:
  • 调用客户端.write函数,将要发送的消息转成char类型发送,toLocal8Bit转为char类型client->write(data.toLocal8Bit().data(), data.toLocal8Bit().size())
  1. 断开连接:
  • 为客户端连接disconnect信号

  • TCP客户端

#include <QTcpSocket>

#include <QHostAddress>

  • 创建QTcpSocket对象
  • 使用socket对象调用connectToHost函数设置连接主机IP、端口与权限
  • socket连接 连接信号 connected
  • 当连接上信号时(调用到connected信号的槽函数时),连接断连信号和预备读取信号

  1. UDP

 

#include <QUdpSocket>

#include <QHostAddress>

  • 创建QUdpSocket对象
  • 绑定监听端口
  • 连接接受到消息时执行的槽函数

  • 发送数据

qint64 writeDatagram(

                  const QByteArray &datagram, //发送的数据  可以使用QString进行转换

                  const QHostAddress &host,   //接收端服务器的类型 

                  quint16 port                               //接收端端口号

);

  • 接收数据

         qint64 readDatagram(

                  char *data,                                                  //读取数据到data中

                  qint64 maxlen,                                            //最大长度

                  QHostAddress *host = 0,                           //发送广播的主机

                  quint16 *port = 0                                        //端口

         );

示例:读取数据

while(socket->hasPendingDatagrams())//判断socket是否有数据报 可读

{

    QByteArray data;

    data.resize(socket->pendingDatagramSize());

    socket->readDatagram(data.data(), data.size());

    ui->lineEdit->setText(QString::fromLocal8Bit(data));

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值