Qt5模板库、工具类及控件

Qt5模板库、工具类及控件

1、字符串类

1.1、操作字符串

QString 类保存16 位Unicode 值,该类还进行了使用隐式共享(implicit sharing) 、高效的内存分配策略等多方面的优化。

QString strl ="Welcome";  // const char* 类型的ASCII 字符串,以"\0"结尾的C 类型字符串 QString : :fromAscii() 函数转换为Unicode 编码。
strl=strl+"to you! ";//strl=" Welcome to you! "
QString str2="Hello, ";
str2+="World! "; //str2="Hello,World! "

//QString: :append() 函数具有与"+="操作符同样的功能,实现在一个字符串的末尾追加另一个字符串。
QString strl ="Welcome";
QString str2 ="to ";
strl.append(str2); //strl=" Welcome to"
strl.append("you! ");//strl="Welcome to you! "

QString str;
str.sprintf("%s"," Welcome"); //str="Welcome"
str.sprintf("%s"," to you! "); //str="to you! "
str.sprintf("%s %s"," Welcome", "to you!"); //str=" Welcome to you!"

QString str;
str=QString("%1 was born in %2.").arg ("John").arg (1998); / / str="John was born in 1998."

insert() //在原字符串特定的位置插入另一个字符串。
prepend() //在原字符串的开头插入另一个字符串。
replace() //用指定的字符串代替原字符串中的某些字符。
QString::trimmed() //移除字符串两端的空白字符。
QString::simplified() //移除字符串两端的空白字符,使用单个空格字符”“代替字符串中出现的空白字符。

QString str=" Welcome \t to \n you! ";
str=str.trimmed(); //str=" Welcome \t to \n you!"

1.2 查询字符串数据

//判断一个字符串是否以某个字符串开头。
QString str="Welcome to you! ";
str.startsWith("Welcorne",Qt: :CaseSensitive); //返回true
str.startsWith("you",Qt::CaseSensitive); //返回false
QString::endsWithO() //判断一个字符串是否以某个字符串结尾。
//判断一个指定的字符串是否出现过
QString str=" Welcome to you! ";
str. contains ("Welcome", Qt:: CaseSensitive); //返回true

//比较两个字符串 返回true
operator<(const QString&): 比较一个字符串是否小于另一个字符串。 <=  ==   >=可替代<
localeAwareCompare(const QString&,const QString&): //静态函数,比较前后两个字符串。小于返回负整数;等于则返回0; 大于返回正整数值。基于本地(locale) 字符集与平台相的。通常,该函数用于向用户显示一个有序的字符串列表。
compare(const QString&,const QString&,Qt::CaseSensitivity): //指定是否进行大小写的比较,基于字符的Unicode编码值。

1.3 字符串的转换

//字符串转换为数值类
// toDouble()、toFloat()、toLong() 、toLongLong()等。
QString str="l25"; //初始化一个"125" 的字符串
bool ok;
//第二个参数指定转换的基数。字符串"0x"开头,则基数为16; 字符串以"0"开头基数为8; 其他情况,基数10 
int hex=str.toInt (&ok, 16) ; // ok=true, hex=293  将字符串转换为整型数值
int dec=str.toInt(&ok,10); //ok=true,dec=125

//字符编码集的转换函数  返回const char*类型版本的QByteArray,即构造函数QByteArray(const char*)构造的QByteArray 对象。QByteArray类具有字节数组,既可存储原始字节(raw bytes) , 也可存储传统的以"\O" 结尾的8 位的字符串。在Qt中,使用QByteArray 比使用const char*更方便,且QByteArray也支待隐式共享。

toAscii()// 返回ASCII编码的8位字符串。
toLatinl()// 返回一个Latin-1 (ISO8859-1) 编码的8位字符串。
toUtf8()//返回一个UTF-8 编码的8 位字符串(UTF-8是ASCII 码的超集,它支待整个Unicode 字符集)
toLocal8Bit()//返回一个系统本地(locale) 编码的8位字符串。

QString str=" Welcome to you! "; //初始化一个字符串对象
QByteArray ba=str.toAscii(); //将Unicode转换为ASCII 码的字符串,存储在ba中。
qDebug ()<<ba; // 使用qDebug()函数输出转换后的字符串(qDebug() 函数支持输出Qt 对象)。
ba.append("Hello, World! ");//
qDebug()<<ba.data() ;//输出最后结果
//一个NULL字符串一定是一个空字符串,而一个空字符串未必是一个NULL 字符串。
QString("").isNull();//结果为false
QString("").isEmpty();//结果为true

2、容器类

  • 基于模板的容器类,比STL更轻量、更安全更容易使用。
  • 在速度、内存消耗和内联(inline) 代码等方面进行了优化(较少的内联代码将缩减可执行程序的大小)。

数据必须是可赋值的数据类型(该数据类型必须提供一个默认的构造函数(不需要参数的构造函数)、一个复制构造函数和一个赋值操作运算符。)
Qt 的QObject 及其他的子类不能存储在容器中,因为这些类没有复制构造函数和赋值操作运算符。但可以存储其指针。

QList<QToolBar*> list;
QHash<QString,QList<double> > //保留空格

容器类遍历Java-style iterators与STL-style iterators,后者可与QT一起使用,且效率更高。

2.1 Qlist 类、Qlinkedlist 类和QVector 类

时间复杂度比较在这里插入图片描述"Amort.0(1)" 表示,如果仅完成一次操作,可能会有O(n) 行为;但是如果完成多次操作(如n 次),平均结果将会是0(1) 。

Qlist 类

QList 存储给定数据类型T的一列数值。继承自QList类的子类有QitemSelection 、QQueue 、QSignalSpy 、QStringList 和QTestEventList 。在列表中追加QList::append()和Q list::prepend() ,在中间插入QList::insert()。为了使可执行代码尽可能少,QList 被高度优化。提供下标快速访问

对千不同的数据类型, QList 采取不同的存储策略,
(1) 如果T 是一个指针类型或指针大小的基本类型(即该基本类型占有的字节数和指针类型占有的字节数相同), QList会将数值直接存储在它的数组中。
(2) 如果QList 存储对象的指针,则该指针指向实际存储的对象。

#include <QDebug>
int main(int argc,char *argv[])
{
	QList<QString> list; //(a)声明了一个QList<QString>栈对象。
	{
		QString str("This is a test string");
		list<<str; //将一个QString 字符串存储在该列表中
	}
	qDebug()<<list[0]<<"How are you!";
	return 0;
}
QLinkedList 类

QLinkedList链式列表,它以非连续的内存块保存数据。不能使用下标,只能使用迭代器访问它的数据项,当对一个很大的列表进行插入操作时, QLinkedList 具有更高的效率。

QVector 类

QVector在相邻的内存中存储给定数据类型T的一组数值。在QVector 前部或者中间位置进行插入操作的速度是很慢,因为将导致内存中的大量数据被移动,这是由存储数据的方式决定的。
可以用下标访问或迭代器访问数据项,继承自QVector类的子类有QPolygon 、QPolygonF 和QStack

java风格迭代与C++风格迭代

Java比STL使用更方便,但以轻微性能损耗为代价。
Qt提供只读迭代器类和读写迭代器类两种Java 风格迭代器数据类型。
迭代点位于列表项的中间,前后中间。
在这里插入图片描述
QList 只读遍历方法

#include <QCoreApplication>
#in~lude <QDebug>
int main(int argc, char *argv[))
(
	QCoreApplication a(argc, argv);
	QList<int> list;
	list<<l<<2<<3<<4<<5;
	QListIterator<int> i(list);//QList 只读遍历方法
	for (; i.hasNext();) //检查当前迭代点之后是否有列表项
	//next() 函数将会跳过下一个列表项(即迭代点将位千第一个列表项和第二个列表项之间),并返回它跳过的列表项的内容。
		qDebug()<<i.next(); 
	return a. exec() ;
}

QListlterator<T>: :toBack(): 将迭代点移动到最后一个列表项的后面。
QListlterator<T>: :hasPrevious(): 检查当前迭代点之前是否具有列表项。
QListlterator<T>::previous(): 返回前一个列表项的内容并将迭代点移动到前一个列表项之前。
除此之外, QListlterator提供的其他函数还有如下几种。
toFront(): 移动迭代点到列表的前端(第一个列表项的前面)。
peekNext(): 返回下一个列表项,但不移动迭代点。
peekPrevious(): 返回前一个列表项,但不移动迭代点。
findNext(): 从当前迭代点开始向后查找指定的列表项,找到返回true, 迭代点位千匹配列表项的后面;没找到返回false,迭代点位千列表的后端(最后一个列表项的后面)。
findPrevious(): 方向向前,查找操作完成后的迭代点在匹配项的前面或整个列表的前端。

读写迭代器QMutableListlterator除提供基本的遍历操作(与QListlterator 的操作相同)外,还提供了insert()插入操作函数、remove() 删除操作函数和修改数据函数等。

#include <QCoreApplication>
#include <QDebug>
int main(int argc,char *argv[])
{
	QCoreApplication a(argc, argv);
	QList<int> list;  //创建一个空的列表list
	QMutableListiterator<int> i(list); //创建上述列表的读写迭代器
	for (int j=O; j<lO; ++j)
		i.insert(j);  //插入操作
	for (i. to Front() ; i. hasNext () ;)  // 将迭代器移动到列表前端,完成遍历
		qDebug () <<i. next() ;
	for(i.toBack();i.hasPrevious();)  // 移动迭代器到列表后端,并遍历
	{
		if (i.previous ()%2==0)
		1..remove();
		else
		i.setValue(i.peekNext()*lO);
	}
	for(i.toFront();i.hasNext();)
		qDebug ()«i. next () ;
	return a.exec();
}

在这里插入图片描述

#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<int> list;						//初始化一个空的QList<int>列表
    for(int j=0;j<10;j++)
        list.insert(list.end(),j);			//(a)
    QList<int>::iterator i;
    //初始化一个QList<int>::iterator读写迭代器
    for(i=list.begin();i!=list.end();++i)	//(b)
    {
           qDebug()<<(*i);
           *i=(*i)*10;
    }
    //初始化一个QList<int>:: const_iterator读写迭代器
    QList<int>::const_iterator ci;
    //在控制台输出列表的所有值
    for(ci=list.constBegin();ci!=list.constEnd();++ci)
            qDebug()<<*ci;

    return a.exec();
}

QMap 类和Otlafill 类

QMap 类和QHash 类具有非常类似的功能,它们的差别仅在千:
• QHash 具有比QMap 更快的查找速度。
• QHash 以任意的顺序存储数据项,而QMap 总是按照键Key 的顺序存储数据。
• QHash 的键类型Key 必须提供operator==()和一个全局的qHash(Key) 函数,而QMap的键类型Key 必须提供operator<() 函数。
在这里插入图片描述

  1. QMap 类
    QMap<Key, T>提供了一个从类型为Key 的键到类型为T 的值的映射。
    通常, QMap 存储的数据形式是一个键对应一个值,并且按照键Key 的顺序存储数据。为了能够支持一键多值的情况,Map 提供了QMap<Key,T>: :insertMulti()和QMap<Key,T>: :values()函数。存储一键多值的数据时,也可以使用QMultiMap<Key,T>容器,它继承自QMap 。
  2. QHash 类
    QHash<Key,T>维护着一张哈希表(Hash Table),哈希表的大小与QHash 的数据项的数目相适应。以任意的顺序组织它的数据。当存储数据的顺序无关紧要时,建议使用QHash 作为存放数据的容器。QMultiHash<Key,T>存储一键多值形式的数据。
    在这里插入图片描述
    在这里插入图片描述
#include <QCoreApplication>
#include <QDebug>
int main(int argc,char *argv[])
{
QCoreApplication a(argc, argv);
QMap<QString,QString> map;
map.insert("beijing","111");
map.insert("shanghai","021");
map.insert("nanjing","025");
QMapiterator<QString,QString> i(map);//创建一个只读迭代器
for (; i.hasNext () ;)
{
	i .next();
	qDebug () <<" "<<i. key () <<" "<<i. value ();
}
QMutableMapiterator<QString,QString> mi(map);
if (mi.findNext ("111"))
	mi.setValue ("010");
QMapiterator<QString,QString> modi(map);
qDebug () <<" ";
for (; modi. hasNext () ;) //再次遍历井输出修改后的结果
{
modi.next();
qDebug () <<" "<<modi. key () <<" "<<modi. value ();
}
return a.exec();



hnclude <QCoreApplication>
hnclude <QDebug>
int main(int argc,char *argvf])
QCoreApplication a(argc, argv);
QMap<QString,QString> map;
map. insert ("bei扛ng","111");
map.insert("shanghai","021");
map.insert("nanjing","025");
QMap<QString,QString>::const_iterator i;
for(i=map.constBegin();i!=map.constEnd();++i)
	qDebug () <<" "<<i. key()<<" "<<i. value();
QMap<QString,QString>::i 七erator mi;
mi=map.find("beijing");
if (mi! =map. end())
mi. v·a.lue () ="010"; //(a)
QMap<QString;Qs_tring>: :const iterator modi;
qDebug () <<" ";
for (modi=map. constBegin ();modi! =map. constEnd (); ++modi)
qDebug()<<" "<<modi.key()<<" "<<modi.value();
return a.exec();
}

QVariant 类

QVariant 类类似千C++的联合(union) 数据类型,它不仅能保存很多Qt 类型的值,包括QColor 、QBrush 、QFont 、QPen 、QRect 、QString 和QSize 等,

#include "widget.h"
#include <QDebug>
#include <QVariant>
#include <QColor>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QVariant v(709);					//(a)
    qDebug()<<v.toInt();				//(b)
    QVariant w("How are you! ");		//(c)
    qDebug()<<w.toString();				//(d)
    QMap<QString,QVariant>map;			//(e)
    map["int"]=709;						//输入整数型
    map["double"]=709.709;				//输入浮点型
    map["string"]="How are you! ";		//输入字符串
    map["color"]=QColor(255,0,0);		//输入QColor类型的值
    //调用相应的转换函数并输出
    qDebug()<<map["int"]<< map["int"].toInt();
    qDebug()<<map["double"]<< map["double"].toDouble();
    qDebug()<<map["string"]<< map["string"].toString();
    qDebug()<<map["color"]<< map["color"].value<QColor>();	//(f)
    QStringList sl;						//创建一个字符串列表
    sl<<"A"<<"B"<<"C"<<"D";
    QVariant slv(sl);					//将该列表保存在一个QVariant变量中
    if(slv.type()==QVariant::StringList)//(g)
    {
        QStringList list=slv.toStringList();
        for(int i=0;i<list.size();++i)
            qDebug()<<list.at(i);		//输出列表内容
    }

}

Widget::~Widget()
{

}

算法及正则表达式

Qt 的<QtAlgorithms><QtGlobal> 模块中提供的几种常用算法.使用正则表达式可以方便地完成处理字符串的一些操作,如验证、查找、替换和分割等。Qt 的QRegExp 类是正则表达式的表示类,它基千Perl 的正则表达式语言,完全支待Unicode 。
正则表达式由表达式(expressions) 、量词(quantifiers) 和断言(assertions) 组成。

字符集可以使用表达式如"[AEIOU]", 表示匹配所有的大写元音字母;使用"[AAEIOU]", 表示匹配所有非元音字母,即辅音字母;连续的字符集可以使用表达式如"[a-z] ", 表示匹配所有的小写英文字母。

量词说明表达式出现的次数,如"x(l,2]" 表示"x" 可以至少有一个,至多有两个。

" [A-Za-z_]+[A-Za-z_0-9]*"

其中,表达式中的"+“表示”[A-Za-z_]“至少出现一次,可以出现多次;“*”表示”[A-Za-z_ 0-9]"
可以出现零次或多次。

在这里插入图片描述

控件

按钮组(Buttons)

• Push Button: 按钮。
• Tool Button: 工具按钮。
• Radio Button: 单选按钮。
• Check Box: 复选框。
• Command Link Button: 命令链接按钮。
• Dialog Button Box: 对话框按钮盒。

输入部件组(Input Widgets)

• Combo Box: 组合框。
• Font Combo Box: 字体组合框。
• Line Edit: 行编辑框。
• Text Edit: 文本编辑框。
• Plain Text Edit: 纯文本编辑框。
• Spin Box: 数字显示框(自旋盒)。
• Double Spin Box: 双自旋盒。
• Time Edit: 时间编辑。
• Date Edit: 日期编辑。
• Date/Time Edit: 日期/时间编辑。
• Dial: 拨号。
• Horizontal Scroll Bar: 横向滚动条。
• Vertical Scroll Bar: 垂直滚动条。
• Horizontal Slider: 横向滑块。
• Vertical Slider: 垂直滑块。
• Key Sequence Edit: 按键序列编辑框。

QDateTime 类
Date/Time Edit 可以用来获得系统时间。通过QDateTime: :currentDateTime()来获取本地系统的时间和日期信息。可以通过date()和time()来返回datetime中的日期和时间部分,典型代码如下:

QLabel * datalabel =new QLabel();
QDa 七eTime *datatime=new QDateTime (QDateTime:: currentDateTime());
datalabel->setText(datatime->date ().toString ());
datalabel->show();

QTimer 定时器类

QTimer *time_clock=new QTimer(parent); //新建一个定时器。
connect(time_clock,SIGNAL(timeout()), this, SLOT (slottimedone ()));  //连接这个定时器的信号和槽,利用定时器的timeout()
/*
定时器定时有两种方式: start(int time)和setSingleShot(true) 。其中, start(int time)表示每隔"time" 秒就会重启定时器,可以重复触发定时,利用stop()将定时器关掉;而setSingleShot(true)则是仅启动定时器一次。工程中常用的是前者.
*/
time_clock->start(2000);

显示控件组(Display Widgets)

• Label: 标签。
• Text Browser: 文本浏览器。
• Graphics View: 图形视图。
• Calendar Widget: 日历。
• LCD Number: 液晶数字。
• Progress Bar: 进度条。
• Horizontal Line: 水平线。
• Vertical Line: 垂直线。
• OpenGL Widget: 开放式图形库工具。
• QQuickWidget: 嵌入QML 工具。

Graphics View对应于QGraphicsView 类提供了Qt5 的图形视图框架。
Text Browser 对应千QTextBrowser 类。QTextBrowser 类继承自QTextEdit, 而且仅是只读的,对里面的内容不能进行更改,但是相对千QTextEdit 来讲,它还具有链接文本的作用。QTextBrowser 的属性设置,可以设定QTextBrowser 是否允许外部链接夕是否为只读属性,外部链接的路径及链接的内容,是否可以进行撤销等操作。QTextBrowser 还提供了几种比较有用的槽(SLOTS), 即可以通过链接这几个槽来达到“翻页”效果。
QQuickWidget可以用它来嵌入QML 代码,但目前在QML 中尚不能嵌入其他非QML 窗口,因为QML 的渲染机制和QWidget 的是不一样的。

空间间隔组(Spacers)

• Horizontal Spacer: 水平间隔。
• Vertical Spacer: 垂直间隔。

布局管理组(Layouts)

• Vertical Layout: 垂直布局。
• Horizontal Layout: 横向(水平)布局。
• Grid Layout: 网格布局。
• Form Layout: 表单布局。

容器组(Containers)

• Group Box: 组框。
• Scroll Area: 滚动区域。
• Tool Box: 工具箱。
• Tab Widget: 标签小部件。
• Stacked Widget: 堆叠部件。
• Frame: 帧。
• Widget: 小部件。
• MDI Area: MDI 区域。
• Dock Widget: 停靠窗体部件。
• QAxWidget: 封装Flash 的ActiveX 控件。

Widget 对应QWidget 类的用法。Widget 是使用Qt 编写的图形用户界面(GUI)应用程序的基本生成块。每个GUI 组件,如按钮、标签或文本编辑器,都是一个Widget, 并可以放置在现有的用户界面中或作为单独的窗口显示。每种类型的组件都是由QWidget 的特殊子类提供的,而QWidget 又是QObject 的子类。
QWidget 是所有Qt GUI 界面类的基类,它接收鼠标、键盘及其他窗口事件,并在显示器上绘制自己。
通过传入QWidget 构造函数的参数(或者调用QWidget: :setWindowFlags()和QWidget::setParent()函数)可以指定一个窗口部件的窗口标识(window flags) 和父窗口部件。
窗口部件的窗口标识(window flags) 定义了窗口部件的窗口类型和窗口提示(hint) 。
窗口类型指定了窗口部件的窗口系统属性(window-system properties), 一个窗口部件只有一个窗口类型窗口提示定义了顶层窗口的外观,一个窗口可以有多个提示(提示能够进行按位或操作)。没有父窗口部件的Widget 对象是一个窗口,窗口通常具有一个窗口边框(frame) 和一个标题栏。QMainWindow 和所有的QDialog 对话框子类都是经常使用的窗口类型,而子窗口部件通常处在父窗口部件的内部,没有窗口边框和标题栏。
QWidget 窗口部件的构造函数为:QWidget(QWidget *parent=(),Qt::WindowFlags f=())其中,参数parent 指定了窗口部件的父窗口部件,如果parent=0(默认值),则新建的窗口部件将是一个窗口;否则,新建的窗口部件是parent 的子窗口部件(是否为一个窗口还需要由第二个参数决定)。如果新窗口部件不是一个窗口,则它会出现在父窗口部件的界面内部。参数
f 指定了新窗口部件的窗口标识,默认值是o, 即Qt::Widget 。
QWidget 定义的窗口类型为Qt::Window Flags 枚举类型,它们的可用性依赖千窗口管理器是否支待它们。
QWidget 不是一个抽象类,它可用作其他Widget 的容器,并很容易作为子类来创建定制Widget 。它经常用于创建放置其他Widget 的窗口。
对千QObject, 可使用父对象创建Widget 以表明其所属关系,这样可以确保删除不再使用的对象。使用Widget, 这些父子关系就有了更多的意义,每个子类都显示在其父级所拥有的屏幕区域内。也就是说,当删除窗口时,其包含的所有Widget 也都被自动删除。

项目视图组(Item Views)

• List View: 清单视图。
• Tree View: 树形视图。
• Table View: 表视图。
• Column View: 列视图。

模型/视图框架用于完成数据与表现的分离,这在Qt5 中称为InterView 框架,类似千常用的MVC 设计模式。模型(Model) 表示数据;视图(View) 是用户界面;控制(Controller) 定义了用户在界面上的操作。
在这里插入图片描述
• 模型:所有的模型都基千QAbstractltemModel 类,该类是抽象基类。
• 视图:所有的视图都从抽象基类QAbstractltemView 继承。
Inter View 框架提供了一些常见的模型类和视图类,如QStandardltemModel 、QDirModel、QStringListModel 、ProxyModel 和QColumnView 、QHeaderView 、QListView 、QTableView 、QTreeView 。其中,
QDirModel 可以通过树形方式显示某个目录下的所有子目录及其相关信息;
QProxyModel 用千将旧的Model 类型过渡到新的类型上;
QStandardltemModel 是用最简单的Grid方式显示Model 。
开发人员还可以从QAbstractListModel 、QAbstractProxyModel 、AbstractTableModel 继承出符合自己要求的Model 。

相对千使用现有的模型和视图, Qt 还提供了更为便捷的类用于处理常见的一些数据模型。它们将模型和视图合二为一,因此便千处理一些常规的数据类型。使用这些类型虽然简单方便,但也失去了模型/视图结构的灵活性,因此要根据具体情况来选择。
QTableWidget 继承自QTableView 。QSqlTableModel 能够与QTableView 绑定,但不能与QTableWidget 绑定。
视图与模型绑定时,模型必须使用new 创建, 会否则视图不能随着模型的改变而改变。

QSqlTableModel *model= new QSqlTableModel;
model->setTable("employee");
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
model->removeColumn(O); //不显示ID
model->setHeaderData(O, Qt::Horizontal, tr("Name"));
model->setHeaderData(l, Qt::Horizontal, tr("Salary"));
QTableView *view= new QTableView;
view->setModel(model);
view->show();

项目控件组CItern Widgets)

• List Widget: 清单控件。
• Tree Widget: 树形控件。
• Table Widget: 表控件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值