Qt可视化界面编译与调用

        上一章我们实现了简易加法器,通过Qt Designer设计界面,然后通过信号与槽完成了“计算”功能。这一章我们来研究下使用Qt Designer设计的界面是如何被Qt Creator编译,又如何被主程序所调用的。

        我们看下上一章使用Qt Designer设计的界面是什么样的:

4211c916e05e4666876c414e44d7f02f.png

        从这个布局图可以看出,这个界面里由7个标签、2个数字输入框、1个按钮、1个水平占位符、4个垂直布局器、2个水平布局器和中心控件组成,下面列出界面中所有的控件及其名称:

        7个标签为:“简易加法器”label_6、“加数1”label_1、“加数2”label_2、“结果”label_3、“+”label_4、“=”label_5、存放结果的标签(带边框)resultLabel;

        2个数字输入框:加数1数字输入框add1SpinBox、加数2数字输入框add2SpinBox;

        1个按钮:“计算”按钮calculatePushButton;

        1个水平占位符:图中在计算按钮左侧的蓝色像弹簧的长条horizontalSpacer;

        4个垂直布局器:加数1垂直布局器verticalLayout_1、加数2垂直布局器verticalLayout_2、结果垂直布局器verticalLayout_3,还有个别忘了,用于整个界面垂直布局的布局器verticalLayout_4;

        2个水平布局器:用于输入数字和结果的那一行的水平布局器horizontalLayout_1、用于水平占位符和计算按钮那一行的水平布局器horizontalLayout_2;

        中心控件:界面中用于盛放所有控件的中心控件centralwidget。

        我们想研究Qt Creator是如何将这些控件编译成代码的,在这之前,我们先看看Qt C++的应用是如何启动的,窗口是如何运行起来的。我们先看下Qt C++应用的入口函数main()函数所在的main.cpp中的代码:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

         main.cpp中的代码很简单,只有短短几行,先是包含了2个头文件,一个是主窗口MainWindow类的头文件"mainwindow.h",一个是Qt的应用头文件<QApplication>。

        接下来就是Qt C++程序的入口函数main()函数,在main()函数中,只有4行代码,第一行定义了一个QApplication类的对象a,并在构造函数中传入了main()函数的实参;第二行定义了一个主窗口类MainWindow的对象w;第三行执行了w的show()函数,作用是将主窗口显示在屏幕上;第四行main()函数返回了a.exec(),这句代码的作用是执行QApplication应用程序,将程序的控制权交给了Qt。

        QApplication是Qt核的类,我们不必深究,我们只需要看下MainWindow这个类,以下是mainwindow.cpp中的代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_calculatePushButton_clicked()
{
    // 获取加数1的值
    int add1 = ui->add1SpinBox->value();
    // 获取加数2的值
    int add2 = ui->add2SpinBox->value();
    // 计算和
    int result = add1 + add2;
    // 将计算和显示出来
    ui->resultLabel->setText(QString::number(result));
}

        在mainwindow.cpp代码中,包含了两个头文件,一个是mainwindow.h,是MainWindow类的头文件;一个是ui_mainwindow.h,这个就是界面编译的文件,Qt Creator将界面翻译成代码存放在ui_mainwindow.h头文件中。下面我们看下ui_mainwindow.h中的内容:

/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.14.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/

#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H

#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

QT_BEGIN_NAMESPACE

class Ui_MainWindow
{
public:
    QWidget *centralwidget;
    QVBoxLayout *verticalLayout_4;
    QLabel *label_6;
    QHBoxLayout *horizontalLayout_1;
    QVBoxLayout *verticalLayout_1;
    QLabel *label_1;
    QSpinBox *add1SpinBox;
    QLabel *label_4;
    QVBoxLayout *verticalLayout_2;
    QLabel *label_2;
    QSpinBox *add2SpinBox;
    QLabel *label_5;
    QVBoxLayout *verticalLayout_3;
    QLabel *label_3;
    QLabel *resultLabel;
    QHBoxLayout *horizontalLayout_2;
    QSpacerItem *horizontalSpacer;
    QPushButton *calculatePushButton;

    void setupUi(QMainWindow *MainWindow)
    {
        if (MainWindow->objectName().isEmpty())
            MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
        MainWindow->resize(291, 187);
        centralwidget = new QWidget(MainWindow);
        centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
        verticalLayout_4 = new QVBoxLayout(centralwidget);
        verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
        label_6 = new QLabel(centralwidget);
        label_6->setObjectName(QString::fromUtf8("label_6"));
        QFont font;
        font.setPointSize(12);
        font.setBold(true);
        font.setWeight(75);
        label_6->setFont(font);
        label_6->setAlignment(Qt::AlignCenter);

        verticalLayout_4->addWidget(label_6);

        horizontalLayout_1 = new QHBoxLayout();
        horizontalLayout_1->setObjectName(QString::fromUtf8("horizontalLayout_1"));
        verticalLayout_1 = new QVBoxLayout();
        verticalLayout_1->setObjectName(QString::fromUtf8("verticalLayout_1"));
        label_1 = new QLabel(centralwidget);
        label_1->setObjectName(QString::fromUtf8("label_1"));
        label_1->setAlignment(Qt::AlignCenter);

        verticalLayout_1->addWidget(label_1);

        add1SpinBox = new QSpinBox(centralwidget);
        add1SpinBox->setObjectName(QString::fromUtf8("add1SpinBox"));

        verticalLayout_1->addWidget(add1SpinBox);


        horizontalLayout_1->addLayout(verticalLayout_1);

        label_4 = new QLabel(centralwidget);
        label_4->setObjectName(QString::fromUtf8("label_4"));
        QFont font1;
        font1.setPointSize(16);
        label_4->setFont(font1);
        label_4->setAlignment(Qt::AlignCenter);

        horizontalLayout_1->addWidget(label_4);

        verticalLayout_2 = new QVBoxLayout();
        verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
        label_2 = new QLabel(centralwidget);
        label_2->setObjectName(QString::fromUtf8("label_2"));
        label_2->setAlignment(Qt::AlignCenter);

        verticalLayout_2->addWidget(label_2);

        add2SpinBox = new QSpinBox(centralwidget);
        add2SpinBox->setObjectName(QString::fromUtf8("add2SpinBox"));

        verticalLayout_2->addWidget(add2SpinBox);


        horizontalLayout_1->addLayout(verticalLayout_2);

        label_5 = new QLabel(centralwidget);
        label_5->setObjectName(QString::fromUtf8("label_5"));
        label_5->setFont(font1);
        label_5->setAlignment(Qt::AlignCenter);

        horizontalLayout_1->addWidget(label_5);

        verticalLayout_3 = new QVBoxLayout();
        verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
        label_3 = new QLabel(centralwidget);
        label_3->setObjectName(QString::fromUtf8("label_3"));
        label_3->setAlignment(Qt::AlignCenter);

        verticalLayout_3->addWidget(label_3);

        resultLabel = new QLabel(centralwidget);
        resultLabel->setObjectName(QString::fromUtf8("resultLabel"));
        resultLabel->setFrameShape(QFrame::Box);
        resultLabel->setFrameShadow(QFrame::Sunken);
        resultLabel->setLineWidth(1);
        resultLabel->setMidLineWidth(0);
        resultLabel->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
        resultLabel->setMargin(0);
        resultLabel->setOpenExternalLinks(false);

        verticalLayout_3->addWidget(resultLabel);


        horizontalLayout_1->addLayout(verticalLayout_3);

        horizontalLayout_1->setStretch(0, 10);
        horizontalLayout_1->setStretch(2, 10);
        horizontalLayout_1->setStretch(4, 10);

        verticalLayout_4->addLayout(horizontalLayout_1);

        horizontalLayout_2 = new QHBoxLayout();
        horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2"));
        horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

        horizontalLayout_2->addItem(horizontalSpacer);

        calculatePushButton = new QPushButton(centralwidget);
        calculatePushButton->setObjectName(QString::fromUtf8("calculatePushButton"));

        horizontalLayout_2->addWidget(calculatePushButton);


        verticalLayout_4->addLayout(horizontalLayout_2);

        MainWindow->setCentralWidget(centralwidget);

        retranslateUi(MainWindow);

        QMetaObject::connectSlotsByName(MainWindow);
    } // setupUi

    void retranslateUi(QMainWindow *MainWindow)
    {
        MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "MainWindow", nullptr));
        label_6->setText(QCoreApplication::translate("MainWindow", "\347\256\200\346\230\223\345\212\240\346\263\225\345\231\250", nullptr));
        label_1->setText(QCoreApplication::translate("MainWindow", "\345\212\240\346\225\2601", nullptr));
        label_4->setText(QCoreApplication::translate("MainWindow", "+", nullptr));
        label_2->setText(QCoreApplication::translate("MainWindow", "\345\212\240\346\225\2602", nullptr));
        label_5->setText(QCoreApplication::translate("MainWindow", "=", nullptr));
        label_3->setText(QCoreApplication::translate("MainWindow", "\347\273\223\346\236\234", nullptr));
        resultLabel->setText(QCoreApplication::translate("MainWindow", "0", nullptr));
        calculatePushButton->setText(QCoreApplication::translate("MainWindow", "\350\256\241\347\256\227", nullptr));
    } // retranslateUi

};

namespace Ui {
    class MainWindow: public Ui_MainWindow {};
} // namespace Ui

QT_END_NAMESPACE

#endif // UI_MAINWINDOW_H

        我们看到这个文件的顶部注释,意思是:这个文件由界面文件'mainwindow.ui'生成,被Qt用户接口编译版本5.14.2创建。警告!对这个文件的所有改动都将在编译界面文件时丢失。

        也就是说,这个文件是Qt根据界面自动生成的,用户不需要更改。我们看下这个文件有哪些代码:首先,文件头部包含了所用到的头文件,后定义了一个类Ui_MainWindow,在这个类里,定义了一些公有指针变量,这些变量就是我们上面列举的界面上的控件,名称就是设置的objectName,之后定义了一个公有函数void  setupUi(QMainWindow *MainWindow),在这个函数中实例了各个控件对象,设置了各个控件的属性以及界面的布局,是不是很像我们手动撸的代码,但因为是机器自动生成的,显得有些机械化而已,但作用是一样的。其中有条语句关注一下,是QMetaObject::connectSlotsByName(MainWindow);这条语句的作用是搜索MainWindow界面上的所有控件,将信号与槽函数匹配的信号和槽关联起来,用作名为 void 类名::on_控件名_信号();这种槽函数的声明,使得控件的信号可以直接关联到这样的槽函数中。

        除了setupUi函数外,这个类里还定义了一个void retranslateUi(QMainWindow *MainWindow)函数,这个函数用来设置界面各组件的文字内容属性,如窗口的标题、标签的文字、按钮的文字,将界面上的文字设置的内容独立出来作为一个函数,在设计多语言界面时会被用到。

        在函数的最后,有以下语句:

namespace Ui {
    class MainWindow: public Ui_MainWindow {};

这几条语句定义了命名空间Ui,并定义了一个继承Ui_MainWindow的类MainWindow。这个操作的意义我们等会会讲到。

        接下来我们看看mainwindow.h中的代码:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

private slots:
    void on_calculatePushButton_clicked();
};
#endif // MAINWINDOW_H

        mainwindow.h文件中,先是包含了<QMainWindow>头文件,后声明了命名空间namespace Ui { class MainWindow; },注意,这里的class MainWindow是命名空间Ui中的类,Ui命名空间和其下的MainWindow在ui_mainwindow.h文件中定义,这里只是拿过来显性地声明下,在mainwindow.h文件中定义的MainWindow类中用到。

        我们看下mainwindow.h文件中定义的MainWindow类包含哪些东西,首先,这个类继承自QMainWindow,类的内部有个Q_OBJECT宏定义,在声明信号与槽之前,必须使用宏定义Q_OBJECT。类中声明了构造函数和析构函数,是公有函数。然后定义了一个私有指针变量Ui::MainWindow *ui;我们仔细分析下这个指针变量,ui这个指针变量的类型是Ui::MainWindow,就是ui_mainwindow.h文件中定义的MainWindow,所以这个ui指针变量可以访问到ui_mainwindow.h文件中定义的MainWindow内部的所有的公有变量和函数,即可以通过ui这个指针变量访问到界面上的所有控件。

        ui_mainwindow.h文件中实现界面功能的类是Ui_MainWindow,再定义一个类MainWindow继承Ui_MainWindow,并定义在namespace Ui里,这样Ui::MainWindow与mainwindow.h文件中的类MainWindow同名,但是用namespace区分开来。所以,界面的Ui::MainWindow类与文件mainwindow.h中定义的MainWindow类实际上是两个类,但是Qt的处理让用户感觉不到Ui::MainWindow类的存在,只需要知道在MainWindow类里用ui指针可以访问界面的控件就行了。是不是感觉Qt这样的设计非常的巧妙,行云流水!

        mainwindow.h中MainWindow类的最后部分声明的公有槽函数void on_calculatePushButton_clicked();这个是“计算”按钮calculatePushButton的点击信号clicked链接的槽函数,之所以这个槽函数能够被“计算”按钮的点击信号触发,完全是因为在ui_mainwindow.h文件中Ui_MainWindow类里的一条语句QMetaObject::connectSlotsByName(MainWindow)的作用。

        讲完了mainwindow.h,我们再回过头来看看mainwindow.cpp中的内容。在MainWindow的构造函数中,使用new Ui::MainWindow实例化了ui指针变量,开辟了空间,ui也不再是空指针了。在构造函数中,使用ui->setupUi(this);初始化了界面。在MainWindow的析构函数中,将ui指针释放掉。在mainwindow.cpp中定义了槽函数void on_calculatePushButton_clicked(),实现简易加法器计算功能。

        到此,简易加法器的代码框架我们就讲完了,小伙伴们清晰了吗,如果还不清晰,对着代码看几遍就懂了。

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中怎么用Ui文件 第一步, 制作ui文件。 首先应该用Qt Designer绘制一个自己的界面,并存为myform.ui(这里的myform可以用自己喜欢的名字代替)。 在制作自己的界面文件时要注意以下几个要点: 1、要记住ui文件的名字,因为uic生成的代码会存在ui_myform.h里 2、要记住主窗体的object name, 因为ui文件提供的类名将以这个form的名字来命名 3、要特别注意你的form选择的基类要和你代码中的窗体类兼容 4、要记得给每个后面需要访问到的控件起一个有意义并且好记的object name, 因为ui文件提供的控件将以这些object name来命名 清楚了以上几点,在代码中使用你的ui文件就会变得非常简单。 第二步,将ui文件加入工程 这一步最简单,只需要修改pro文件,加入FORMS+=myform.ui qmake -project命令也可以识别后缀名为ui的文件,并将之加入工程。 第三步,在代码中引用ui文件 官方介绍的使用ui文件的方法有三种,一个是直接引用,二是单继承,三是多继承。 第一种方法其实很不实用,大家去看一下文档中的例子就可以了;第二种和第三种没有本质的差别,可以并作一类,这里做重点介绍。 ui文件最终会被翻译成标准的C++代码,并存入一个.h文件中,这个过程在调用make之后才进行,所以初始情况下你是看不到这个ui_myform.h文件的,只有经过了make过程该头文件才生成。不过没关系,没有这个文件我们照样能写出正确的代码。 单继承方式简单来说就是在代码中首先要自定义一个子类(后文称为MyForm),该类要从form对应的窗体类(或其兼容的子类)派生;并用ui生成的类定义一个类里的成员变量(后文成文myui)。这样在MyForm的构造函数中可以直接调用myui和myui中的变量和函数,使用起来很方便。 举例说明, 比如这里有一个ui文件叫myform.uiui文件里定义的窗体名字为BigWidget,上面摆放了一个单行编辑控件叫lineeditName: //myform.h #include “ui_myform.h” class MyForm: public QWidget { Q_OBJECT public: MyForm(QWidget*parent) { myui.setupUi(this); } private: Ui::BigWidget myui; private: void my_function(); }; 上面这段简单的类的声明是前文所述前三点要点的最佳例证,请对照要点的文字描述和具体的代码体会其中的含义。这里还有一点比较有意思的地方,就是ui文件提供的类被包含在了名为Ui的name space里,这样做的目的是将ui文件的命名空间与用户的代码分离,避免两者出现命名冲突的情况。相应的,我们写代码的时候也要注意在使用ui文件中的类时要用“Ui::”的方式进行引用。 再来看cpp文件 //myform.cpp #include #include “myform.h” void my_function(void) { QMessageBox::information(this, “Name”, myui.lineeditName->text()); } 这里随便写了一个函数,为了说明如何在窗体类里调用ui文件中定义的控件。这段代码非常简单,就不多作说明了。 有了单继承的基础,学习多继承是小菜一碟。来段代码看一下就明白了。 //myform.h #include “ui_myform.h” class MyForm: public QWidget, public Ui::BigWidget { Q_OBJECT public: MyForm(QWidget*parent) { setupUi(this); } private: void my_function(); }; //myform.cpp #include #include “myform.h” void my_function(void) { QMessageBox::information(this, “Name”, lineeditName->text()); } 是不是不用说明大家也能明白呢?多继承其实就是不仅从form需要的窗体类去派生,还要加上ui提供的类本身。这样带来的好处是你的窗体类继承了ui里的所有控件和方法,调用时就可以少写一些字。 单继承和多继承这两种方法没有好坏之分,大家可以根据自己的编程习惯取舍。 第四步,编译、验证在pro文件包含正确FORMS信息的情况下,运行qmake; make就可以编译工程了。 make时如果你认真看一下输出就会发现,make在最开始编译的时候就会自动调用uic去生成需要的代码。经过make之后ui_myform.h文件就生成了,建议大家去看一下这个文件的内容。
### 回答1: Qt是一款跨平台的C++应用程序开发框架,Qt提供了一套完整的工具集合来编译和构建应用程序。下面是一些常见的Qt6源码编译工具集合: 1. C++编译器:Qt6的源码是用C++编写的,因此需要使用C++编译器来将源码编译成可执行的二进制文件。常见的C++编译器有GCC、Clang和MSVC等。 2. qmake:qmake是Qt的默认构建系统工具。它能够根据项目文件(.pro)生成Makefile,并提供了一些便捷的方式来编译、链接和部署应用程序。 3. cmake:cmake是另外一种流行的跨平台构建系统工具。Qt6支持使用cmake作为替代qmake的构建工具。cmake可以生成适用于不同操作系统和编译器的构建文件。 4. ninja:ninja是一个快速且轻量级的构建工具,被广泛用于Qt的源码编译。它能够更高效地并行处理编译任务,并生成可执行文件。 5. Qt Creator:Qt Creator是一款集成开发环境(IDE),专门用于Qt应用程序的开发。它集成了Qt编译工具,并提供了可视化界面来管理项目、编辑代码和调试应用程序。 6. Qt Installer Framework:如果需要将编译好的Qt应用程序打包成安装包,则可以使用Qt Installer Framework。它提供了一套用于构建安装程序的工具和界面,可以方便地进行应用程序的部署和分发。 以上是一些常见的Qt6源码编译工具集合,根据实际需要和开发环境的要求,可以选择合适的工具来完成Qt应用程序的编译和构建。 ### 回答2: Qt是一款流行的跨平台C++应用程序开发框架,Qt 6 是其最新版本。为了编译Qt 6的源码,我们需要使用一系列的工具集合。 首先,我们需要确保我们的系统上安装了C++编译器。常见的C++编译器有GCC、Clang和MSVC。根据不同的平台和操作系统,我们可以选择适合的编译器。确保编译器安装正确并可以通过命令行调用。 其次,为了构建Qt 6源码,我们需要使用一个建构工具,Qt提供了一个名为qmake的构建工具。qmake是一个用于构建Qt工程的工具,它可以自动生成相应的构建脚本(Makefile或其他)来编译和链接我们的代码。在Qt 6中,qmake已经被一个新的构建系统qbs替代,但我们仍然可以使用qmake来编译Qt 6的源码。确保安装了Qt工具包并可以通过命令行调用qmake。 另外,为了成功编译Qt 6源码,我们需要安装一些依赖项。Qt 6有一些核心的依赖项,如OpenGL、DBus和SQLite。我们需要确保这些依赖项已经正确地安装在系统上,并配置好相应的开发环境变量。 最后,Qt提供了一个名为Qt Creator的集成开发环境(IDE),它是一个方便的工具,可以帮助我们管理和编译Qt工程。虽然Qt Creator并不是编译Qt 6源码所必需的,但它提供了许多便利的功能,如代码自动完成、调试工具等。如果我们习惯使用IDE来开发Qt应用程序,建议安装并使用Qt Creator。 总之,编译Qt 6的源码需要使用C++编译器、构建工具(如qmake),确保安装了必要的依赖项,并可以使用Qt Creator作为开发环境。这些工具的正确配置和使用可以帮助我们成功地构建和编译Qt 6应用程序。 ### 回答3: Qt 6 是一个跨平台的应用程序开发框架,它提供了许多工具来帮助开发编译和构建他们的项目。以下是一些常用的 Qt 6 源码编译工具集合: 1. CMake:Qt 6 的源码使用 CMake 构建系统管理,CMake 是一个跨平台的开源构建工具。使用 CMake,开发者可以配置源码编译过程中的各种参数,包括编译器选项、库依赖项等等。 2. Qt Creator:Qt 6 提供了 Qt Creator 集成开发环境,它是一个功能强大的跨平台 IDE,专为 Qt 应用程序开发而设计。Qt Creator 提供了丰富的源码编辑、调试和构建工具,使开发者能够方便地编译和调试他们的项目。 3. qmake:qmake 是一个用于构建 Qt 项目的命令行工具。在 Qt 6 中,开发者可以使用 qmake 创建项目文件(.pro)来描述项目的构建过程,然后使用 qmake 工具生成相应的构建文件,例如 Makefile 或 Visual Studio 解决方案。通过运行生成的构建文件,开发者可以编译和构建他们的项目。 4. Ninja:Ninja 是一个轻量级的构建系统,能够更快地构建大型项目。Qt 6 提供了对 Ninja 的支持,开发者可以使用 Ninja 替代 Make 构建项目,以提高构建速度。 这些工具提供了便捷的编译和构建环境,使开发者能够轻松地编译和构建 Qt 6 的源码。无论是使用命令行工具还是集成开发环境,开发者都可以根据自己的需求选择适合自己的工具来编译和构建他们的项目。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值