在QTableView中使用各种自定义委托

https://blog.csdn.net/hu_linux/article/details/52791665 
该链接也有自定义控件用法,比较好看
 
QT的MVC(View/Delegate)模型十分强大,可以利用各种控件来对表格的输入进行限制。

思路:
1:为每一列定义委托:
A:第一列是编号列,使用只读委托,令该列的单元格是只读的
B:第三列是ID列,只能输入1-12个数字,利用QLineEdit委托和正则表达式对输入进行限制
C:第四年龄列,利用QSpinBox委托进行输入限制,只能输入1-100之间的数字
D:第五列是性别列,利用QComboBox委托对输入进行限制,该列的单元格只能输入Male或Female
E:第六列是头像列,在该列的单元格中央放置一张头像
2:定义代理类,把所有单元格中的字符居中显示。
3:利用QSS,将表格的背景色弄成黄蓝相间。

截图:

 

上代码:

#include <QtGui>   
#include <QItemDelegate>
 #include <QSpinBox>
 
//编号列,只读委托   
//这个方法我还真想不到,呵呵   
class ReadOnlyDelegate : public QItemDelegate  
{  
    Q_OBJECT  
public:  
    ReadOnlyDelegate(QObject *parent = 0): QItemDelegate(parent) { }  
    QWidget *createEditor(QWidget*parent, const QStyleOptionViewItem &option,  
        const QModelIndex &index) const  
    {  
        return NULL;  
    }  
};  
  
//ID列,只能输入1-12个数字   
//利用QLineEdit委托和正则表达式对输入进行限制   
class UserIDDelegate : public QItemDelegate  
{  
    Q_OBJECT  
public:  
    UserIDDelegate(QObject *parent = 0): QItemDelegate(parent) { }  
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,  
        const QModelIndex &index) const  
    {  
        QLineEdit *editor = new QLineEdit(parent);  
        QRegExp regExp("[0-9]{0,10}");  
        editor->setValidator(new QRegExpValidator(regExp, parent));  
        return editor;  
    }  
    void setEditorData(QWidget *editor, const QModelIndex &index) const  
    {  
        QString text = index.model()->data(index, Qt::EditRole).toString();  
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);  
        lineEdit->setText(text);  
    }  
    void setModelData(QWidget *editor, QAbstractItemModel *model,  
        const QModelIndex &index) const  
    {  
        QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);  
        QString text = lineEdit->text();  
        model->setData(index, text, Qt::EditRole);  
    }  
    void updateEditorGeometry(QWidget *editor,  
        const QStyleOptionViewItem &option, const QModelIndex &index) const  
    {  
        editor->setGeometry(option.rect);  
    }  
};  
  
//年龄列,利用QSpinBox委托进行输入限制,只能输入1-100之间的数字   
class AgeDelegate : public QItemDelegate  
{  
    Q_OBJECT  
public:  
    AgeDelegate(QObject *parent = 0): QItemDelegate(parent) { }  
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,  
        const QModelIndex &index) const  
    {  
        QSpinBox *editor = new QSpinBox(parent);  
        editor->setMinimum(1);  
        editor->setMaximum(100);  
        return editor;  
    }  
    void setEditorData(QWidget *editor, const QModelIndex &index) const  
    {  
        int value = index.model()->data(index, Qt::EditRole).toInt();  
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);  
        spinBox->setValue(value);  
    }  
    void setModelData(QWidget *editor, QAbstractItemModel *model,  
        const QModelIndex &index) const  
    {  
        QSpinBox *spinBox = static_cast<QSpinBox*>(editor);  
        spinBox->interpretText();  
        int value = spinBox->value();  
        model->setData(index, value, Qt::EditRole);  
    }  
    void updateEditorGeometry(QWidget *editor,  
        const QStyleOptionViewItem &option, const QModelIndex &index) const  
    {  
        editor->setGeometry(option.rect);  
    }  
};  
  
//性别列,利用QComboBox委托对输入进行限制   
//这一列的单元格只能输入Male或Female   
class SexDelegate : public QItemDelegate  
{  
    Q_OBJECT  
public:  
    SexDelegate(QObject *parent = 0): QItemDelegate(parent) { }  
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,  
        const QModelIndex &index) const  
    {  
        QComboBox *editor = new QComboBox(parent);  
        editor->addItem("Female");  
        editor->addItem("Male");  
        return editor;  
    }  
    void setEditorData(QWidget *editor, const QModelIndex &index) const  
    {  
        QString text = index.model()->data(index, Qt::EditRole).toString();  
        QComboBox *comboBox = static_cast<QComboBox*>(editor);  
        int tindex = comboBox->findText(text);  
        comboBox->setCurrentIndex(tindex);  
    }  
    void setModelData(QWidget *editor, QAbstractItemModel *model,  
        const QModelIndex &index) const  
    {  
        QComboBox *comboBox = static_cast<QComboBox*>(editor);  
        QString text = comboBox->currentText();  
        model->setData(index, text, Qt::EditRole);  
    }  
    void updateEditorGeometry(QWidget *editor,  
        const QStyleOptionViewItem &option, const QModelIndex &index) const  
    {  
        editor->setGeometry(option.rect);  
    }  
};  
  
//头像列,只是在单元格中央放一张小图而已   
class IconDelegate : public QItemDelegate  
{  
    Q_OBJECT  
public:  
    IconDelegate(QObject *parent = 0): QItemDelegate(parent) { }  
    void paint(QPainter *painter, const QStyleOptionViewItem &option,  
        const QModelIndex & index ) const  
    {  
        //show.bmp是在工程目录中的一张图片(其实就是QQ的图标啦,呵呵)  
        QPixmap pixmap = QPixmap("show.bmp").scaled(24, 24);  
        qApp->style()->drawItemPixmap(painter, option.rect,  Qt::AlignCenter, QPixmap(pixmap));  
    }  
};  
  
//代理类,把所有单元格中的字符居中显示   
class VIPModel : public QStandardItemModel  
{  
    Q_OBJECT  
public:  
    VIPModel(QObject *parent=NULL) : QStandardItemModel(parent) { }  
    VIPModel(int row, int column, QObject *parent=NULL)  
        : QStandardItemModel(row, column, parent) { }  
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const  
    {  
        if( Qt::TextAlignmentRole == role )  
            return Qt::AlignCenter;   
        return QStandardItemModel::data(index, role);  
    }  
  
};  
  
#include "main.moc"   
  
int main(int argc, char *argv[])  
{  
    QApplication app(argc, argv);  
  
    VIPModel *model = new VIPModel(5, 5);  
    QTableView *tableView = new QTableView;  
  
    //把表格的背景调成黄蓝相间   
    //这种方法是在网上看到的,用起来还真方便啊   
    tableView->setAlternatingRowColors(true);  
    tableView->setStyleSheet("QTableView{background-color: rgb(250, 250, 115);"  
        "alternate-background-color: rgb(141, 163, 215);}");  
  
    tableView->setWindowTitle("VIP List");  
    tableView->resize(700, 400);  
    tableView->setModel(model);  
    QStringList headerList;  
    headerList << "No." << "ID" << "Name" << "Age" << "Sex" << "Show";  
    model->setHorizontalHeaderLabels(headerList);  
    tableView->verticalHeader()->setVisible(false);  
    tableView->horizontalHeader()->setStretchLastSection(true);  
  
    //为每一列加载委托   
    ReadOnlyDelegate readOnlyDelegate;  
    //tableView->setItemDelegateForColumn(0, &readOnlyDelegate);  //我用了会报错
    tableView->setItemDelegateForColumn(0, new ReadonlyDelegate(this)); //我用的是这种
    UserIDDelegate userIDDelegate;  
    tableView->setItemDelegateForColumn(1, &userIDDelegate);  
    AgeDelegate spinBoxDelegate;  
    tableView->setItemDelegateForColumn(3, &spinBoxDelegate);  
    SexDelegate comboBoxDelegate;  
    tableView->setItemDelegateForColumn(4, &comboBoxDelegate);  
    IconDelegate iconDelegate;  
    tableView->setItemDelegateForColumn(5, &iconDelegate);  
  
    for(int i=0; i<10; i++)  
    {  
        QModelIndex index = model->index(i, 0, QModelIndex());  
        model->setData(index, i);  
    }  
  
    tableView->show();  
    return app.exec();  
}  

  

  QTableView、QStandardItemModel/QAbstractItemModel 、QStyledItemDelegate/QItemDelegate和QModelIndex;

 先上图看效果吧

选择文件按钮这一列,第0行是点击后进入编辑模式时显示按钮的情况。

下面一行是显示的选择文件的全路径。

第2行”C:“是初始化时设置的值,只是为了测试显示。

最后一行是没有选择文件。

 

我实现的这个SelectFileButton办法:

QPushButton;

SelectFileButton里实现一个槽函数:功能,点击时选择文件并返回路径。

cQItemDelegate;

d、然后再重写createEditor();返回SelectFileButton的指针

e、重写setModelData()、setEditorData(); 设置模型数据和设置编辑数据的。

#ifndef SELECTFILEBUTTONDELEGATE_H
#define SELECTFILEBUTTONDELEGATE_H

#include <QItemDelegate>
#include <QPushButton>
#include <QModelIndex>
#include <QFileDialog>
#include <QAbstractItemModel>
#include <QDebug>


class TableModel;


class  SelectFileButton: public QPushButton
{
	Q_OBJECT
public:
	SelectFileButton(const QModelIndex & index, QWidget *parent = 0)
	:	QPushButton(parent)
	{
		Init(index);
	}
	SelectFileButton(const QModelIndex & index, const QString &text, QWidget *parent = 0) 
		: QPushButton(text, parent)
	{
		Init(index);
	}
	SelectFileButton(const QModelIndex & index, const QIcon& icon, const QString &text, QWidget *parent = 0) 
		:QPushButton(icon, text, parent)
	{
		Init(index);
	}
	~SelectFileButton() {
		qDebug() << "~SelectFileButton";
	}
protected:
	void Init(const QModelIndex & index)
	{
		m_index = index;
		connect(this, SIGNAL(clicked()), this, SLOT(btnClick_slot()));

	}

public slots:
void btnClick_slot()
{
	QString strValue;
	QModelIndex index = this->m_index;
	QFileDialog * dlg = new QFileDialog(0);
	
	int res =dlg->exec();	 //这里开启新的线程,顶层会释放这个按钮,所以要把Index 保存一份
	if (res==QFileDialog::Accepted)
	{
		strValue = dlg->selectedFiles()[0];
		 QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model());
		 model->setData(index, strValue);

	}
	

}
private:
	QModelIndex m_index;
};



/**********************************************************************/

class SelectFileButtonDelegate : public QItemDelegate
{
	Q_OBJECT

public:
	QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
		const QModelIndex &index) const
	{
		SelectFileButton* btn = new SelectFileButton(index,QStringLiteral("查找文件路径"), parent);	  //这个是其他线程里的 所以不能保存下来。每次的btn还不一样

		return btn;
		
	}
	
	void setModelData(QWidget *editor, QAbstractItemModel *model,
		const QModelIndex &index) const;
	void setEditorData(QWidget *editor, const QModelIndex &index) const;

public:
	SelectFileButtonDelegate(QObject *parent);
	~SelectFileButtonDelegate();

private:
	QPushButton* m_btn;
	
};

#endif // SELECTFILEBUTTONDELEGATE_H

  

通过painter画自定义控件

 

 QStyleOption子类:

 

QStyleOptionButton, QStyleOptionComplex, QStyleOptionDockWidget, QStyleOptionFocusRect, QStyleOptionFrame, QStyleOptionGraphicsItem, QStyleOptionHeader, QStyleOptionMenuItem, QStyleOptionProgressBar, QStyleOptionRubberBand, QStyleOptionTab, QStyleOptionTabBarBase, QStyleOptionTabWidgetFrame, QStyleOptionToolBar, QStyleOptionToolBox, and QStyleOptionViewItem

 

一 、painter 自定义进度条 
//自定义进度条
BarDelegate::BarDelegate( QObject *parent ) : QAbstractItemDelegate( parent ) { }

void BarDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  if( option.state & QStyle::State_Selected )
    painter->fillRect( option.rect, option.palette.highlight() );

  // 数据是存储在QStandardItemModel的QStandardItem,会自动根据当前行进行匹配(我认为)
  int value = index.model()->data( index, Qt::DisplayRole ).toInt(); // 这句,取得当前行的数据
  qDebug() << value;
  double factor = double(value)/100.0; // 计算比例因子

  painter->save(); // 保存旧画板(我认为)
  // 进度条背景色
  if( factor > 0.8 )
  {
    painter->setBrush( Qt::red ); // 超过0.8画纯红色
    factor = 1;
  }
  else
    painter->setBrush( QColor( 0, int(factor*255), 255-int(factor*255) ) ); // 否则颜色依次变淡

  int n = factor*100;
  QString str1 = QString("%1\%").arg(n);
  painter->setPen( Qt::red ); // 画笔颜色(这里没用到,我认为)
  // 前面都是准备工作,这里才是真正画进度条
  painter->drawRect( option.rect.x()+2, option.rect.y()+2, int(factor*(option.rect.width()-5)), option.rect.height()-5 );
  painter->drawText(option.rect.x()+int(factor*(option.rect.width()))+2, option.rect.y()+option.rect.height()/2, str1);
  painter->restore(); // 恢复新画板(我认为)
}

QSize BarDelegate::sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  return QSize( 45, 15 ); // 随便改,不影响(我认为)
}
class BarDelegate : public QAbstractItemDelegate
{
public:
  BarDelegate( QObject *parent = 0 );
  // 覆盖两个函数就可以显示进度条
  void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const;
  QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const;
};

 1  painter进度条 QStyleOptionProgressBar

void ProgressBarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.column() == 0) {
        int value = index.model()->data(index).toInt();
        QStyleOptionProgressBarV2 progressBarOption;
        progressBarOption.rect = option.rect.adjusted(4, 4, -4, -4);
        progressBarOption.minimum = 0;
        progressBarOption.maximum = 100;
        progressBarOption.textAlignment = Qt::AlignRight;
        progressBarOption.textVisible = true;
        progressBarOption.progress = value;
        progressBarOption.text = tr("%1%").arg(progressBarOption.progress);

        painter->save();
        if (option.state & QStyle::State_Selected) {
            painter->fillRect(option.rect, option.palette.highlight());
                    painter->setBrush(option.palette.highlightedText());
        }
                QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);

        painter->restore();

    } else {
        return QItemDelegate::paint (painter, option, index);
    }
}

 

二、painter自定义按钮  QStyTableViewDelegate::TableViewDelegate(int z_Column, int z_NumberButtons,QWidget *parent)

    : QStyledItemDelegate(parent),
      m_pOpenButton(new QPushButton()),
      m_pDeleteButton(new QPushButton()),
      m_nSpacing(5),
      m_nWidth(25),
      m_nHeight(20),
      m_Column(z_Column),
      m_NumberButtons(z_NumberButtons)
{if (2 == m_NumberButtons)
    {
        m_list << QStringLiteral("编辑按钮") << QStringLiteral("删除按钮");
    }
    // 设置按钮正常、划过、按下样式
    QString z_Path = QCoreApplication::applicationDirPath();
    m_pOpenButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url("+z_Path+"/res/system.png);} \
                                 QPushButton:hover {image:url("+z_Path+"/res/system.png);} \
                                 QPushButton:pressed {image:url("+z_Path+"/res/system.png);}");

     m_pDeleteButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url("+z_Path+"/res/delete.png);} \
                                QPushButton:hover {image:url("+z_Path+"/res/delete.png);} \
                                QPushButton:pressed {image:url("+z_Path+"/res/delete.png);}");
}

TableViewDelegate::~TableViewDelegate()
{

}

// 绘制按钮
void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, viewOption, index);

    if (index.column() == m_Column)
    {
        // 计算按钮显示区域
        int nCount = m_list.count();
        int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
        int nTop = (option.rect.height() - m_nHeight) / 2;

        for (int i = 0; i < nCount; ++i)
        {
            // 绘制按钮
            QStyleOptionButton button;
            button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                                option.rect.top() + nTop,  m_nWidth, m_nHeight);
            button.state |= QStyle::State_Enabled;
            button.iconSize = QSize(20, 20);

            if (button.rect.contains(m_mousePoint))
            {
                if (m_nType == 0)
                {
                    button.state |= QStyle::State_MouseOver;
                    //button.icon = QIcon(QString(":/Images/%1Hover").arg(m_list.at(i)));
                }
                else if (m_nType == 1)
                {
                    button.state |= QStyle::State_Sunken;
                    //button.icon = QIcon(QString(":/Images/%1Pressed").arg(m_list.at(i)));
                }
            }

            //QWidget *pWidget = m_pOpenButton.data();
            QWidget *pWidget = (i == 0) ? m_pOpenButton.data() : m_pDeleteButton.data();
            pWidget->style()->drawControl(QStyle::CE_PushButton, &button, painter, pWidget);
        }
    }
}

// 响应按钮事件 - 划过、按下
bool TableViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
    if (index.column() != m_Column)
        return false;

    m_nType = -1;
    bool bRepaint = false;
    QMouseEvent *pEvent = static_cast<QMouseEvent *> (event);
    m_mousePoint = pEvent->pos();

    int nCount = m_list.count();
    int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
    int nTop = (option.rect.height() - m_nHeight) / 2;

    // 还原鼠标样式
    QApplication::restoreOverrideCursor();

    for (int i = 0; i < nCount; ++i)
    {
        QStyleOptionButton button;
        button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                            option.rect.top() + nTop,  m_nWidth, m_nHeight);

        // 鼠标位于按钮之上
        if (!button.rect.contains(m_mousePoint))
            continue;

        bRepaint = true;
        switch (event->type())
        {
        // 鼠标滑过
        case QEvent::MouseMove:
        {
            // 设置鼠标样式为手型
            //QApplication::setOverrideCursor(Qt::PointingHandCursor);

            m_nType = 0;
            QToolTip::showText(pEvent->globalPos(), m_list.at(i));
            break;
        }
            // 鼠标按下
        case QEvent::MouseButtonPress:
        {
            m_nType = 1;
            break;
        }
            // 鼠标释放
        case QEvent::MouseButtonRelease:
        {
            if (i == 0)
            {
                emit EditData(index);
            }
            else
            {
                emit deleteData(index);
            }
            break;
        }
        default:
            break;
        }
    }

    return bRepaint;
}

 

三 painter 设置图片

void ItemdelegateTest::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem  viewOption(option);
    if (viewOption.state & QStyle::State_HasFocus)
    {
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
    }

    QStyledItemDelegate::paint(painter, viewOption, index);

    int height = (viewOption.rect.height()) / 2;
    QPixmap pixmap = QPixmap(":/check.png");
    //QPixmap pixmap = QPixmap("E:/qt/QtDelegateTestT/zhj.png");
    QRect DrawRect = QRect(viewOption.rect.left() + viewOption.rect.width() - 30, viewOption.rect.top() + height, 9, 9);
    painter->drawPixmap(DrawRect, pixmap);
}

bool ItemdelegateTest::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    int height = (option.rect.height()) / 2;
    QRect DrawRect = QRect(option.rect.left() + option.rect.width() - 30, option.rect.top() + height, 9, 9);

    //QMouseEvent *mouseEvent = static_cast(event);
    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
    if (event->type() == QEvent::MouseButtonPress && DrawRect.contains(mouseEvent->pos()))
    {
       emit deleteItem(index);
    }

    if (event->type() == QEvent::MouseMove && DrawRect.contains(mouseEvent->pos()))
    {
        QCursor cursor(Qt::PointingHandCursor);
        QApplication::setOverrideCursor(cursor);
        QToolTip::showText(mouseEvent->globalPos(), "删除");
    }
    else
    {
        QCursor cursor(Qt::ArrowCursor);
        QApplication::setOverrideCursor(cursor);
    }

    return QStyledItemDelegate::editorEvent(event, model, option, index);
}

 

 

 

panier绘制checkbox

CheckBoxDelegate::CheckBoxDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
{

}

CheckBoxDelegate::~CheckBoxDelegate()
{

}

// 绘制复选框
void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, viewOption, index);

    if (index.column() == CHECK_BOX_COLUMN)
    {
        bool data = index.model()->data(index, Qt::UserRole).toBool();

        QStyleOptionButton checkBoxStyle;
        checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;
        checkBoxStyle.state |= QStyle::State_Enabled;
        checkBoxStyle.iconSize = QSize(20, 20);
        checkBoxStyle.rect = option.rect;

        QCheckBox checkBox;
        QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox);
    }
}

// 响应鼠标事件,更新数据
bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    QRect decorationRect = option.rect;

    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
    if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
    {
        if (index.column() == CHECK_BOX_COLUMN)
        {
            bool data = model->data(index, Qt::UserRole).toBool();
            model->setData(index, !data, Qt::UserRole);
        }
    }

    return QStyledItemDelegate::editorEvent(event, model, option, index);
}
--------------------- 
作者:一去丶二三里 
来源:CSDN 
原文:https://blog.csdn.net/liang19890820/article/details/50721200 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

转载于:https://www.cnblogs.com/wangjian8888/p/8883634.html

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值