重庆大学2023实训试题参考

1:QtWidgets类在QT程序开发中的作用?

QtWidgets类是Qt框架中的一个重要类,用于创建和管理图形用户界面(GUI)。它提供了各种用于创建窗口、按钮、标签、文本框等常见GUI元素的类和函数。

QtWidgets类提供了丰富的功能和工具,使开发者能够轻松地创建交互式和可视化的应用程序。它具有跨平台的特性,可以在多个操作系统上运行,包括Windows、Mac和Linux。

通过使用QtWidgets类,开发者可以实现以下功能:

  1. 创建窗口和对话框:可以使用QtWidgets类创建主窗口、子窗口和对话框,并设置它们的属性和样式。
  1. 添加控件和布局:可以使用QtWidgets类添加各种控件,如按钮、标签、文本框、下拉列表等,并使用布局管理器来管理它们的位置和大小。
  1. 响应用户交互:可以使用QtWidgets类中的信号和槽机制来响应用户的操作,例如按钮点击、文本框输入等。
  1. 绘制和绘图:可以使用QtWidgets类进行绘图操作,包括绘制图形、绘制文本、绘制图像等。
  1. 处理用户输入:可以使用QtWidgets类处理用户的键盘输入、鼠标事件等。

总之,QtWidgets类是Qt框架中用于创建和管理GUI的核心类之一。它提供了丰富的功能和工具,使开发者能够轻松地构建各种交互式和可视化的应用程序。

2:QtDesigner在QT程序开发中的作用

Qt Designer是Qt框架中的一个可视化界面设计工具,用于创建和编辑Qt应用程序的用户界面。它提供了一个直观的图形界面,使开发者能够以可视化的方式设计和布局GUI元素,而无需手动编写代码。

Qt Designer的主要作用如下:

  1. 可视化设计:Qt Designer允许开发者通过拖放和调整控件来设计用户界面。开发者可以从工具箱中选择各种预定义的控件,如按钮、标签、文本框等,并将它们放置在窗口上。通过直观的界面操作,开发者可以快速创建和布局GUI元素。
  1. 属性编辑:Qt Designer提供了一个属性编辑器,用于设置控件的属性和样式。开发者可以轻松地修改控件的大小、位置、颜色、字体等属性,以满足特定的设计需求。
  1. 信号和槽连接:Qt Designer允许开发者通过简单的拖放操作来连接控件的信号和槽。开发者可以选择控件的信号,然后将其连接到其他控件的槽函数,以实现交互和响应用户操作。
  1. 自定义控件:Qt Designer支持自定义控件的创建和编辑。开发者可以使用自定义的控件库,或者创建自己的控件,并在Qt Designer中进行可视化编辑和布局。
  1. 代码生成:Qt Designer可以将设计好的用户界面转换为相应的代码。开发者可以将设计好的界面保存为.ui文件,并使用Qt的代码生成工具将其转换为可执行的C++代码,以便在应用程序中使用。

总之,Qt Designer是一个强大的可视化界面设计工具,它简化了Qt应用程序的用户界面设计过程。通过使用Qt Designer,开发者可以以可视化的方式创建和编辑GUI,提高开发效率并实现更好的用户体验。

3setGeometry方法的参数作用

setGeometryQt框架中QWidget类的一个成员函数,用于设置窗口或控件的位置和大小。

setGeometry函数的参数作用如下:

  1. x:指定窗口或控件的左上角在父窗口坐标系中的x坐标。
  1. y:指定窗口或控件的左上角在父窗口坐标系中的y坐标。
  1. width:指定窗口或控件的宽度。
  1. height:指定窗口或控件的高度。

通过调用setGeometry函数并传递适当的参数,可以将窗口或控件放置在指定的位置,并设置其大小。

例如,以下代码将一个窗口放置在父窗口的(100, 100)坐标处,并设置宽度为200,高度为150

QWidget *window = new QWidget(parent);

window->setGeometry(100, 100, 200, 150);

这将使窗口在父窗口的(100, 100)位置处显示,并具有200x150的大小。

请注意,坐标和大小参数是相对于父窗口的坐标系的。如果没有指定父窗口,则相对于屏幕的坐标系。

4信号和槽的程序开发流程

Qt框架中,信号和槽是一种用于实现对象间通信的机制。通过信号和槽,一个对象可以发出信号,而其他对象可以连接到该信号并在接收到信号时执行相应的槽函数。

以下是使用信号和槽的程序开发流程:

  1. 定义信号和槽函数:在需要发出信号的类中,定义一个信号函数,并在需要接收信号的类中,定义一个槽函数。信号函数和槽函数可以是任意的成员函数,但需要遵循特定的语法规则。
  1. 发出信号:在发出信号的对象中,通过调用信号函数来发出信号。可以在适当的时机调用信号函数,例如在按钮点击、数据更新等事件发生时。
  1. 连接信号和槽:在接收信号的对象中,使用connect函数将信号与槽函数连接起来。connect函数的参数包括发出信号的对象、信号函数的指针、接收信号的对象、槽函数的指针等。
  1. 处理信号:当发出信号的对象调用信号函数时,与之连接的槽函数将被自动调用。在槽函数中,可以执行相应的操作,例如更新界面、处理数据等。

以下是一个简单的示例代码,演示了信号和槽的使用:

class Sender : public QObject

{

    Q_OBJECT

public:

    // 定义一个信号函数

    void sendSignal()

    {

        emit mySignal();

    }

signals:

    // 声明一个信号

    void mySignal();

};

class Receiver : public QObject

{

    Q_OBJECT

public slots:

    // 定义一个槽函数

    void handleSignal()

    {

        qDebug() << "Signal received!";

    }

};

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

{

    QApplication app(argc, argv);

    Sender sender;

    Receiver receiver;

    // 连接信号和槽

    QObject::connect(&sender, &Sender::mySignal, &receiver, &Receiver::handleSignal);

    // 发出信号

    sender.sendSignal();

    return app.exec();

}

在上述示例中,Sender类定义了一个信号函数sendSignal,并在需要发出信号时调用该函数。Receiver类定义了一个槽函数handleSignal,用于接收信号并执行相应的操作。在main函数中,通过connect函数将Sender类的信号与Receiver类的槽函数连接起来。当sender对象发出信号时,与之连接的receiver对象的槽函数将被调用。

可以使用lambda表达式来替代上述的connect函数。使用lambda表达式可以更简洁地定义信号和槽的连接。

以下是使用lambda表达式替代connect函数的示例代码:

QObject::connect(&sender, &Sender::mySignal, &receiver, [&]() {

    qDebug() << "Signal received!";

});

在上述示例中,使用lambda表达式[&]() { qDebug() << "Signal received!"; }来定义槽函数。lambda表达式中的代码将在接收到信号时执行。

请注意,lambda表达式中的&表示捕获外部变量,这里使用&捕获所有外部变量。如果需要捕获特定的外部变量,可以在[]中指定。

使用lambda表达式可以更简洁地定义信号和槽的连接,并且可以在连接的同时编写槽函数的实现代码。

5类的构造函数的执行顺序

C++中,类的构造函数的执行顺序是按照成员变量在类中的声明顺序来确定的。具体来说,构造函数会按照以下顺序执行:

  1. 基类构造函数:如果类是派生类,那么首先会执行基类的构造函数。基类的构造函数会在派生类构造函数的初始化列表中调用。
  1. 成员变量构造函数:在执行派生类构造函数的初始化列表时,会按照成员变量在类中的声明顺序调用它们的构造函数。成员变量的构造函数会在派生类构造函数体之前执行。
  1. 派生类构造函数体:最后,执行派生类构造函数的函数体中的代码。

以下是一个示例代码,演示了类构造函数的执行顺序:

class Base {

public:

    Base() {

        cout << "Base constructor" << endl;

    }

};



class Member {

public:

    Member() {

        cout << "Member constructor" << endl;

    }

};



class Derived : public Base {

public:

    Derived() : member(), Base() {

        cout << "Derived constructor" << endl;

    }



private:

    Member member;

};



int main() {

    Derived derived;

    return 0;

}

在上述示例中,Derived类继承自Base类,并包含一个Member类的成员变量。当创建Derived类的对象时,构造函数的执行顺序是先执行基类构造函数(Base),然后执行成员变量构造函数(Member),最后执行派生类构造函数(Derived)。

输出结果为:

Base constructor

Member constructor

Derived constructor

这个输出结果反映了类构造函数的执行顺序。

先构造基类,再构造子类,最后构造自己,先父亲后儿子,最后才是自己

7、c++中的处理时间event的触发条件

C++中,处理事件的触发条件取决于所使用的框架或库。以下是一些常见的C++框架和库中处理事件的触发条件的示例:

  1. Qt框架:在Qt框架中,事件处理是通过事件循环(event loop)来实现的。事件循环会不断地从操作系统接收事件,并将其分发给相应的对象进行处理。事件的触发条件包括但不限于:用户交互(例如鼠标点击、键盘输入)、定时器事件、网络事件等。

8、了解QWidget类、QFrame类和QGraphicsView类的层次关系

Qt框架中,QWidget类、QFrame类和QGraphicsView类是三个常用的类,它们之间存在层次关系。下面是它们之间的层次关系的简要说明:

  1. QWidget类:QWidget是Qt中所有用户界面类的基类。它提供了一个基本的窗口部件,可以用于创建应用程序的主窗口或其他窗口部件。QWidget类提供了一些基本的功能,如绘制、布局管理、事件处理等。其他的窗口部件类,如QPushButton、QLineEdit等,都是QWidget的子类。
  1. QFrame类:QFrame是QWidget的子类,它是一个可见的矩形框架部件。QFrame类提供了一些额外的功能,如边框样式、背景色、阴影效果等。它可以用于创建具有特定样式和外观的窗口部件,如QGroupBox、QToolBar等。
  1. QGraphicsView类:QGraphicsView是一个用于显示和编辑2D图形场景的部件。它提供了一个可视化的视图,可以在其中显示QGraphicsScene中的图形项。QGraphicsView类提供了一些功能,如缩放、平移、旋转等,以及与图形项的交互,如选择、移动、编辑等。

总结起来,QWidget类是Qt中所有用户界面类的基类,QFrame类是QWidget的子类,提供了一些额外的框架样式和外观功能,而QGraphicsView类是用于显示和编辑2D图形场景的部件,提供了与图形项的交互功能。

9、了解布局管理器Layout的功能

布局管理器(Layout)是Qt框架中用于管理窗口部件位置和大小的机制。布局管理器可以自动调整窗口部件的位置和大小,以适应不同的窗口大小和布局需求。以下是布局管理器的一些功能:

  1. 自动调整大小和位置:布局管理器可以根据窗口的大小自动调整窗口部件的大小和位置,以适应不同的窗口尺寸。这样可以确保窗口部件在不同的屏幕分辨率或窗口大小下都能正确显示。
  1. 灵活的布局:布局管理器提供了不同的布局选项,如水平布局(QHBoxLayout)、垂直布局(QVBoxLayout)、网格布局(QGridLayout)等。这些布局选项可以根据需要将窗口部件按照一定的规则进行排列,以实现灵活的布局效果。
  1. 自动调整大小策略:布局管理器可以设置窗口部件的自动调整大小策略,以确定窗口部件在布局中的大小调整方式。常见的自动调整大小策略包括固定大小、自动拉伸、保持宽高比等。
  1. 嵌套布局:布局管理器可以嵌套使用,以实现更复杂的布局效果。通过将布局管理器嵌套在其他布局管理器中,可以创建更灵活和复杂的窗口布局。
  1. 动态布局:布局管理器可以在运行时动态地添加、删除或更改窗口部件,而不需要手动调整其位置和大小。这使得在运行时根据需要动态修改窗口布局变得更加方便。

通过使用布局管理器,开发者可以更轻松地实现可伸缩和自适应的用户界面,减少手动调整窗口部件位置和大小的工作量,提高开发效率。

10、了解类的成员函数的类型

C++中,类的成员函数可以分为以下几种类型:

  1. 实例成员函数(Instance Member Function):实例成员函数是类的对象所拥有的函数,它们可以访问和操作对象的成员变量。实例成员函数通过对象来调用,可以访问对象的成员变量和其他成员函数。实例成员函数没有使用static关键字进行声明。
  1. 静态成员函数(Static Member Function):静态成员函数是与类关联而不是与类的对象关联的函数。它们可以在没有类的实例的情况下被调用,通过类名和作用域解析运算符::来调用。静态成员函数不能访问类的非静态成员变量,只能访问类的静态成员变量。
  1. 常量成员函数(Const Member Function):常量成员函数是在成员函数的声明和定义中使用const关键字修饰的函数。常量成员函数承诺不会修改类的成员变量,因此它们可以在常量对象上调用。常量成员函数可以通过对象或常量对象来调用。
  1. 构造函数(Constructor):构造函数是一种特殊的成员函数,用于创建和初始化类的对象。构造函数的名称与类的名称相同,没有返回类型,并且可以有参数。构造函数在创建对象时自动调用,用于初始化对象的成员变量和执行其他必要的操作。
  1. 析构函数(Destructor):析构函数是一种特殊的成员函数,用于在对象销毁时执行清理操作。析构函数的名称与类的名称相同,前面加上波浪号(~),没有返回类型,也没有参数。析构函数在对象销毁时自动调用,用于释放对象占用的资源。

这些是常见的类的成员函数类型。每种类型的成员函数都有其特定的用途和行为,可以根据需要在类中定义和使用

下面是关于前三种成员函数的区分以及相应的代码示例:

  1. 实例成员函数(Instance Member Function):
    • 实例成员函数是类的对象所拥有的函数,通过对象来调用。
    • 实例成员函数可以访问和操作对象的成员变量。
    • 实例成员函数没有使用static关键字进行声明。
class MyClass {

public:

    void instanceFunction() {

        // 实例成员函数可以访问和操作对象的成员变量

        memberVariable = 10;

        // ...

    }



private:

    int memberVariable;

};



int main() {

    MyClass obj;

    obj.instanceFunction(); // 通过对象调用实例成员函数

    return 0;

}



  1. 静态成员函数(Static Member Function):
    • 静态成员函数是与类关联而不是与类的对象关联的函数,通过类名和作用域解析运算符::来调用。
    • 静态成员函数不能访问类的非静态成员变量,只能访问类的静态成员变量。
class MyClass {

public:

    static void staticFunction() {

        // 静态成员函数可以访问类的静态成员变量

        staticVariable = 20;

        // ...

    }



private:

    static int staticVariable;

};



int MyClass::staticVariable = 0; // 静态成员变量的定义和初始化



int main() {

    MyClass::staticFunction(); // 通过类名调用静态成员函数

    return 0;

}



  1. 常量成员函数(Const Member Function):
    • 常量成员函数是在成员函数的声明和定义中使用const关键字修饰的函数。
    • 常量成员函数承诺不会修改类的成员变量,因此可以在常量对象上调用。
    • 常量成员函数可以通过对象或常量对象来调用。
class MyClass {

public:

    void normalFunction() {

        // ...

    }



    void constFunction() const {

        // 常量成员函数不能修改类的成员变量

        // 只能访问和调用其他常量成员函数

        // normalFunction(); // 错误,常量成员函数不能调用非常量成员函数

        // memberVariable = 30; // 错误,常量成员函数不能修改成员变量

        // ...

    }



private:

    int memberVariable;

};



int main() {

    MyClass obj1;

    obj1.normalFunction(); // 通过对象调用普通成员函数



    const MyClass obj2;

    obj2.constFunction(); // 通过常量对象调用常量成员函数



    return 0;

}

通过以上示例,您可以看到实例成员函数通过对象调用,可以访问和操作对象的成员变量;静态成员函数通过类名调用,只能访问类的静态成员变量;常量成员函数通过对象或常量对象调用,承诺不会修改类的成员变量。

10、理解makefile文件的作用

Makefile文件是一种用于自动化构建和管理软件项目的文件。它包含了一系列规则和指令,用于描述项目中的源代码文件、依赖关系以及如何编译、链接和构建可执行文件或库。

Makefile文件的主要作用包括:

  1. 自动化构建:Makefile文件定义了项目的构建规则,包括编译源代码、链接目标文件、生成可执行文件或库等。通过执行Makefile文件,可以自动化执行这些构建步骤,减少手动操作的工作量。
  1. 依赖管理:Makefile文件中可以指定源代码文件之间的依赖关系。当某个源代码文件发生变化时,Makefile可以根据依赖关系自动判断需要重新编译哪些文件,以及重新链接生成最终的可执行文件或库。
  1. 增量构建:Makefile文件可以记录每个文件的编译状态和时间戳信息。通过比较源代码文件和目标文件的时间戳,Makefile可以判断哪些文件需要重新编译,从而实现增量构建,提高构建效率。
  1. 并行构建:Makefile文件可以指定并行构建的规则,充分利用多核处理器的能力,加快构建速度。
  1. 管理编译选项:Makefile文件可以定义编译器和链接器的选项,如编译标志、库路径、库依赖等。通过Makefile文件,可以统一管理项目中的编译选项,确保编译的一致性。
  1. 管理项目结构:Makefile文件可以定义项目的目录结构和文件组织方式,使得项目的结构清晰可见,方便管理和维护。

总之,Makefile文件是一个重要的构建工具,它可以自动化构建和管理软件项目,提高开发效率和代码质量。

11、掌握创建 qt widgets application项目的步骤

创建Qt Widgets Application项目的步骤如下:

  1. 打开Qt Creator:启动Qt Creator集成开发环境。
  1. 创建新项目:点击Qt Creator的"File"菜单,选择"New File or Project"选项。
  1. 选择项目模板:在弹出的对话框中,选择"Qt Widgets Application"模板,并点击"Choose"按钮。
  1. 设置项目信息:在下一个对话框中,输入项目的名称和路径,然后点击"Next"按钮。
  1. 配置项目:在此步骤中,您可以选择项目的构建目标(例如Desktop Kit),选择Qt版本,以及其他项目配置选项。根据您的需求进行选择,并点击"Next"按钮。
  1. 设计界面:在此步骤中,您可以使用Qt Designer工具来设计应用程序的界面。您可以添加窗口部件、布局和其他UI元素,并设置它们的属性和信号槽连接。完成界面设计后,点击"Next"按钮。
  1. 选择类:在此步骤中,您可以选择要创建的类的类型。您可以选择创建一个主窗口类,或者添加其他自定义类。根据您的需求进行选择,并点击"Next"按钮。
  1. 完成项目创建:在最后一个对话框中,确认项目的设置和配置,并点击"Finish"按钮。
  1. 构建和运行:Qt Creator将自动为您生成项目的初始代码和构建脚本。您可以点击"Build"按钮来构建项目,并点击"Run"按钮来运行应用程序。

通过以上步骤,您可以创建一个Qt Widgets Application项目,并开始开发您的应用程序。

12、掌握弹出消息对话框的程序编写

#include <QApplication>

#include <QMessageBox>



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

{

    QApplication app(argc, argv);



    // 创建一个消息对话框

    QMessageBox messageBox;

    messageBox.setWindowTitle("消息"); // 设置对话框标题

    messageBox.setText("你好,世界!"); // 设置对话框文本

    messageBox.setIcon(QMessageBox::Information); // 设置对话框图标为信息类型



    // 添加按钮到对话框

    messageBox.addButton("确定", QMessageBox::AcceptRole); // 添加一个确定按钮



    // 显示对话框,并等待用户响应

    messageBox.exec();



    return app.exec();

}

13、掌握QT图形界面的控件类型

QT图形界面提供了多种控件类型,用于创建各种交互式用户界面。以下是一些常见的QT控件类型及其功能的中文回答:

  1. QLabel(标签):用于显示文本或图像。
  1. QPushButton(按钮):用于触发操作或执行特定功能。
  1. QLineEdit(文本输入框):用于接收用户输入的单行文本。
  1. QTextEdit(文本编辑框):用于接收用户输入的多行文本。
  1. QRadioButton(单选按钮):用于从一组选项中选择一个。
  1. QCheckBox(复选框):用于从一组选项中选择多个。
  1. QComboBox(下拉框):用于从预定义的选项中选择一个。
  1. QSlider(滑动条):用于在一个范围内选择一个值。
  1. QProgressBar(进度条):用于显示操作的进度。
  1. QSpinBox(数字输入框):用于接收用户输入的整数值。
  1. QCalendarWidget(日历控件):用于选择日期。
  1. QTableView(表格视图):用于显示和编辑表格数据。
  1. QListView(列表视图):用于显示列表数据。
  1. QTreeWidget(树形视图):用于显示层次结构数据。
  1. QTabWidget(选项卡控件):用于显示多个选项卡页面。

这些只是一些常见的QT控件类型,QT还提供了许多其他控件类型和自定义控件的功能。您可以根据您的需求选择适当的控件类型来创建您的图形界面。

14、理解Qt定时器的作用和定时器类

Qt定时器是一种机制,用于在特定时间间隔内触发事件或执行代码。它可以用于实现定时任务、周期性更新界面、处理周期性事件等。

Qt中,定时器类是QTimerQTimer类提供了一种简单的方式来创建和管理定时器。它可以在指定的时间间隔内触发一个信号,或者执行一个特定的槽函数。

使用Qt定时器的一般步骤如下:

  1. 创建一个QTimer对象。
  1. 设置定时器的时间间隔,即触发信号或执行槽函数的时间间隔。
  1. 连接定时器的信号(timeout()信号)到相应的槽函数。
  1. 启动定时器,使其开始计时。
  1. 在槽函数中编写需要定时执行的代码。

以下是一个示例代码,演示了如何使用Qt定时器:

include <QApplication>

#include <QTimer>

#include <QDebug>



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

{

    QApplication app(argc, argv);



    // 创建定时器对象

    QTimer timer;



    // 设置定时器的时间间隔为1秒

    timer.setInterval(1000);



    // 连接定时器的timeout()信号到槽函数

    QObject::connect(&timer, &QTimer::timeout, [&]() {

        qDebug() << "定时器触发";

    });



    // 启动定时器

    timer.start();



    // 运行应用程序

    return app.exec();

}

在这个示例中,我们创建了一个QTimer对象,并设置了时间间隔为1秒。然后,我们将定时器的timeout()信号连接到一个槽函数,该槽函数在定时器触发时输出一条调试信息。最后,我们启动定时器,使其开始计时。

15、掌握求和函数的递归定义程序编写

以下是一个递归定义的求和函数的示例代码:

def recursive_sum(n):
    if n == 0:
        return 0
    else:
        return n + recursive_sum(n-1)

# 测试递归求和函数
print(recursive_sum(5))  # 输出:15


在这个示例中,recursive_sum函数使用递归的方式计算从1n的所有整数的和。当n等于0时,递归终止,返回0。否则,函数将nrecursive_sum(n-1)的结果相加,实现递归求和的过程。

通过调用recursive_sum函数并传入一个整数参数,我们可以测试该递归求和函数的功能。在示例中,我们计算从15的整数的和,并将结果打印输出。

16、掌握动态添加和显示控件的程序编写

动态添加和显示控件是在运行时根据需要创建和显示控件的过程。在Qt中,可以使用布局管理器和信号槽机制来实现动态添加和显示控件的功能。

以下是一个示例代码,演示了如何动态添加和显示QPushButton控件:

#include <QApplication>

#include <QWidget>

#include <QPushButton>

#include <QVBoxLayout>



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

{

    QApplication app(argc, argv);



    // 创建一个QWidget作为主窗口

    QWidget window;



    // 创建一个垂直布局管理器

    QVBoxLayout layout;



    // 创建一个QPushButton控件

    QPushButton *button = new QPushButton("Click me");



    // 将QPushButton控件添加到布局管理器中

    layout.addWidget(button);



    // 设置主窗口的布局管理器

    window.setLayout(&layout);



    // 显示主窗口

    window.show();



    // 运行应用程序

    return app.exec();

}

在这个示例中,我们创建了一个QWidget作为主窗口,并创建了一个垂直布局管理器。然后,我们创建了一个QPushButton控件,并将其添加到布局管理器中。最后,我们将布局管理器设置为主窗口的布局,并显示主窗口。

通过这种方式,我们可以在运行时动态地添加和显示控件。您可以根据需要创建多个控件,并将它们添加到布局管理器中,以实现动态添加和显示的效果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值