Qt/Embedded和Qtopia的GUI设计

Qt Embedded:简介与平台插件介绍 嵌入式 Linux 发行版上的 Qt 属于 QtEmbedded Linux 分支平台(本文简称为 Qt/E)。Qt/E 在原始 Qt 的基础上,做了许多出色的调整以适合嵌入式环境。同桌面版的 Qt/X11 相比,嵌入式Qt/E 很节省内存,因为它不需要 X server 或是 Xlib 库,它在底层摒弃了 Xlib,采用 Framebuffer(帧缓冲)作为底层图形接口。Qt/E 的应用程序可以直接写内核帧缓冲,这避免开发者使用繁琐的 Xlib/Server 系统。 阅读详情

基于Qt/EmbeddedQtopiaGUI设计

王丽洁,习勇,魏急波

(国防科技大学 电子科学与工程学院 湖南省 长沙市 410073)

摘要:介绍了Qt/EmbeddedQtopia的体系结构及其交叉编译过程与安装过程,重点讲述了如何实现Qt/Embedded下的应用程序以及如何将应用程序移植到Qtopia桌面系统。本文介绍的方法在笔者的开发平台上都做过验证。

关键词:嵌入式系统; GUIQt/Embedded; Qtopia; 交叉编译

中图分类号:TP368

     Design of GUI Based on Qt/Embedded and Qtopia

Wang Li-Jie, Xi Yong, Wei Ji-Bo

(School of Electronic Science and Engineering, National University of Defense Technology, Changsha 410073, China)

Abstract: In this paper, the architecture, cross-compiling and installation of Qt/Embedded and Qtopia are introduced. Especially, we focus on how to implement an application program based on Qt/Embedded and how to port an existing application to Qtopia desktop system. The methods introduced in the paper have all been validated in our development platform.

Key words: Embedded System; GUI; Qt/Embedded; Qtopia; Cross-Compiling

1 引言

随着当前各种手持设备、无线设备及信息家电等嵌入式产品的迅猛发展,相应的嵌入式软硬件设计技术也在发生深刻的变化。如今,越来越多的嵌入式终端需要一个图形化的人机接口界面(GUI),良好的人机接口界面是嵌入式系统设计的一个关键技术,能够极大地提高人机交互的效率。本文详细阐述了在自行开发的嵌入式主板上实现某平台的图形显示终端过程。

2系统平台介绍

根据系统设计需求,本文目的是实现一个具有图形接口界面的嵌入式显示终端,该系统使用嵌入式系统设计技术。硬件上,使用自行开发的基于Samsung S3C2440A CPU的目标板,该CPU使用arm920T内核,其主频可达400Mhz;在软件上,选择嵌入式linux为操作系统,因为它源码开放,而且稳定性与安全性较高。

整个系统软件由引导装载程序(uboot)、 设备驱动(包括帧缓存fb)、嵌入式Linux内核、文件系统(yaffs)、基于QT/EmbeddedQtopia用户图形界面以及应用程序组成,系统平台结构如图(1)所示。

(1) 系统平台软件结构图

3 Qt/EmbeddedQtopia 介绍及其开发环境的建立

目前嵌入式Linux的主流GUI系统主要有MiniGUIMicrowindowsOpenGUIQt/Embedded,这些GUI在接口定义、体系结构、功能特性存在很大差别,采取的技术路线也有所不同[1]MiniGUI是建立在比较成熟的图形引擎之上,开发的重点在于窗口系统,其小巧精致并且尽量与Win32兼容。MicroWindows目前开发的重点在底层的图形引擎,窗口系统和图形接口方面功能比较欠缺,与Win32X Windows窗口系统保持兼容,提供了相对完善的图形功能。OpenGUI基于一个用汇编实现的x86图形内核,提供了一个高层的C/C++图形/窗口接口,它的资源消耗小,可移植性差,不支持多进程。

Qt/Embedded是一个多平台的C++图形用户界面应用程序框架,其对象容易扩展,可移植性好,支持多个GUI平台的交互开发[2,3]。现在,Qt/Embedded被广泛地应用于各种嵌入式产品和设备中,从消费电器(如智能手机、机顶盒)到工业控制设备(如医学成像设备、移动信息系统等)。因此本文选择Qt/Embedded为本系统的GUI

(1) Qt/EmbeddedQtopia体系结构

Qt/EmbeddedTrolltech公司开发的面向嵌入式系统的Qt版本,与X11版本的Qt在最大程度上接口兼容,采用帧缓存(framebuffer作为底层图形接口。Qt/Embedded类库完全采用C++封装,并且有着丰富的控件资源以及较好的可移植性,大范围的Qt/Embedded API可用于多种开发项目。Qt/Embedded的实现结构如图(2)所示:

 

(2) Qt/Embedded实现结构

    

Qt/Embedded的底层图形引擎基于framebuffer framebuffer是一种驱动程序接口,它将显示设备抽象为帧缓冲区[4]。该驱动程序的设备文件一般是/dev/fb0/dev/fb1等。对用户而言,它和/dev下的其他设备没有什么区别,用户可以把framebuffer看成一块内存,既可以从这块内存中读取数据,也可以向其中写入数据,而写操作立即反应在屏幕上。为运行Qt/Embedded,嵌入式Linux内核要支持framebuffer

Qt/EmbeddedQt的面向嵌入式应用的简化版本,它包括一组完备的GUI类、操作系统封装、数据结构类、功能类和组合类。大部分Qt的应用程序可以经过简单的编译与重设窗口大小移植到Qt/Embedded

Qtopia是基于QT/Embedded开发的一个嵌入式的窗口系统和应用程序集,如地址本、图像浏览、Media播放器等,还包括娱乐和配置工具,广泛用于PDA等掌上设备。 Qtopia平台由Qtopia (Qt/E,libqpe,libqtopia1,qtopiapim)Qtopia server/laucher组成。Qtopia server/laucher是控制窗口系统、进程间通信、发起所有应用和其他核心任务的主要服务程序。

(2) Qt/EmbeddedQtopia的交叉编译与运行

整个GUI系统的构建需要对Qt/EmbeddedQtopia依次分别编链,然后有机地整合在一起。Qt/EmbeddedQtopia提供了底层支持,GUI系统的图形库窗口组建都由Qt/Embedded实现。

在构建GUI时用于Qt开发的典型工具如下:

l         tmake跨平台的Makefile生成器。

l         moc:用于Qt C++扩展的metra-object编译器。

l         uicXML文件生成代码的用户界面编译器。

l         designer:用于设计窗口组建的应用程序。

Qtopia的开发工具包SDKSoftware Development Kit)是Qtopia开发环境的核心部分,编译后得到创建应用程序所需的软件包如下:

l         qvfb(virtual frame buffer)X窗口用来运行和测试Qtopia应用程序的系统程序。

l         qpe(Qtopia executable):用来处理所有的用户程序界面[2,5]

由于我们使用的是ARM CPU,因此需要对Qt/EmbeddedQtopia开发工具包进行交叉编译。本文使用arm-linux-gcc-3.3.2来建立交叉编译环境。为了对Qt/EmbeddedQtopia进行交叉编译,需要使用如下的源码树:

l         tmake-1.13.tar.gz:用来得到tmake工具。

l         qt-embedded-2.3.7.tar.gzQt的嵌入式版本。

l         qt-x11-2.3.2.tar.gzQtX11版本。

l         qtopia-free-1.7.0.tar.gz:官方网站提供的Qtopia免费版。

l         e2fsprogs-1.38.tar.gz:为了得到qtopia所需的uuid.hlibuuid.so

假设将上述源码树放在同一目录下,例如:/root/qtopia,并依次解压,然后进行编译,步骤如下:

设定tmake的环境变量如下:

export TMAKEPATH=/root/qtopia/tmake-1.13/lib/qws/linux-arm-g++

此处指定了tmake在生成Makefile时使用arm交叉编译。

编译qt-x11,其目的是生成mocuicqvfbdesigner,并将它们放在qt-embedded/bin目录下。

配置qt-embedded编译选项,命令为:

./configure -platform linux-arm-g++  -qconfig qpe -qvfb -depths 4,8,16,32.

此处-platform linux-arm-g++表示在arm平台上进行交叉编译;-qconfig local表示使用src/tools/qconfig-local.h-depths 4,8,16,32表示需要qt支持的显示颜色深度。

④使用make命令编译qt-embedded,用来生成Qt(libqte.so)

⑤配置并交叉编译Qtopia,生成应用程序以及桌面环境。

假设编译完成后将qtqtopia相关的库及所需文件分别存放于目标板文件系统的/opt/qt/opt/qtopia下,运行Qtopia的方法是:

设置QTDIRQPEDIR和键盘鼠标等环境变量

  export QTDIR=/opt/qt

  export QPEDIR=/opt/qtopia

export QWS_KEYBOARD=USB:/dev/input/event1

export QWS_MOUSE_PROTO=USB:/dev/input/mouse0

开启qpe,也就是在Linux图形模式下执行/opt/qtopia/bin/qpe &

这样就可以在显示终端上看到qtopia桌面环境了。

4 Qt/EmbeddedQtopia下应用程序的实现

(1) Qt/Embedded应用程序的实现

Qt是一个创建GUI程序的C++类库,编写Qt应用程序的主要工作是基于已有的Qt类编写用户类。Qt应用程序的设计使用基于工程的方法,并通过.pro文件进行工程管理。实现应用程序的第一步是编写.pro文件,然后使用tmake根据该文件生成Makefile,最后进行源代码的编写。tmake的语法如下:

tmake *.pro –o Makefile

.pro的具体内容可以参考/qt/examples/下其他应用程序的.pro文件。

在本项目的研究中,需要涉及基本的窗口构建、应用程序的调用、图像背景的显示以及中文显示,下面对此进行详细阐述。

构建主窗口

    Qt拥有众多的窗口部件,如按钮、菜单、滚动条和应用程序窗口等,它们组合起来可以创建各种用户界面。QWidget 是所有用户界面对象的基类,窗口部件是QWidget或其子类的实例。

创建主窗口先要在main.cpp函数中创建QApplication类型的对象。QApplication类管理图形用户界面应用程序的控制流和主要设置,它包含主事件循环,在其中来自窗口系统和其它资源的所有事件被处理和调度,它也处理应用程序的初始化和结束,并提供对话管理。对于任何一个使用Qt图形用户界面应用程序,都正好存在一个QApplication对象。然后定义主窗口变量,并通过QApplication类型的函数调用主窗口变量来启动主窗口。

创建主窗口部件最常用的方法是基于QWidgetQDialog类创建一个用户类。QDialog类是对话框窗口的基类,主要用于短期任务以及和用户进行简要通讯的顶级窗口。在本程序中使用QWidget类创建用户类,并使用户类通过公有继承派生于Qwidget类。

    在构建窗口时需要注意用户界面的风格和布局。Qt提供了WindowsWindowsXPMotifMotifPlusCDEPlatinumSGIMac的内置风格。自定义风格可以通过继承QStyleQCommonStyle或其他QCommenStyle类来完成。应用程序的风格可以如下设置:

    QApplication::setStylenew MyCustomStyle

    在布局上Qt提供了布局管理器来组织父部件区域中的子部件,Qt内建的布局管理器有QHBoxLayoutQVBoxLayoutQGridLayout,而且布局也可以嵌套在任意层。例如使用QHBoxLayout(按行放置部件)的部件管理器为例在窗口水平放置两个按钮B1B2的代码如下:

    QHBoxLayout *hbox = new QHBoxLayout(this);

    Hbox->addWidget(B1);

Hbox->addWidget(B2);

 

创建按钮实现对应用程序的调用

    Qt部件与用户的交互方式不同于其他的GUI工具包,其他的GUI工具包使用回调函数创建用户交互,但是Qt提供了信号/(signal/slots)[5]通信机制描述对象间的无缝通讯。槽(slot)标准的成员函数,它能够连接到信号,每当槽所连接的信号被发射时,槽(函数)就被执行。信号(signal)是一种特殊类型的函数,都是返回void型,它们被定义为当某个事件发生时就被发射,之后执行所有被连接的槽。当定义信号时必须使用QT的宏SIGNAL(),定义槽时必须使用宏SLOT()

通过调用QObject对象的connect函数可以将某个对象的信号与另一个对象的槽相关联,这样当发射对象发射信号时,接收对象的槽将被调用。该函数定义如下:

bool QObject::connectconst QObject *sender,const char *signal,const QObject *receiver,

                         const char *member)

与这个函数对应的disconnect函数,可以将信号和槽断开连接。

   本文使用了QT提供的按钮clicked()信号,自定义了槽函数run()实现对应用程序的调用,并且定义了槽函数mycall()调用已经使用了特定参数的run()函数。

例如当一个按钮B1被点击时,它就发送“clicked”信号,通过connect()函数将信号与槽“mycall”连接起来,调用/opt/qt/examples/clock/下的应用程序“clock”的代码如下:

void MyMainWindow::mycall()

{

MyMainWindow::run(“(cd /opt/qt/examples/clock; exec ./clock;)”);

}

connect(B1,SIGNAL(clicked()),this,SLOT(mycall())); 

 

图像背景的显示

为了在Qt中装载和显示所支持的图像格式,需要创建一个QPixmap对象。QPixmap本质上是一个“屏幕外的部件(off-screen)”,图像可以先复制到一个QPixmap对象上,然后传送到QWidget

QWidget部件使用如下的成员函数来为窗口添加图像背景:

Public Members

const QPixmap* backgroundPixmap () const

virtual void setBackgroundPixmap ( const QPixmap & ) 

例如有一幅名为flower.png的图片,将其设为背景的代码如下:

QPixmap picture(“flower.png”)

SetbackgroundPixmap(picture)

 

中文显示

    Qt的中文显示是Qt国际化的一部分,“国际化”简称为i18n,用来提供一个架构,让同样的代码可以适用于各种语种习惯和编码系统,程序设计人员只要利用这个架构的机制、准则编写应用程序,就可以在不新编译代码的情况下,支持各种语言。

    Qt支持Unicode—国际标准字符集,程序员可以在程序里自由的混用英语、汉语和其他Unicode所支持的语言。为Qt增加一种编码只需要增加该编码和Unicode的转化编码就可以了,Qt支持中文的GBK/Big5编码。

Qt支持的字体常用的是ttfqpfqpfQt/Embedded专用的一种适合嵌入式应用的字体它属于位图字体不可以缩放,而ttf字体可以缩放默认情况下Qt/Embeddedlib/fonts目录下提供了一种可以显示中文的字体库UniFont,但是该字体库中没有ttf的字体。为了使用ttf字体显示中文,本文采取如下的方法:拷贝一种支持unicode编码的ttf字体到lib/fonts目录下,例如,windows系统下的宋体simsun.ttf;同时还需要在此目录的fontdir本中添加下面一行

simsun simsun.ttf FT n 50 0 su

fontdir脚本用来向系统注册所支持的字体,它的每一行定义了一种字体的设置,其格式如下:

<字体名称><字体文件名><字体渲染类型><是否斜体><尺寸><字体标志>[尺寸列表]

在程序设计中,首先指定编码方式以支持中文:

QTextCodec *code=QTextCodec::codecForName("GBK")

接着为部件(例如Mywidget)执行 Unicode的转化编码

QString uniStr=code -> toUnicode("要显示的中文字符")

Mywidget-> setFont(QFont("simsun",20,QFont::Bold))

Mywidget-> setText(uniStr)

(2) Qtopia移植应用程序

Qtopia是一个基于QT/Embedded开发的一个嵌入式的桌面环境和应用程序集可以方便地在Qtopia桌面环境中添加用户应用程序或者对桌面进行配置。为了添加用户应用程序,需要在Qtopia/apps/Application目录下建立一个.desktop的桌面文件,该文件指明了桌面文件的图标以及应用程序的入口点。应该注意的是为了让新的应用程序在Qtopia桌面环境中运行,应用程序必须使用QT提供的图形库进行编译。

下面以移植嵌入式的web浏览器konqueror为例,说明添加新的应用程序的过程。

(1)下载konqueror源代码,对其进行交叉编译。为了支持中文显示和flash,还需要进行必要的源代码修改,并且加入相应的插件。

(2)konqueror.png图标文件拷贝到在/opt/Qtopia/pic/下。

(3)konqueror可执行文件放于/opt/konqueror/下,然后在Qtopia/apps/Application目录下建立konqueror.desktop文件,具体内容可参考qtopia自带的.desktop文件。需要注意的是konqueror.desktopExec项应指明可执行文件的具体位置。例如:Exec=/opt/konqueror/bin/konqueror

(4)导出konqueror的运行环境变量,就可以直接在桌面上点击其图标浏览网页了。

5 结束语

嵌入式产品的广泛应用带动了图形用户界面(GUI)的迅速发展,嵌入式系统需要一个高性能、高可靠的GUI的支持。基于Qt/EmbeddedQtopia桌面系统为系统用户提供了良好的使用和交互环境。本文系统介绍了基于Qt/Embedded开发应用程序的方法以及将现有的应用程序移植进Qtopia的具体过程,为类似的系统开发供了一个参考。

 

 

参考文献

[1] 丁丁,习勇,魏急波,三种主流嵌入式图形用户界面的移植及性能比较,《电子产品世界》,2004,9(5):73-74

[2] QT 3.3白皮书,http://www.trolltech.com

[3] 袁鹏飞,24小时学通qt编程,北京:人民邮电出版社,2000/11

[4] 于明俭,陈向阳,方汉, LINUX程序设计权威指南,北京:机械工业出版社,2001/4

[5] 张娟,张雪兰,基于嵌入式的GUI应用程序的实现,《计算机应用》,2003,23(4):115-117

作者简介:王丽洁(1981-),女,硕士研究生,研究方向为嵌入式系统的开发与应用。

作者联系方式:410073,湖南长沙国防科大四院2系,0731457575213873163041lilywang_04601@163.com

 
【01、Go与VSCode的安装】 小白学Go语言 阅读详情

相关推荐

AFSim2.9.0学习笔记 —— 2、AFSim的Wizard软件概述(ArkSIM集成开发环境 (IDE))

AFSim2.9.0学习笔记 —— 2、AFSim的Wizard软件详述(ArkSIM集成开发环境 (IDE))

859

基于Qt/EmbeddedQtopiaGUI设计

基于Qt/EmbeddedQtopiaGUI设计王丽洁,习勇,魏急波(国防科技大学 电子科学与工程学院 湖南省 长沙市 410073)摘要:介绍了Qt/EmbeddedQtopia的体系结构及其交叉编译过程与安装过程,重点讲述了如何实现Qt/Embedded下的应用程序以及如何将应用程序移植到Qtopia桌面系统。本文介绍的方法在笔者的开发平台上都做过验证。关键词:嵌入式系统

lideming的专栏 1801

GSM手机测试参数测试内容.pdf

GSM手机测试参数测试内容.pdf

测试Qtopia应用程序的系统程序

  基于Qt/EmbeddedQtopiaGUI设计王丽洁,习勇,魏急波(国防科技大学 电子科学与工程学院 湖南省 长沙市 410073)摘要:介绍了Qt/EmbeddedQtopia的体系结构及其交叉编译过程与安装过程,重点讲述了如何实现Qt/Embedded下的应用程序以及如何将应用程序移植到Qtopia桌面系统。本文介绍的方法在笔者的开发平台上都做过验证。关键词:嵌入式系统

lideming的专栏 1005

QObject::connect 出错

在使用QObject::connect时在SLOT那里默认了给槽函数加上了QObject::: 解决方法,在.h文件上加上Q_OBJECT然后找到工程目录路径,删除了文件夹。objmake有关文件

lishaoqi_scau的专栏 796

第二次 的面试题目 (自闭!!)

qt 调试时遇见过的报错信息。 在linux上使用过gdb吗? 怎么使用。 什么情况下使用线程池内存池。怎么实现的。 怎么使用git管理代码。 c++ 多态 虚函数 static函数参数的使用。 多个类怎么使用一个变量 linux怎么单次永久改ip 使用什么命令查找复制指定目录定位.so文件。 重点看下如下问题: 1、qt线程中怎样处理修改界面? 2、TCP与UDP的区别? 3、UDP传输时,数据过大会不会拆包? 4、说说QT创建线程有几种方法,分别说说。 5、说说c++的3个特性。 6.

she666666的博客 1739

Q_OBJECT宏的作用

Q_OBJECT宏的作用  The Q_OBJECT macro at the beginning of the class definition is necessary for all classes that define signals

dongliqiang2006的专栏 1466

基于Qt/EmbeddedQtopiaGUI设计(转)

导读:   1 引言   随着当前各种手持设备、无线设备及信息家电等嵌入式产品的迅猛发展,相应的嵌入式软硬件设计技术也在发生深刻的变化。如今,越来越多的嵌入式终端需要一个图形化的人机接口界面(GUI),良好的人机接口界面是嵌入式系统设计的一个关键技术,能够极大地提高人机交互的效率。本文详细阐述了在自行开发的嵌入式主板上实现某平台的图形显示终端过程。   2 系统平台介绍   根据系统设计

zozowit的专栏 1149

test

  基于Qt/EmbeddedQtopiaGUI设计王丽洁,习勇,魏急波(国防科技大学 电子科学与工程学院 湖南省 长沙市 410073)摘要:介绍了Qt/EmbeddedQtopia的体系结构及其交叉编译过程与安装过程,重点讲述了如何实现Qt/Embedded下的应用程序以及如何将应用程序移植到Qtopia桌面系统。本文介绍的方法在笔者的开发平台上都做过验证。关键词:嵌入式系统

lideming的专栏 940

Qt5.9中QObject::connect()函数用法(函数使用的前提条件参数详解)

本文章主要总结Qt5.9中QObject::connect()函数的用法,全文分为两大部分,第一部分讲解connect函数使用的前提条件,第二部分讲解connect函数各个参数详解具体的用法实例。 一、首先需要注意的是,connect()函数有且只能在QObject类里面QObject派生类里面使用,自己新建的类里面(基类不是QObject类其QObject派生类)使用connect()函数是无效的,编译时一直报错。当然,我们新建工程比如widget,mainwindow,dialog都是QO.

周杰伦 1094

QObject::connect连接方式

QT信号槽 方式一:Qt4连接方式 信号发送者,信号,信号接受者,处理函数 方式二:Qt5连接方式 绑定信号或者槽函数 方式三:Qt5 Lambda表达式

lankyysina的博客 1223

Qt/Embedded简介

from http://hi.baidu.com/shlongli/blog/item/7fb5830f1b7c9be8ab6457c2.html1、 Qt/Embedded体系结构 Qt/Embedded是基于Qt嵌入式GUI应用程序开发的工具包,它可运行多种嵌入式设备上,主要运行在嵌入式Linux系统上,并且需要C++编译器的支持,并为嵌入式应用程序提供Qt的标准API。 Qt/Emb

hh2000的专栏 2865

Qt/Embedded编译与安装

本文介绍了Qt/Embedded的编译与安装的详细详细过程,包括简要介绍了Qt/Embedded的安装的前期准备——交叉编译链的安装,tslib 的编译与安装。对Qt/Embedded的./configure 配置的常用参数进行了说明。

KwanSampson的专栏 1万+

Qt Embedded之一:简介与平台插件介绍

嵌入式 Linux 发行版上的 Qt 属于 QtEmbedded Linux 分支平台(本文简称为 Qt/E)。Qt/E 在原始 Qt 的基础上,做了许多出色的调整以适合嵌入式环境。同桌面版的 Qt/X11 相比,嵌入式Qt/E 很节省内存,因为它不需要 X server 或是 Xlib 库,它在底层摒弃了 Xlib,采用 Framebuffer(帧缓冲)作为底层图形接口。Qt/E 的应用程序可以直接写内核帧缓冲,这避免开发者使用繁琐的 Xlib/Server 系统。

szembed的博客 1832

QT QT/Embeded 介绍

在公司折腾了3个月,我的工作内容终于确定下来了。Linux 嵌入式QT embeded,偏上层。         我不知道在别的公司怎么样,我现在在的这个公司,喜欢把人当全才。其实也不是不好,但是我个人更喜欢,先专再泛,还好的是这个在这个公司不会很累,所以我也有时间弄弄自己感兴趣的东西。我所感兴趣的是,Linux 嵌入式,偏底层。         大四时才知道QT,(参加工作后觉得自己在大学

HappyJandun's 学习笔录 2072
上一篇: 基于Qt/Embedded和Qtopia的GUI设计
下一篇: 行和测试Qtopia应用程序的系统程序
lideming
博客等级 码龄20年 0粉丝 3原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值