当前位置: 首页 > news >正文

Qt基础 | QSqlTableModel 的使用

文章目录

  • 一、QSqlTableModel 的使用
    • 1.主窗口MainWindow类定义
    • 2.构造函数
    • 3.打开数据表
      • 3.1 添加 SQLite 数据库驱动、设置数据库名称、打开数据库
      • 3.2 数据模型设置、选择模型、自定义代理组件、界面组件与模型数据字段间的数据映射
    • 4.添加、插入与删除记录
    • 5.保存与取消修改
    • 6.设置和清除照片
    • 7.数据记录的遍历
    • 8.记录排序
    • 9.记录过滤

关于QSqlDatabase、QSqlTableModel、QSqlRecord、QDataWidgetMapper 类的使用可参考:Qt基础 | Qt SQL模块介绍 | Qt SQL模块常用类及其常用函数介绍

一、QSqlTableModel 的使用

  这一部分使用 QSqlTableModel 显示实例数据库 demodb 中 employee 数据表的内容,实现编辑、插入、删除记录的操作,实现数据的排序和记录过滤,还实现 BLOB 类型字段 Photo 中存储照片的显示、导入等操作。

1.主窗口MainWindow类定义

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include    <QMainWindow>#include    <QLabel>
#include    <QString>#include    <QtSql>
#include    <QDataWidgetMapper>#include    "qwcomboboxdelegate.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTprivate:QSqlDatabase  DB;//数据库连接QSqlTableModel  *tabModel;  //数据模型QItemSelectionModel *theSelection; //选择模型QDataWidgetMapper   *dataMapper; //数据映射QWComboBoxDelegate   delegateSex; //自定义数据代理,性别QWComboBoxDelegate   delegateDepart; //自定义数据代理,部门void    openTable();//打开数据表void    getFieldNames();//获取字段名称,填充“排序字段”的comboBox
public:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_currentChanged(const QModelIndex &current, const QModelIndex &previous);// QTableView的SelectionModel的行发生了变化,进行处理void on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);void on_actOpenDB_triggered();void on_actRecAppend_triggered();void on_actRecInsert_triggered();void on_actRevert_triggered();void on_actSubmit_triggered();void on_actRecDelete_triggered();void on_actPhoto_triggered();void on_actPhotoClear_triggered();void on_radioBtnAscend_clicked();void on_radioBtnDescend_clicked();void on_radioBtnMan_clicked();void on_radioBtnWoman_clicked();void on_radioBtnBoth_clicked();void on_comboFields_currentIndexChanged(int index);void on_actScan_triggered();
private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

MainWindow 类中定义了几个私有变量:

  • QSqlDatabase DB:用于加载数据库驱动和建立与数据库之间的连接

  • QSqlTableModel *tabModel:用于指定某个数据表 ,作为数据表的数据模型

  • QItemSelectionModel *theSelection:作为 tabModel 的选择模型,提供 currentChanged()、currentRowChanged()信号,在 tabModel 选择的字段发生变化、当前记录发生变化时发射信号,以便程序进行响应。

    例如,在 currentChanged() 信号发射时,检查 tabModel 是否有数据被修改 ,从而更新界面上 “保存”和“取消“两个按钮的使能状态

  • QDataWidgetMapper *dataMapper:用于实现界面组件与 tabModel 的字段之间的映射。

    例如,界面上的 QLineEdit 型的 dbEditName 组件与数据表的 Name 字段映射,当前记录变化时会自动更新显示当前记录 Name 段的数据。

  • QWComboBoxDelegate delegateSex:是自定义的基于 QComboBox 的代理类,delegateSex 和 delegateDepart 用作 tableView 中“性别” 和 “部门” 字段的代理组件。

私有函数:

  • openTable函数:用于打开数据表,包括添加 SQLite 数据库驱动、打开数据库文件、连接 employee 数据表并设置显示属性,并创建 tableView 显示的代理组件,设置数据源与界面组件的映射等
  • getFieldNames函数:用于获取数据表 employee 的所有字段的名称,并填充界面上 “排序字段” 后的 ComboBox 组件。

槽函数:

  • on_currentChanged:用于检查数据表内容是否修改,根据是否有未提交的修改,更新工具栏按钮 “保存” 和 “取消” 两个按钮的使能状态。
  • on_currentRowChanged:用于在当前行变化时,从新的记录里提取 Photo 字段的内容,并将图片在 QLabel 组件里显示出来。

2.构造函数

  MainWindow 的构造函数代码如下,主要是对 tableView 一些显示属性的设置。

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);this->setCentralWidget(ui->splitter);//   tableView显示属性设置ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);ui->tableView->setAlternatingRowColors(true);
//    ui->tableView->resizeColumnsToContents();
//    ui->tableView->horizontalHeader()->setStretchLastSection(true);
}
  • setSelectionBehavior函数:用于定义视图(View)选择哪种选择行为

    void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
    

    QAbstractItemView::SelectionBehavior是一个枚举类型,有如下选择:

    • QAbstractItemView::SelectItems:选择单个项
    • QAbstractItemView::SelectRows:仅选择行
    • QAbstractItemView::SelectColumns:仅选择列
  • setSelectionMode函数:用于定义视图(view)的选择模式

    void setSelectionMode(QAbstractItemView::SelectionMode mode)
    

    QAbstractItemView::SelectionMode是一个枚举类型,有如下取值:

    • QAbstractItemView::SingleSelection:单选模式,用户只能选择一个项目。
    • QAbstractItemView::ContiguousSelection:连续选择模式,用户可以选择多个项目,但这些项目必须在视觉上是连续的。
    • QAbstractItemView::ExtendedSelection:扩展选择模式,用户可以选择多个项目,并且可以选择非连续的项目。
    • QAbstractItemView::MultiSelection:多选模式,用户可以选择多个项目。
    • QAbstractItemView::NoSelection:无选择模式
  • setAlternatingRowColors函数:用来控制当前是否启用交替行颜色绘制背景

    void setAlternatingRowColors(bool enable)
    
    • alternatingRowColors 属性设置为 true 时,视图中的项背景将使用 QPalette::BaseQPalette::AlternateBase 颜色交替绘制。QPalette::Base 是默认的背景颜色,而 QPalette::AlternateBase 是用于交替行的背景颜色。

      image-20240723122428920

    • alternatingRowColors 属性设置为 false 时,所有项的背景将统一使用 QPalette::Base 颜色绘制。

  • resizeColumnsToContents函数:用于根据列中每个项的代理组件的大小提示来调整所有列的宽度

    void QTableView::resizeColumnsToContents()
    
  • horizontalHeader函数:用于返回 QTableView 的水平表头

    QHeaderView *QTableView::horizontalHeader() const
    

3.打开数据表

  打开数据表这一部分主要包括:

  • 添加 SQLite 数据库驱动、设置数据库名称、打开数据库
  • 设置数据模型、选择模型、自定义代理组件、界面组件与模型数据字段间的数据映射

3.1 添加 SQLite 数据库驱动、设置数据库名称、打开数据库

  这一部分主要用到了 QSqlDatabase 类,该类用于处理与数据库的连接。

void MainWindow::on_actOpenDB_triggered()
{//打开数据表QString aFile=QFileDialog::getOpenFileName(this,"选择数据库文件","","SQL Lite数据库(*.db *.db3)");if (aFile.isEmpty())  //选择SQL Lite数据库文件return;//打开数据库DB=QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动DB.setDatabaseName(aFile); //设置数据库名称
//    DB.setHostName();
//    DB.setUserName();
//    DB.setPassword();if (!DB.open())   //打开数据库{QMessageBox::warning(this, "错误", "打开数据库失败",QMessageBox::Ok,QMessageBox::NoButton);return;}//打开数据表openTable();
}

补充

  • QSqlDatabase::addDatabase:该静态函数用于添加数据库驱动,其返回结果为 QSqlDatabase 类,该类可用于数据库操作,包括建立数据库连接,设置登陆数据库的参数,打开数据库等。

    其完整的函数声明如下:

    [static] QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName = QLatin1String(defaultConnection))
    

    示例:

    // 添加一个名为 "myConnection" 的 SQLite 数据库连接
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "myConnection");
    db.setDatabaseName("example.db"); // 设置数据库文件名
    db.setUserName("user"); // 设置用户名
    db.setPassword("password"); // 设置密码// 打开数据库连接
    if (db.open()) {QSqlQuery query;query.exec("SELECT * FROM table_name"); // 执行查询while (query.next()) {// 处理查询结果}db.close();
    } else {qDebug() << "Error: Unable to open database";
    }
    

    还有一个函数重载,参数指定的不是驱动名称,而是 QSqlDriver 类。

    [static] QSqlDatabase QSqlDatabase::addDatabase(QSqlDriver *driver, const QString &connectionName = QLatin1String(defaultConnection))
    

    示例:

    PGconn *con = PQconnectdb("host=server user=bart password=simpson dbname=springfield");
    QPSQLDriver *drv = new QPSQLDriver(con);
    QSqlDatabase db = QSqlDatabase::addDatabase(drv); // becomes the new default connection
    QSqlQuery query;
    query.exec("SELECT NAME, ID FROM STAFF");
    
  • QSqlDatabase类的数据库连接操作:用于设置数据库连接与登陆参数

    注意:对于 SQLite 数据库,只需用 setDatabaseName() 设置数据库文件即可。如果是网络型数据库,如 Oracle、MS SQL Server等,还需要使用 setHostName() 设置主机名,setUserName() 设置数据库用户名,setPassword() 设置数据库登陆密码。

    • setDatabaseName:设置数据库名称
    • setHostName:设置数据库主机名
    • setUserName:设置数据库用户名
    • setPassword:设置数据库登陆密码
  • open()函数:打开数据库。如果成功打开数据库则返回true

3.2 数据模型设置、选择模型、自定义代理组件、界面组件与模型数据字段间的数据映射

  这部分用到 3 个类:

  • QSqlTableModel

    QSqlTableModel 是一个用于显示和编辑单个数据库表内容的模型

  • QTableView

    二维数据表视图组件,有多个行和多个列,每个基本显示单元是一个单元格,通过 setModel() 函数设置一个 QSqlTableModel 类的数据模型之后,一个单元格显示 QSqlTableModel 数据模型中的一个项

  • QItemSelectionModel

    一个用于跟踪视图组件的单元格选择状态的类,当在 QTableView 选择某个单元格,或多个单元格时,通过 QItemSelectionModel 可以获得选中的单元格的模型索引,为单元格的选择操作提供方便。

这几个类之间的关系是:QTableView是界面视图组件,其关联的数据模型是 QSqlTableModel,关联的项选择模型是 QItemSelectionModel。

数据模型创建与属性设置

tabModel=new QSqlTableModel(this,DB);//数据表
tabModel->setTable("employee"); //设置数据表
tabModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//数据保存方式,OnManualSubmit , OnRowChange
tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
if (!(tabModel->select()))//查询数据
{QMessageBox::critical(this, "错误信息","打开数据表错误,错误信息\n"+tabModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);return;
}
  • 创建数据库模型且指定数据库的连接

    通过往 QSqlTableModel 构造函数中传入参数来指定数据库连接

    构造函数为:

    QSqlTableModel::QSqlTableModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase())
    

    在本案例中为

    tabModel=new QSqlTableModel(this,DB);//数据表
    
  • 使用 setTable() 函数来指定数据表,此时不会立即读取记录,但会提取字段信息

    [virtual] void QSqlTableModel::setTable(const QString &tableName)
    

    在本案例中为

    tabModel->setTable("employee"); //设置数据表
    
  • 使用 setSort() 函数设置排序字段与排序规则,需调用 select() 函数才生效

    [virtual] void QSqlTableModel::setSort(int column, Qt::SortOrder order)
    
    • 第一个参数 column 是排序字段的列号
    • 第二个参数 order 是枚举类型Qt::SortOrder,表示排序方式,其中,Qt::AscendingOrder表示升序,Qt::DescendingOrder表示降序

    在本案例中为

    tabModel->setSort(tabModel->fieldIndex("empNo"),Qt::AscendingOrder); //排序
    
  • 使用 setEditStrategy() 函数用于设置编辑策略

    [virtual] void QSqlTableModel::setEditStrategy(QSqlTableModel::EditStrategy strategy)
    
    • 参数 strategy 是枚举类型 QSqlTableModel::EditStrategy,各取值的意义如下:
      • QSqlTableModel::OnFieldChange:字段值变化时立即更新到数据库
      • QSqlTableModel::OnRowChange:当前行(记录)变换时更新到数据库
      • QSqlTableModel::OnManualSubmit:所有修改暂时缓存,手动调用 submitAll() 保存所有修改,或调用 revertAll() 函数取消所有未保存的修改。
  • 使用 select() 函数查询数据表的数据,并使用设置的排序和过滤规则

    [virtual slot] bool QSqlTableModel::select()
    
    • 如果成功打开则返回true,否则,返回false

    在本案例中为:

    tabModel->select()
    

表头设置

  使用 setHeaderData() 函数设置表头,即设置数据库表的字段在 tableView 中显示时的字段名称。为此,将每个字段的显示设置为相应的中文标题。

[override virtual] bool QSqlQueryModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole)
  • 参数 section 是字段的序号,通过 fieldIndex() 函数可以获取某个字段名在数据模型里的序号
  • 参数 orientation 是字段的方向,其中,Qt::Horizontal表示是水平方向标题,Qt::Vertical表示是竖直方向标题
  • 参数 value 是要设置的值

表头设置部分代码为:

    tabModel->setHeaderData(tabModel->fieldIndex("empNo"),Qt::Horizontal,"工号");tabModel->setHeaderData(tabModel->fieldIndex("Name"),Qt::Horizontal,"姓名");tabModel->setHeaderData(tabModel->fieldIndex("Gender"),Qt::Horizontal,"性别");tabModel->setHeaderData(tabModel->fieldIndex("Height"),Qt::Horizontal,"身高");tabModel->setHeaderData(tabModel->fieldIndex("Birthday"),Qt::Horizontal,"出生日期");tabModel->setHeaderData(tabModel->fieldIndex("Mobile"),Qt::Horizontal,"手机");tabModel->setHeaderData(tabModel->fieldIndex("Province"),Qt::Horizontal,"省份");tabModel->setHeaderData(tabModel->fieldIndex("City"),Qt::Horizontal,"城市");tabModel->setHeaderData(tabModel->fieldIndex("Department"),Qt::Horizontal,"部门");tabModel->setHeaderData(tabModel->fieldIndex("Education"),Qt::Horizontal,"学历");tabModel->setHeaderData(tabModel->fieldIndex("Salary"),Qt::Horizontal,"工资");tabModel->setHeaderData(tabModel->fieldIndex("Memo"),Qt::Horizontal,"备注"); //这两个字段不再tableView中显示tabModel->setHeaderData(tabModel->fieldIndex("Photo"),Qt::Horizontal,"照片");

创建选择模型及信号的作用

  选择模型的作用是当用户在 TableView 组件上操作时,获取当前选择的行 、列信息,并且在选择的单元格变化时发射 currentChanged() 信号,在当前行变化时发射 currentRowChanged() 信号。

theSelection=new QItemSelectionModel(tabModel);//关联选择模型
//theSelection当前项变化时触发currentChanged信号
connect(theSelection,SIGNAL(currentChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentChanged(QModelIndex,QModelIndex)));
//选择行变化时
connect(theSelection,SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),this,SLOT(on_currentRowChanged(QModelIndex,QModelIndex)));

对应的槽函数为:

void MainWindow::on_currentChanged(const QModelIndex &current, const QModelIndex &previous)
{//更新actPost和actCancel 的状态Q_UNUSED(current);Q_UNUSED(previous);ui->actSubmit->setEnabled(tabModel->isDirty()); //有未保存修改时可用ui->actRevert->setEnabled(tabModel->isDirty());
}void MainWindow::on_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{Q_UNUSED(previous);
// 行切换时的状态控制ui->actRecDelete->setEnabled(current.isValid());ui->actPhoto->setEnabled(current.isValid());ui->actPhotoClear->setEnabled(current.isValid());if (!current.isValid()){ui->dbLabPhoto->clear(); //清除图片显示return;}dataMapper->setCurrentIndex(current.row()); //更新数据映射到当前行,使界面上的编辑框、下拉列表框等与字段关联的界面组件显示当前记录的内容int curRecNo=current.row();//获取行号QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录if (curRec.isNull("Photo"))  //图片字段内容为空ui->dbLabPhoto->clear();else{QByteArray data=curRec.value("Photo").toByteArray();QPixmap pic;pic.loadFromData(data);ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));}
}

tableView的设置

  用 QTableView 组件显示 tabModel 的表格数据内容时,需要设置其数据模型和关联选择模型,并且将 “Memo” 和 “Photo” 两个字段的列设置为隐藏,因为在表格里难以显示备注文件和图片。

ui->tableView->setModel(tabModel);//设置数据模型
ui->tableView->setSelectionModel(theSelection); //设置选择模型
ui->tableView->setColumnHidden(tabModel->fieldIndex("Memo"),true);//隐藏列
ui->tableView->setColumnHidden(tabModel->fieldIndex("Photo"),true);//隐藏列

  自定义基于 QComboBox 的代理组件类 QWComboBoxDelegate,组件类中有一个函数 setItems() ,用于初始化下拉列表框和设置是都可以编辑,

qwcombocoxdelegate.h

#ifndef QWCOMBOBOXDELEGATE_H
#define QWCOMBOBOXDELEGATE_H#include    <QStyledItemDelegate>
#include    <QComboBox>class QWComboBoxDelegate : public QStyledItemDelegate
{Q_OBJECTprivate:QStringList m_ItemList;//选择列表bool    m_isEdit; //是否可编辑public:QWComboBoxDelegate(QObject *parent=0);void    setItems(QStringList items, bool isEdit);//初始化设置列表内容,是否可编辑
//自定义代理组件必须继承以下4个函数QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
};#endif // QWCOMBOBOXDELEGATE_H

qwcombocoxdelegate.cpp

#include "qwcomboboxdelegate.h"#include    <QComboBox>QWComboBoxDelegate::QWComboBoxDelegate(QObject *parent):QStyledItemDelegate(parent)
{}void QWComboBoxDelegate::setItems(QStringList items, bool isEdit)
{m_ItemList=items;m_isEdit=isEdit;
}QWidget *QWComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{Q_UNUSED(option);Q_UNUSED(index);QComboBox *editor = new QComboBox(parent);for (int i=0;i<m_ItemList.count();i++)   //从字符串列表初始下拉列表editor->addItem(m_ItemList.at(i));editor->setEditable(m_isEdit); //是否可编辑return editor;
}void QWComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{QString str = index.model()->data(index, Qt::EditRole).toString();QComboBox *comboBox = static_cast<QComboBox*>(editor);comboBox->setCurrentText(str);
}void QWComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{QComboBox *comboBox = static_cast<QComboBox*>(editor);QString str = comboBox->currentText();model->setData(index, str, Qt::EditRole);
}void QWComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const
{Q_UNUSED(index);editor->setGeometry(option.rect);
}

  创建多个代理组件实例,分别用于“性别” 和 “部门” 两个字段。

//tableView上为“性别”和“部门”两个字段设置自定义代理组件
QStringList strList;
strList<<"男"<<"女";
bool isEditable=false;
delegateSex.setItems(strList,isEditable);
ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Gender"),&delegateSex); //Combbox选择型strList.clear();
strList<<"销售部"<<"技术部"<<"生产部"<<"行政部";
isEditable=true;
delegateDepart.setItems(strList,isEditable);
ui->tableView->setItemDelegateForColumn(tabModel->fieldIndex("Department"),&delegateDepart); //Combbox选择型

数据映射

  QDataWidgetMapper 用于建立界面组件与数据模型之间的映射,可以将界面的 QLineEdit、QCombobox 等组件与数据模型的一个字段关联起来。当数据模型关联的字段内容发生变化时,自动更新组件的显示内容。

//创建界面组件与数据模型的字段之间的数据映射
dataMapper= new QDataWidgetMapper();
dataMapper->setModel(tabModel);//设置数据模型
dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);////    dataMapper->setItemDelegate(new QSqlRelationalDelegate(this)); //含有外键的
//界面组件与tabModel的具体字段之间的联系
dataMapper->addMapping(ui->dbSpinEmpNo,tabModel->fieldIndex("empNo"));
dataMapper->addMapping(ui->dbEditName,tabModel->fieldIndex("Name"));
dataMapper->addMapping(ui->dbComboSex,tabModel->fieldIndex("Gender"));dataMapper->addMapping(ui->dbSpinHeight,tabModel->fieldIndex("Height"));
dataMapper->addMapping(ui->dbEditBirth,tabModel->fieldIndex("Birthday"));
dataMapper->addMapping(ui->dbEditMobile,tabModel->fieldIndex("Mobile"));dataMapper->addMapping(ui->dbComboProvince,tabModel->fieldIndex("Province"));
dataMapper->addMapping(ui->dbEditCity,tabModel->fieldIndex("City"));
dataMapper->addMapping(ui->dbComboDep,tabModel->fieldIndex("Department"));dataMapper->addMapping(ui->dbComboEdu,tabModel->fieldIndex("Education"));
dataMapper->addMapping(ui->dbSpinSalary,tabModel->fieldIndex("Salary"));dataMapper->addMapping(ui->dbEditMemo,tabModel->fieldIndex("Memo"));//    dataMapper->addMapping(ui->dbPhoto,tabModel->fieldIndex("Photo")); //图片无法直接映射dataMapper->toFirst();//移动到首记录getFieldNames();//获取字段名称列表,填充ui->groupBoxSort组件//更新actions和界面组件的使能状态
ui->actOpenDB->setEnabled(false);ui->actRecAppend->setEnabled(true);
ui->actRecInsert->setEnabled(true);
ui->actRecDelete->setEnabled(true);
ui->actScan->setEnabled(true);ui->groupBoxSort->setEnabled(true);
ui->groupBoxFilter->setEnabled(true);
  • setModel() 函数–设置关联的数据模型

    void QDataWidgetMapper::setModel(QAbstractItemModel *model)
    

    用于设置 QDataWidgetMapper 将要使用的数据模型。参数 model 是一个指向 QAbstractItemModel 类型的指针

  • setSubmitPolicy() 函数–设置数据提交策略

    void setSubmitPolicy(QDataWidgetMapper::SubmitPolicy policy)
    

    其参数policy是一个枚举类型QDataWidgetMapper::SubmitPolicy。取值如下:

    • QDataWidgetMapper::AutoSubmit:自动,行切换时将自动提交修改。
    • QDataWidgetMapper::ManualSubmit:手动,需调用 submit() 方法,手工提交当前记录的修改。
  • addMapping() 函数 – 用于设置界面组件与数据模型的列的映射,这种映射关系使得控件的值可以与数据模型中的特定项关联起来

    void QDataWidgetMapper::addMapping(QWidget *widget, int section)
    

    参数 widget 是指向 UI 控件的指针,section 指定了数据模型中的列(如果方向是水平的)或行(如果方向是垂直的)

  • setCurrentIndex() 函数 – 将当前行数据映射到界面组件, 使界面上的编辑框、下拉列表框等与字段关联的界面组件显示当前记录的内容

    virtual void setCurrentIndex(int index)
    

    例如:

    dataMapper->setCurrentIndex(current.row()); //更新当前行数据映射
    
  • setCurrentModelIndex() 函数–当用户在视图中选择不同的行或列时,自动更新与之关联的表单或控件的数据。

    [slot] void QDataWidgetMapper::setCurrentModelIndex(const QModelIndex &index)
    
  • revert() 和 submit() 函数用于手工取消或提交当前记录的修改。

  • toFirst()、toPrevious()、toNext() 和 toLast() 函数用于在记录间移动

    如:toFirst()函数用于移动到首记录

获取数据表的所有字段名称

  使用不带参数的 record() 函数获取数据表的所有字段名称,并填充到排序的下拉列表框中

void MainWindow::getFieldNames()
{ //获取所有字段名称QSqlRecord  emptyRec=tabModel->record();//获取空记录,只有字段名for (int i=0;i<emptyRec.count();i++)ui->comboFields->addItem(emptyRec.fieldName(i));
}

4.添加、插入与删除记录

  使用 insertRow() 函数在数据模型的 row 行前面插入一行记录,如果 row 大于或等于数据模型的总行数,则在最后添加一行记录。最后,选中刚插入的那一行记录。

void MainWindow::on_actRecAppend_triggered()
{//添加记录tabModel->insertRow(tabModel->rowCount(),QModelIndex()); //在末尾添加一个记录QModelIndex curIndex=tabModel->index(tabModel->rowCount()-1,1);//创建最后一行的ModelIndextheSelection->clearSelection();//清空选择项theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);//设置刚插入的行为当前选择行int currow=curIndex.row(); //获得当前行tabModel->setData(tabModel->index(currow,0),2000+tabModel->rowCount()); //自动生成编号tabModel->setData(tabModel->index(currow,2),"男");
// 插入行时设置缺省值,需要在primeInsert()信号里去处理
}void MainWindow::on_actRecInsert_triggered()
{//插入记录QModelIndex curIndex=ui->tableView->currentIndex();tabModel->insertRow(curIndex.row(),QModelIndex());theSelection->clearSelection();//清除已有选择theSelection->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}

  使用 removeRow() 函数删除选中的那一行记录。

void MainWindow::on_actRecDelete_triggered()
{//删除当前记录QModelIndex curIndex=theSelection->currentIndex();//获取当前选择单元格的模型索引tabModel->removeRow(curIndex.row()); //删除最后一行
}

在插入或删除记录操作,未提交保存之前, tableView 的左侧表头会以标记表示记录编辑状态,"*"表示新插入的记录,”!” 表示删除的记录 。在保存或取消修改,这些标记就消失,删除的记录行也从 tableView 里删除。

5.保存与取消修改

  在打开数据表初始化时,设置数据模型的编辑策略为 OnManualSubmit,即手动提交修改。当数据模型的数据被修改后,不管是直接修改字段值,还是插入或删除记录,在未提交修改前,QSqlTableModel::isDirty() 函数返回 true,就是利用这个函数在槽函数 on_currentChanged() 里设置 ”保存修改“和”取消修改“ 按钮的使能状态。

  使用 submitAll() 函数用于将数据表所有未提交的修改保存到数据库中;使用 revertAll() 函数来取消所有修改。

void MainWindow::on_actRevert_triggered()
{//取消修改tabModel->revertAll();ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);
}void MainWindow::on_actSubmit_triggered()
{//保存修改bool res=tabModel->submitAll();if (!res)QMessageBox::information(this, "消息", "数据保存错误,错误信息\n"+tabModel->lastError().text(),QMessageBox::Ok,QMessageBox::NoButton);else{ui->actSubmit->setEnabled(false);ui->actRevert->setEnabled(false);}
}

6.设置和清除照片

  设置照片功能是用文件对话框选择一个图片文件,读取文件内容到 QByteArray 类型的变量data里,获取当前记录到变量 curRec 后,用 QSqlRecord 的 setValue() 函数为 Photo 字段设置数据为 data,然后用 setRecord() 函数更新当前记录的数据到数据模型,并在界面组件上显示。

注意:这里的更新只是更新到数据模型,并没有更新到数据库。

void MainWindow::on_actPhoto_triggered()
{
//设置照片QString aFile=QFileDialog::getOpenFileName(this,"选择图片文件","","照片(*.jpg)");if (aFile.isEmpty())return;QByteArray data;QFile* file=new QFile(aFile); //fileName为二进制数据文件名file->open(QIODevice::ReadOnly);data = file->readAll();file->close();int curRecNo=theSelection->currentIndex().row();QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录curRec.setValue("Photo",data); //设置字段数据tabModel->setRecord(curRecNo,curRec);QPixmap pic;pic.load(aFile);  //在界面上显示ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->width()));
}

  清楚照片的功能是获取当前记录到变量 curRec 后,调用 setNull () 函数将 Photo 字段设置为 NULL,就是清除了字段的内容,然后更新记录到数据模型,并清除界面组件的显示。

void MainWindow::on_actPhotoClear_triggered()
{int curRecNo=theSelection->currentIndex().row();QSqlRecord  curRec=tabModel->record(curRecNo); //获取当前记录curRec.setNull("Photo");//设置为空值tabModel->setRecord(curRecNo,curRec);ui->dbLabPhoto->clear();
}

7.数据记录的遍历

  使用 record(int index) 函数获取每一行记录,并对该行记录的值进行修改。

void MainWindow::on_actScan_triggered()
{//涨工资,记录遍历if (tabModel->rowCount()==0)return;for (int i=0;i<tabModel->rowCount();i++){QSqlRecord aRec=tabModel->record(i); //获取当前记录float salary=aRec.value("Salary").toFloat();salary=salary*1.1;aRec.setValue("Salary",salary);tabModel->setRecord(i,aRec);}// 索引方式刷新记录,速度一样
//    float   salary;
//    for (int i=0;i<tabModel->rowCount();i++)
//    {
//        salary=tabModel->data(tabModel->index(i,10)).toFloat();
//        salary=salary*1.1;
//        tabModel->setData(tabModel->index(i,10),salary);
//    }if (tabModel->submitAll())QMessageBox::information(this, "消息", "涨工资计算完毕",QMessageBox::Ok,QMessageBox::NoButton);
}

8.记录排序

  使用 setSort() 函数设置数据表根据某个字段按照升序或降序排列,实际上就是设置 SQL 语句里的 ORDER BY 子句。在调用 setSort() 函数设置排序规则后,需要调用 QSqITableModel::select() 重新读取数据表的数据才会使排序规则生效。

void MainWindow::on_comboFields_currentIndexChanged(int index)
{//选择字段进行排序if (ui->radioBtnAscend->isChecked())tabModel->setSort(index,Qt::AscendingOrder);elsetabModel->setSort(index,Qt::DescendingOrder);tabModel->select();
}void MainWindow::on_radioBtnAscend_clicked()
{//升序tabModel->setSort(ui->comboFields->currentIndex(),Qt::AscendingOrder);tabModel->select();
}void MainWindow::on_radioBtnDescend_clicked()
{//降序tabModel->setSort(ui->comboFields->currentIndex(),Qt::DescendingOrder);tabModel->select();
}

9.记录过滤

  使用 setFilter() 函数设置记录的过滤条件,实际上就是设置 SQL 语句里的 WHERE 子句。调用 setFilter() 后无需调用 select() 函数就可以立即刷新记录,若要取消过滤条件,只需在 setFilter() 函数里传递一个空字符串。

void MainWindow::on_radioBtnMan_clicked()
{tabModel->setFilter(" Gender='男' ");
//    tabModel->select();
}void MainWindow::on_radioBtnWoman_clicked()
{tabModel->setFilter(" Gender='女' ");
//    tabModel->select();
}void MainWindow::on_radioBtnBoth_clicked()
{tabModel->setFilter("");
}

相关文章:

Qt基础 | QSqlTableModel 的使用

文章目录 一、QSqlTableModel 的使用1.主窗口MainWindow类定义2.构造函数3.打开数据表3.1 添加 SQLite 数据库驱动、设置数据库名称、打开数据库3.2 数据模型设置、选择模型、自定义代理组件、界面组件与模型数据字段间的数据映射 4.添加、插入与删除记录5.保存与取消修改6.设置…...

RPA软件-影刀使用

流程自动化 影刀将操作进行抽象&#xff0c;分为一下几个对象&#xff1a; 网页自动化 &#xff08;1&#xff09; 网页自动化应用场景&#xff1a;网页操作、数据抓取 &#xff08;2&#xff09; 网页操作&#xff1a;基础操作-指令操作&#xff0c;智能操作-关联元素&#…...

HarmonyOS NEXT零基础入门到实战-第四部分

自定义组件: 概念: 由框架直接提供的称为 系统组件&#xff0c; 由开发者定义的称为 自定义组件。 源代码&#xff1a; Component struct MyCom { build() { Column() { Text(我是一个自定义组件) } } } Component struct MyHeader { build() { Row(…...

vue2获取视频时长

使用HTML5的video标签和JavaScript&#xff1a; <template><video ref"video" autoplay controls loop muted loadedmetadata"getVideoDuration"><source src"https://desktop-yikao.oss-cn-beijing.aliyuncs.com/avatar/kaissp.mp4&q…...

Linux中进程的控制

一、进程的创建 1、知识储备 进程的创建要调用系统接口&#xff0c;头文件 #include<unistd.h> 函数fork() 由于之前的铺垫我们现在可以更新一个概念 进程 内核数据结构&#xff08;task_struct, mm_struct, 页表....&#xff09; 代码 数据 所以如何理解进程的独…...

【源码】Sharding-JDBC源码分析之JDBC

Sharding-JDBC系列 1、Sharding-JDBC分库分表的基本使用 2、Sharding-JDBC分库分表之SpringBoot分片策略 3、Sharding-JDBC分库分表之SpringBoot主从配置 4、SpringBoot集成Sharding-JDBC-5.3.0分库分表 5、SpringBoot集成Sharding-JDBC-5.3.0实现按月动态建表分表 6、【…...

Java | Leetcode Java题解之第273题整数转换英文表示

题目&#xff1a; 题解&#xff1a; class Solution {String[] singles {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};String[] t…...

数据结构之深入理解简单选择排序:原理、实现与示例(C,C++)

文章目录 一、简单选择排序原理二、C/C代码实现总结&#xff1a; 在计算机科学中&#xff0c;排序算法是一种非常基础且重要的算法。简单选择排序&#xff08;Selection Sort&#xff09;作为其中的一种&#xff0c;因其实现简单、易于理解而受到许多初学者的喜爱。本文将详细介…...

使用vscode搜索打开的文件夹下的文件

右键空白处打开命令面板 摁一次删除键&#xff0c;删除掉图中的大于号 这样就能够找到例化的模块&#xff0c;文件具体在哪个位置&#xff0c;然后打开了...

力扣778.水位上升的泳池中游泳

力扣778.水位上升的泳池中游泳 二分 bfs class Solution {int dx[4] {1,0,-1,0},dy[4] {0,1,0,-1};public:int swimInWater(vector<vector<int>>& grid) {int n grid.size();auto check [&](int mid) -> bool{queue<pair<int,int>>…...

Nacos-2.4.0最新版本docker镜像,本人亲自制作,部署十分方便,兼容postgresql最新版本17和16,奉献给大家了

基于Postgresql数据库存储的nacos最新版本2.4.0,采用docker镜像安装方式 因业务需要,为了让nacos支持postgresql,特意花了两天时间修改了源码,然后制作了docker镜像,如果你也在找支持postgresql的nacos最新版本,恭喜你,你来的正好~ nacos-2.4.0 postgresql的数据库脚本…...

Halcon机器视觉15种缺陷检测案例_9找出所有网格顶点的位置

Halcon机器视觉15种缺陷检测案例_9找出所有网格顶点的位置 效果 原图 代码 *9找出所有网格顶点的位置 dev_update_off ()read_image (Image, 9找出所有风格顶点的位置) get_image_size (Image, Width, Height) *关闭已打开的窗口 dev_close_window ()dev_open_window (0, 0, …...

w30-python02-pytest入门

代码如下&#xff1a; import pytest class Test_Obj:"""测试类"""#用例级别前后置def setup(self):print(用例级别------的前置处理)def teardown(self):print("用例级别--------的后置处理")# 用例def test_case1(self):print(&quo…...

WPF+Mvvm项目入门完整教程-仓储管理系统(二)

目录 一、搭建一个主界面框架二、实现步骤1.主界面区域划分2.主界面区域实现 一、搭建一个主界面框架 主要实现主界面的框架样式和基础功能。这里特别说明一下&#xff0c;由于MvvmLight 已经过时不在维护&#xff0c;本项目决定将MvvmLight框架变更为 CommunityToolkit.Mvvm …...

SkyWalking入门搭建【apache-skywalking-apm-10.0.0】

Java学习文档 视频讲解 文章目录 一、准备二、服务启动2-1、Nacos启动2-2、SkyWalking服务端启动2-3、SkyWalking控制台启动2-4、自定义服务接入 SkyWalking 三、常用监控3-1、服务请求通过率3-2、服务请求拓扑图3-3、链路 四、日志配置五、性能剖析六、数据持久化6-1、MySQL持…...

exo项目目录架构

目录 .yml 文件是 YAML(YAML Aint Markup Language) exo项目目录架构 文件作用 topology、viz:项目拓扑结构可视化相关的代码或工具。 项目目录架构 文件作用 .yml 文件是 YAML(YAML Aint Markup Language) 文件的扩展名,YAML 是一种人类可读的数据序列化标准,通…...

mysql中where与on区别

WHERE子句 作用范围&#xff1a;WHERE子句主要用于过滤FROM子句返回的结果集。它可以在SELECT、UPDATE、DELETE语句中使用&#xff0c;以限制哪些行被包含在最终的查询结果中&#xff0c;或者哪些行被更新或删除。应用场景&#xff1a;当需要基于某些条件过滤结果集时&#xf…...

filebeat把日志文件上传到Es中配置(ES7版本)

默认的filebeat配置会把所有的索引都放到一个文件中&#xff0c;通过摸索发现可以自定义索引的名字、模板、生命周期 &#xff08;重点注意&#xff09;该配置文件只适应于ES版本是7&#xff0c;不适应于8的版本&#xff0c;两个版本的配置文件差异很大 /app/logs/info.log日…...

Vue Router基础

Router 的作用是在单页应用&#xff08;SPA&#xff09;中将浏览器的URL和用户看到的内容绑定起来。当用户在浏览不同页面时&#xff0c;URL会随之更新&#xff0c;但页面不需要从服务器重新加载。 1 Router 基础 RouterView RouterView 用于渲染当前URL路径对应的路由组件。…...

Apache压测工具ab(Apache Bench)工具的下载安装和使用示例

场景 Jmeter进行http接口压力测试&#xff1a; Jmeter进行http接口压力测试_接口压测两万量-CSDN博客 上面讲压测工具Jmeter的使用&#xff0c;下面介绍另外一个ab(Apache Bench)压测工具的使用。 apache bench apache bench是apache自带的压力测试工具。 ab不仅可以对ap…...

IPIDEA与Python爬虫:联手解锁全球电商数据宝库

IPIDEA与Python爬虫&#xff1a;联手解锁全球电商数据宝库 如何运用代理IP在电商领域进行高效数据采集。特别是在遭遇访问限制的情况下&#xff0c;如何优雅地绕过那些恼人的访问管理机制。当然&#xff0c;在我们的探险之旅中&#xff0c;开源神器PlugLink也将适时出场&#…...

Fine-BI学习笔记

官方学习文档&#xff1a;快速入门指南- FineBI帮助文档 FineBI帮助文档 (fanruan.com) 1.零基础入门 1.1 功能简介 完成四个流程&#xff1a;新建分析主题、添加数据、分析数据、分享协作。 示例数据获取&#xff1a;5分钟上手FineBI - FineBI帮助文档 (fanruan.com) 1.2 …...

AI 辅助编程 Coding AI 辅助研发组织的技术蓝图

简简单单 Online zuozuo:欢迎商业合作 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo :联系我们:VX :tja6288 / EMAIL: 347969164@qq.com 文章目录 AI 辅助编程 Coding A…...

VScode 批量操作

VScode 批量操作 批量修改 按住 alt/option 键&#xff0c; 选择需要批量操作的位置 如果是多行&#xff0c;则按住 altshift 键 可以直接操作 但是有时候比如变量命名&#xff0c;可能需要递增操作的命名 需要下载插件 Increment Selection 按照1的方法多选光标之后&am…...

【Linux】管道通信和 system V 通信

文章目录 一、进程通信原理&#xff08;让不同进程看到同一份资源&#xff09;二、管道通信2.1 管道原理及其特点2.1 匿名管道和命名管道 三、共享内存通信3.1 共享内存原理3.2 创建和关联共享内存3.3 去关联、ipc 指令和删除共享内存 四、消息队列和信号量&#xff08;了解&am…...

Python | Leetcode Python题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; class Solution { public:// 判断是否为完全平方数bool isPerfectSquare(int x) {int y sqrt(x);return y * y x;}// 判断是否能表示为 4^k*(8m7)bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7;}int numSquares(i…...

mysql定时备份

为什么写这篇文章 最近项目里面需要定时备份mysql的数据&#xff0c;网上找了下&#xff0c;找到了一些比较好的解决方案。但是发现有几个地方与自己不匹配&#xff0c;我期望有如下 备份过程不能锁表&#xff0c;网上很多都是会锁表备份定时任务无法执行&#xff0c;但是手动…...

数据结构:逻辑结构与物理结构

逻辑结构与物理结构 逻辑结构1. 集合结构2. 线性结构3. 树形结构4. 图形结构 物理结构1. 顺序存储结构2. 链式存储结构 示例逻辑结构的示例&#xff1a;线性表物理结构的示例 结论 逻辑结构 逻辑结构描述了数据元素之间的逻辑关系&#xff0c;它是数据结构的抽象描述&#xff…...

pycharm报错:No module named pip/No module named pytest

1、问题概述? 今天在执行一个python脚本的时候,控制台提示:No module named pytest,就是没有pytest模块,于是我使用pip命令进行安装,命令如下; pip install pytest 结果又提示No module named pip,说我没有pip模块,没办法,再安装pip 2、安装pip-方式1 在pycharm的T…...

Linux:Linux权限

目录 1. Linux权限的概念 2. Linux权限管理 2.1 文件访问者的分类 2.2 文件类型和访问权限 2.2.1 文件类型 2.2.2 基本权限 2.3 文件权限值的表示方法 2.4 文件访问权限的相关设置方法 2.4.1 chmod 2.4.2 chown 2.4.3 chgrp 2.4.4 umask 3. file指令 4. Linux目…...

新版Glide检测生命周期原理

本文章使用的是glide 4.15.1 public class RequestManagerRetriever implements Handler.Callback {rivate final LifecycleRequestManagerRetriever lifecycleRequestManagerRetriever;public RequestManagerRetriever(Nullable RequestManagerFactory factory, GlideExperim…...

Ansible的脚本-----playbook剧本【上】

目录 1.playbook剧本组成 2.playbook剧本实战演练 2.1 实战演练一&#xff1a;给被管理主机安装httpd服务 2.2 实战演练二&#xff1a;定义、引用变量 2.3 实战演练三&#xff1a;指定远程主机sudo切换用户 2.4 实战演练四&#xff1a;when条件判断 2.5 实战演练五&…...

sql注入学习与防护

一、SQL注入分类 SQL注入根据攻击方式的不同&#xff0c;可以分为以下几种类型&#xff1a; 数字型注入字符型注入报错注入布尔盲注时间盲注联合查询注入基于堆叠的查询注入 二、SQL注入流程 发现注入点猜测字段数确定显示字段获取数据库信息获取数据库中的表获取表中的字段获…...

饥荒dst联机服务器搭建基于Ubuntu

目录 一、服务器配置选择 二、项目 1、下载到服务器 2、解压 3、环境 4、启动面板 一、服务器配置选择 首先服务器配置需要2核心4G&#xff0c;4G内存森林加洞穴大概就占75% 之后进行服务器端口的开放&#xff1a; tcp:8082 tcp:8080 UDP:10888 UDP:10998 UDP:10999 共…...

AtCoder Beginner Contest 363

A - Piling Up 题意 不同的分数段有不同的^数量&#xff0c;Takahashi想要使得他的^数量增加&#xff0c;问他所需要的最少分数增幅。 思路 我们只需要找到下一阶段的下限。 a / 100 是本阶段 1 变成下一阶段&#xff0c;再 * 100变成下限&#xff0c;再与原来的相减即可…...

Protel DXP 面试题详解及参考答案(4万字长文)

解释Protel DXP的基本工作流程。 Protel DXP(现已更名为Altium Designer)是一款用于电子设计自动化(EDA)的软件,主要应用于印刷电路板(PCB)设计。其基本工作流程通常包括以下几个阶段: 项目创建与配置: 开始一个新的设计项目时,首先需要创建一个项目文件,在这个文件…...

雪花算法 集群uid重复问题 uid-generator-spring-boot-starter

1、在生成环境 在某个业务使用该插件生成uid,由于业务整合了 mybatis-plus模块 2、该业务是分部署集群部署以及使用的多线程获取uid&#xff0c;使用中发现唯一建冲突&#xff0c;生成的uid有重复。 然后查看日志发现 workerId 始终为0 怀疑是生成workerId出了问题。 查看跟…...

【AutoDL】AutoDL+Xftp+Xshell+VSCode配合使用教程

身边没有显卡资源或不足以训练模型时&#xff0c;可以租赁服务器的显卡。 1、AutoDL Step :注册账号->选择显卡->选择环境->开机启动 1.1 首先打开AutoDL官网&#xff0c;注册账号 1.2 租赁自己想要的显卡资源 1.3 选择基础环境。 此处&#xff0c;我们让其自动配置…...

使用minio cllient(mc)完成不同服务器的minio的数据迁移和mc基本操作

minio client 前言使用1.拉取minio client 镜像2.部署mc容器3.添加云存储服务器4.迁移数据1.全量迁移2.只迁移某个桶3.覆盖重名文件 5.其他操作1.列出所有alias、列出列出桶中的文件和目录1.1.列出所有alias1.2.列出桶中的文件和目录 2.创建桶、删除桶2.1.创建桶2.2.删除桶 3.删…...

Vue3分段控制器(Segmented)

效果如下图&#xff1a;在线预览 APIs Segmented 参数说明类型默认值必传block是否将宽度调整为父元素宽度&#xff0c;同时所有选项占据相同的宽度booleanfalsefalsedisabled是否禁用booleanfalsefalseoptions选项数据string[] | number[] | SegmentedOption[][]falsesize控…...

SpringSecurity如何正确的设置白名单

在SpringSecurity中,往往需要对部分接口白名单访问,而大部分在使用Security中就有一个误区,那就是免鉴权访问和白名单的区别。 大部分的Security文章包括官方文档给出免鉴权访问都是使用.permitAll()去对相应路径进行免鉴权访问,但实际上这仅仅只表示该资源不需要相应的权限访问…...

【Langchain大语言模型开发教程】评估

&#x1f517; LangChain for LLM Application Development - DeepLearning.AI 学习目标 1、Example generation 2、Manual evaluation and debug 3、LLM-assisted evaluation 4、LangChain evaluation platform 1、引包、加载环境变量&#xff1b; import osfrom dotenv imp…...

Python爬虫小项目实战

1.自动获取小说多个章节内容 2.获取英雄联盟里面的全部英雄 3. 简单地自动抽奖系统 4. 简单地点赞系统 5. 制作查询手机号工具 6. 制做登录系统 7. 操作excel办公自动化 8. 自动批量保存图片 9. 获取NBA数据 10. 获取彩票信息 11. 获取房地产信息 12. 获取小说…...

PHP Filesystem 简介

PHP Filesystem 简介 PHP 是一种广泛使用的开源服务器端脚本语言,特别适用于网页开发。在 PHP 中,Filesystem 是一个功能丰富的库,提供了一系列用于文件系统操作的函数。这些函数允许开发者读取、写入、修改和删除文件和目录,以及执行其他与文件系统相关的任务。 PHP Fil…...

源代码加密软件哪家好?五款企业级加密软件推荐

随着软件开发行业的快速发展&#xff0c;源代码作为核心资产&#xff0c;面临着越来越大的安全威胁。保护源代码不被泄露或盗用&#xff0c;是每个开发团队和企业都需要高度重视的问题。源代码加密软件通过对代码进行加密处理&#xff0c;确保其在传输和存储过程中保持机密性。…...

Redis常见的数据类型及操作方式

一、通用命令 1&#xff09;获取redis中所有key keys * 2&#xff09;删除一个或多个key del key1 key2 ... 3&#xff09;判断key是否存在 exists key 4&#xff09;给key添加过期时间 expire key time 5&#xff09;查看key剩余过期时间 ttl key 6) 查看redis内存…...

谷粒商城实战笔记-55-商品服务-API-三级分类-修改-拖拽数据收集

文章目录 一&#xff0c;拖拽后结点的parentCid的更新二&#xff0c;拖拽后结点的父节点下所有结点的sort排序属性的变化更新排序的逻辑代码分析 三&#xff0c;拖拽后结点及其子节点catLevel的变化判断是否需要更新 catLevel获取拖动后的新节点 更新 catLevel完整代码 这一节的…...

AI绘画入门实践|Midjourney:使用 --seed 制作情侣头像与漫画

在 Midjourney 中&#xff0c;seed 是指一个种子&#xff0c;用于生成图像时的起点或基础。 使用格式&#xff1a;--seed 获取的seed值 获取 seed 值 使用 seed 生成图像 a cute boys avatar, background with blue sky and white cloud, Ghibli Studio style, Hayao Miyazaki…...

笔记:Enum中FlagsAttribute特性的用法

一、目的&#xff1a;分享Enum中FlagsAttribute特性的用法 在C#中&#xff0c;Enum&#xff08;枚举&#xff09;类型可以使用[Flags]属性来表示一个枚举可以存储多个值。这是通过按位运算符&#xff08;如|&#xff08;或&#xff09;和&&#xff08;与&#xff09;&#…...

QWidget如何切换ui

在Qt中&#xff0c;QWidget及其子类用于构建图形用户界面。如果你想要在不同的UI之间切换&#xff0c;可以使用QStackedWidget&#xff0c;它可以管理一组QWidget&#xff0c;并且每次只显示其中一个。 以下是一个简单的例子&#xff0c;展示如何使用QStackedWidget切换UI&…...