QTableView使用示例-Qt模型视图代理(Model-View-Delegate)使用示例

news2024/11/16 23:30:37

         模型视图委托(MVD)是Qt中特有的设计模式,类似MVC设计模式,将MVC设计模式中的Controller当做MVD中的Delegate,两者的概念基本相同。不同的是委托不是独立存在,而是包含在视图里面。 模型视图委托设计模式中,模型负责存储和管理数据;视图负责显示数据,其中界面的框架和基础信息是视图负责,具体数据的显示是委托负责;委托不仅仅负责数据的显示,还有一个重要的功能是负责数据的编辑,如在视图中双击就可以编辑数据。

一、MVD简介

        QT当中model-view-delegate(模型-视图-代理),此结构实现数据和界面的分离。

        Qt的模型-视图结构分为三部分:模型(mode)-视图(view)-代理(Delegate) ,其中模型与数据源通信,并为其它部件提供接口;视图从模型中引用数据条的模型索引(Modellndex),在视图当中,代理负责绘制数据条目,比如编辑条目,代理和模型进行直接通信。

1、模型 (model): 实现自定义模型可以通过QAbstractltemModel类继承,也可以通过QAbstractListModel和QAbstractTableModel类继承实现列表模型或者表格模型
2、视图(view): 实现自定义的视图View,可以继承子QAbstractltemView类,对所需要的虚拟函数进行重定义。

3、代理 (delegate) :在表格当中嵌入各种不同的控件,通过表格中控件对编辑的内容进行操作。表格插入控件方式,控件始终显示。

二、简述

         本实例基于QT的委托代理机制实现的Qt模型视图代理(Model-View-Delegate)使用示例。以QTableView为基础,实现表头排序,列表复选框,插入按钮、下拉框、进度条。在Qt中,QTableView是一个用于显示表格数据的控件,可以使用Qt的模型视图代理(Model-View-Delegate)设计模式来定制QTableView的外观和行为。

三、效果 

四、核心代码  

student.h 学生信息

#ifndef STUDENT_H
#define STUDENT_H

#include <QtCore>

struct Student
{
    bool checked = false;
    quint16 id = 0;
    QString name;
    quint16 age = 0;
    QString gender = QObject::tr("男");
    quint16 achievement= 0;
    qint16 process = 50;
};

Q_DECLARE_METATYPE(Student);//将自定义类型声明为元类型(MetaType),以便在信号与槽机制中通过传递
Q_DECLARE_METATYPE(Student*);

#endif // STUDENT_H
1、下拉框委托类

comboboxdelegate.h

#ifndef COMBOBOXDELEGATE_H
#define COMBOBOXDELEGATE_H

#include <QStyledItemDelegate>

//下拉框委托类
class ComboBoxDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit ComboBoxDelegate(QObject *parent = nullptr)
        : QStyledItemDelegate(parent)
    {}

protected:
    QWidget *createEditor(QWidget *parent,
                          const QStyleOptionViewItem &,
                          const QModelIndex &) 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;
};

#endif // COMBOBOXDELEGATE_H

 comboboxdelegate.cpp

#include "comboboxdelegate.h"
#include "student.h"

#include <QtWidgets>

QWidget *ComboBoxDelegate::createEditor(QWidget *parent,
                                        const QStyleOptionViewItem &,
                                        const QModelIndex &) const
{
    QComboBox *comboBox = new QComboBox(parent);
    comboBox->addItems(QStringList() << tr("男") << tr("女"));
    return comboBox;
}

void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
    comboBox->setCurrentIndex(index.data(Qt::EditRole).toInt());
}

void ComboBoxDelegate::setModelData(QWidget *editor,
                                    QAbstractItemModel *model,
                                    const QModelIndex &index) const
{
    QComboBox *comboBox = qobject_cast<QComboBox *>(editor);
    model->setData(index, comboBox->currentText(), Qt::EditRole);
}
2、按钮委托类

buttondelegate.h

#ifndef BUTTONDELEGATE_H
#define BUTTONDELEGATE_H

#include <QStyledItemDelegate>

//按钮委托类
class ButtonDelegate : public QStyledItemDelegate
{
public:
    ButtonDelegate(QObject* parent = nullptr);

    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const override;

protected:
    bool editorEvent(QEvent *event, QAbstractItemModel *model,
                     const QStyleOptionViewItem &option,
                     const QModelIndex &index) override;

private:
    QScopedPointer<QStyleOptionButton> m_buttonPtr;
};

#endif // BUTTONDELEGATE_H

 buttondelegate.cpp

#include "buttondelegate.h"
#include "student.h"

#include <QPainter>
#include <QApplication>
#include <QMouseEvent>
#include <QtWidgets>

ButtonDelegate::ButtonDelegate(QObject *parent)
    : QStyledItemDelegate(parent)
    , m_buttonPtr(new QStyleOptionButton)
{

}

void ButtonDelegate::paint(QPainter *painter,
                           const QStyleOptionViewItem &option,
                           const QModelIndex &index) const
{
    int w = qMin(option.rect.width(), option.rect.height()) / 10.0;
    m_buttonPtr->rect = option.rect.adjusted(w, w, -w, -w);
    m_buttonPtr->text = index.model()->data(index).toString();
    m_buttonPtr->state |= QStyle::State_Enabled;

    painter->save();

    if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.highlight());
        painter->setBrush(option.palette.highlightedText());
    }

    QPushButton button;
    qApp->style()->drawControl(QStyle::CE_PushButton, m_buttonPtr.data(), painter, &button);

    painter->restore();
}

bool ButtonDelegate::editorEvent(QEvent *event,
                                 QAbstractItemModel *model,
                                 const QStyleOptionViewItem &option,
                                 const QModelIndex &index)
{
    int w = qMin(option.rect.width(), option.rect.height()) / 10.0;

    switch (event->type()) {
    case QEvent::MouseButtonPress:{
        QMouseEvent* mouseEvent =(QMouseEvent*)event;
        if (option.rect.adjusted(w, w, -w, -w).contains(mouseEvent->pos())) {
            m_buttonPtr->state |= QStyle::State_Sunken;
        }
    } break;
    case QEvent::MouseButtonRelease:{
        QMouseEvent* mouseEvent =(QMouseEvent*)event;
        if (option.rect.adjusted(w, w, -w, -w).contains(mouseEvent->pos())) {
            m_buttonPtr->state &= (~QStyle::State_Sunken);

            Student* stu = model->data(index, Qt::UserRole).value<Student*>();
            if(stu){
                QString details = tr("This Student id = %1, name = %2, age = %3, "
                                     "gender = %4, achievement = %5")
                                      .arg(stu->id)
                                      .arg(stu->name)
                                      .arg(stu->age)
                                      .arg(stu->gender)
                                      .arg(stu->achievement);
                QDialog dialog;
                QHBoxLayout *layout = new QHBoxLayout(&dialog);
                layout->addWidget(new QLabel(details, &dialog));
                dialog.exec();
            }
        }
    }
    break;
    default: break;
    }
    return true;
}
3、 进度条委托类

progressbardelegate.h

#ifndef PROGRESSBARDELEGATE_H
#define PROGRESSBARDELEGATE_H

#include <QStyledItemDelegate>

//进度条委托类
class ProgressBarDelegate : public QStyledItemDelegate
{
public:
    ProgressBarDelegate(QObject* parent = nullptr) : QStyledItemDelegate(parent) {}

    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
};

#endif // PROGRESSBARDELEGATE_H

 progressbardelegate.cpp

#include "progressbardelegate.h"

#include <QPainter>
#include <QtWidgets>

void ProgressBarDelegate::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);

    int value = index.model()->data(index).toUInt();
    if (value < 0)
        value = 0;
    else if (value > 100)
        value = 100;
    int w = qMin(option.rect.width(), option.rect.height()) / 10.0;
    QStyleOptionProgressBar progressBarOption;
    progressBarOption.initFrom(option.widget);
    progressBarOption.rect = option.rect.adjusted(w, w, -w, -w);
    progressBarOption.minimum = 0;
    progressBarOption.maximum = 100;
    progressBarOption.textAlignment = Qt::AlignCenter;
    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());
    }

    QProgressBar progressBar;
    qApp->style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter, &progressBar);

    painter->restore();
}
 4、排序代理

sortfilterproxymodel.h

#ifndef SORTFILTERPROXYMODEL_H
#define SORTFILTERPROXYMODEL_H

#include <QSortFilterProxyModel>

//排序代理
class SortFilterProxyModel : public QSortFilterProxyModel
{
public:
    SortFilterProxyModel(QObject *parent = nullptr)
        : QSortFilterProxyModel(parent) {}

protected:
    bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; //重定义排序规则
};

#endif // SORTFILTERPROXYMODEL_H

      sortfilterproxymodel.cpp  

#include "sortfilterproxymodel.h"

#include <QDateTime>

bool SortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
    QVariant leftData = sourceModel()->data(left);
    QVariant rightData = sourceModel()->data(right);

    if (leftData.userType() == QMetaType::QDateTime) {
        return leftData.toDateTime() < rightData.toDateTime();
    } else if(leftData.userType() == QMetaType::Int) {
        return leftData.toInt() > rightData.toInt();
    }
    QString leftString = leftData.toString();
    QString rightString = rightData.toString();
    return QString::localeAwareCompare(leftString, rightString) < 0;
}
5、学生数据表数据模型

 studenttablemodel.h

#ifndef STUDENTTABLEMODEL_H
#define STUDENTTABLEMODEL_H

#include <QAbstractTableModel>

struct Student;
class StuedentTableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit StuedentTableModel(QObject *parent = nullptr): QAbstractTableModel(parent){}

    int rowCount(const QModelIndex & = QModelIndex()) const { return m_students.count(); }
    int columnCount(const QModelIndex & = QModelIndex()) const { return 7; }

    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    void setStudents(const QList<Student *> &students);

private:
    QList<Student *> m_students;
};

#endif // STUDENTTABLEMODEL_H

 studenttablemodel.cpp

#include "studenttablemodel.h"
#include "student.h"

enum Property { ID, NAME, AGE, GENDER, ACHIEVEMENT, MENUBUTTON, PROCESS };

QVariant StuedentTableModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return false;

    int row = index.row();
    int col = index.column();

    Student *stu = m_students.at(row);
    switch (role) {
    case Qt::TextAlignmentRole: return Qt::AlignCenter;
    case Qt::CheckStateRole:
        switch (col) {
        case ID: return stu->checked;
        default: break;
        }
        break;
    case Qt::DisplayRole:
    case Qt::EditRole: { //双击为空需添加
        switch (col) {
        case ID: return stu->id;
        case NAME: return stu->name;
        case AGE: return stu->age;
        case GENDER: return stu->gender;
        case ACHIEVEMENT: return stu->achievement;
        case MENUBUTTON: return tr("Detail");
        case PROCESS: return stu->process;
        default: break;
        }
    case Qt::UserRole: {
        switch (col) {
        case MENUBUTTON: return QVariant::fromValue(stu);
        default: break;
        }
    }
    }
    default: break;
    }
    return QVariant();
}

bool StuedentTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;

    int row = index.row();
    int col = index.column();

    Student *stu = m_students[row];
    switch (role) {
    case Qt::CheckStateRole:
        switch (col) {
        case ID:
            stu->checked = !stu->checked;
            emit dataChanged(index, index);
            return true;
        default: break;
        }
        break;
    case Qt::EditRole:
        switch (col) {
        case ID: stu->id = value.toUInt(); break;
        case NAME: stu->name = value.toString(); break;
        case AGE: stu->age = value.toUInt(); break;
        case GENDER: stu->gender = value.toString(); break;
        case ACHIEVEMENT: stu->achievement = value.toUInt(); break;
        case PROCESS: stu->process = value.toUInt(); break;
        }
        emit dataChanged(index, index);
        return true;
    default: break;
    }
    return false;
}

QVariant StuedentTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    const QStringList names = {tr("ID"),
                               tr("姓名"),
                               tr("年龄"),
                               tr("性别"),
                               tr("成绩"),
                               tr("详情"),
                               tr("进度")};
    if (section < 0 || section >= names.size())
        return QVariant();

    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return names.at(section);
    return QVariant();
}

Qt::ItemFlags StuedentTableModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags = QAbstractTableModel::flags(index);
    flags |= Qt::ItemIsEditable;
    if (index.column() == ID)
        flags |= Qt::ItemIsUserCheckable;
    return flags;
}

void StuedentTableModel::setStudents(const QList<Student *> &students)
{
    beginResetModel(); //重置数据之前调用,会自动触发 modelAboutToBeReset 信号
    m_students = students;
    endResetModel();   //重置数据完成后调用,会自动触发 modelReset 信号
}
 6、学生数据表

stuedenttable.h

#ifndef STUDENTTABLE_H
#define STUDENTTABLE_H

#include <QAbstractTableModel>
#include <QStyledItemDelegate>
#include <QTableView>

struct Student;
class StuedentTableModel;
class StudentsTable : public QTableView
{
    Q_OBJECT
public:
    StudentsTable(QWidget *parent = nullptr);

    void setStudents(const QList<Student *> &students);

protected:
    void contextMenuEvent(QContextMenuEvent *event) override;

signals:
    void insertItem();
    void removeItem();

private:
    void initMenu();

    StuedentTableModel *m_stuModel;
    QMenu *m_menu;
};

#endif // STUDENTTABLE_H

 stuedenttable.cpp

#include "stuedenttable.h"
#include "buttondelegate.h"
#include "comboboxdelegate.h"
#include "progressbardelegate.h"
#include "sortfilterproxymodel.h"
#include "studenttablemodel.h"

#include <QtWidgets>

StudentsTable::StudentsTable(QWidget *parent)
    : QTableView(parent)
    , m_stuModel(new StuedentTableModel(this))
    , m_menu(new QMenu(this))
{
    setShowGrid(true);
    setWordWrap(false);
    setAlternatingRowColors(true);
    verticalHeader()->setVisible(false);
    verticalHeader()->setDefaultSectionSize(30);
    horizontalHeader()->setStretchLastSection(true);
    horizontalHeader()->setDefaultSectionSize(90);
    horizontalHeader()->setMinimumSectionSize(35);
    horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    setSelectionBehavior(QAbstractItemView::SelectItems);
    setSelectionMode(QAbstractItemView::SingleSelection);
    setContextMenuPolicy(Qt::DefaultContextMenu);

    //设置委托
    setItemDelegateForColumn(3, new ComboBoxDelegate(this)); //下拉框
    setItemDelegateForColumn(5, new ButtonDelegate(this));  //按钮
    setItemDelegateForColumn(6, new ProgressBarDelegate(this)); //进度条

    //设置代理实现自定义排序
    setSortingEnabled(true);
    SortFilterProxyModel *sortModel = new SortFilterProxyModel(this);
    sortModel->setSourceModel(m_stuModel);
    setModel(sortModel);

    initMenu();
}

void StudentsTable::setStudents(const QList<Student *> &students)
{
    m_stuModel->setStudents(students);
}

void StudentsTable::contextMenuEvent(QContextMenuEvent *event)
{
    if (!currentIndex().isValid())
        return;
    m_menu->exec(mapToGlobal(event->pos()));
}

void StudentsTable::initMenu()
{
    m_menu->addAction(tr("insert"), this, &StudentsTable::insertItem);
    m_menu->addAction(tr("remove"), this, &StudentsTable::removeItem);
    m_menu->addAction(tr("rename"), this, [this] { edit(currentIndex().siblingAtColumn(0)); });
}

五、使用示例

以下是一个简单的示例代码,演示了如何在Qt中使用StudentsTable控件:

mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

struct Student;
class StudentsTable;
class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void onInsertItem();
    void onRemoveItem();

private:
    void init();
    void setupUI();
    StudentsTable *m_table;
    QList<Student *> m_students;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "student.h"
#include "studenttablemodel.h"
#include "stuedenttable.h"

#include <QtWidgets>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setupUI();
    init();
    resize(800, 300);
}

MainWindow::~MainWindow()
{
    if (!m_students.isEmpty()) {
        qDeleteAll(m_students);
        m_students.clear();
    }
}

void MainWindow::onInsertItem()
{
    int row = m_table->currentIndex().row();
    Student *stu = new Student;
    stu->id = m_students.size();

    if (row < 0 || row >= m_students.size())
        m_students.append(stu);
    else
        m_students.insert(row, stu);

    m_table->setStudents(m_students);
}

void MainWindow::onRemoveItem()
{
    QModelIndex index = m_table->currentIndex();
    if (!index.isValid())
        return;
    int row = index.row();
    delete m_students.takeAt(row);
    m_table->setStudents(m_students);
}

void MainWindow::init()
{
    m_students.append(new Student{true, 0, "Jason", 15, "男", 66, 10});
    m_students.append(new Student{false, 1, "Lily", 13, "女", 85, 20});
    m_students.append(new Student{true, 2, "Odin", 16, "女", 76, 30});
    m_students.append(new Student{false, 3, "Willion", 12, "男", 89, 40});
    m_students.append(new Student{true, 4, "Nieo", 14, "男", 77, 50});
    m_table->setStudents(m_students);
    m_table->selectRow(m_students.size() - 1);
}

void MainWindow::setupUI()
{
    QPushButton *addBtn = new QPushButton(tr("增加"), this);
    QPushButton *removeBtn = new QPushButton(tr("删除"), this);
    m_table = new StudentsTable(this);

    QHBoxLayout *hLayout = new QHBoxLayout;
    hLayout->addStretch(1);
    hLayout->addWidget(addBtn);
    hLayout->addWidget(removeBtn);
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addLayout(hLayout);
    layout->addWidget(m_table);
    QFrame *frame = new QFrame(this);
    frame->setLayout(layout);
    setCentralWidget(frame);

    connect(m_table, &StudentsTable::insertItem, this, &MainWindow::onInsertItem);
    connect(m_table, &StudentsTable::removeItem, this, &MainWindow::onRemoveItem);
    connect(addBtn, &QPushButton::clicked, this, &MainWindow::onInsertItem);
    connect(removeBtn, &QPushButton::clicked, this, &MainWindow::onRemoveItem);
}

        到此本文基于QTableView的Model View Delegate使用方法就介绍到这了。

        总的来说,Qt的模型视图代理提供了一种灵活的方式来显示和编辑数据,在处理大量数据和复杂数据结构时特别有用。它将数据与界面分离,使得数据的表示和样式能够独立于数据本身进行修改。这种模式不仅提高了开发效率,还使得代码更加清晰和易于维护。

        谢谢您的阅读,希望本文能为您带来一些帮助和启发。如果您有任何问题或意见,请随时与我联系。祝您度过美好的一天!

六、源代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

#71结构体案例2(三国游戏,冒泡排序)

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <string> using namespace std;//英雄结构体 struct Hero {string name;int age;string gender; };//冒泡排序 void bubbleSort(struct Hero hArray[],int len) {for(int i0;i<len-1;i){for(i…

CentOS 8 本地创建yum源

1.获取iso (有iso就可以建立本地repo) 如CentOS-8.5.2111-aarch64-dvd1.iso 2.解压iso&#xff08;mount挂载就可以吧iso解压到linux某一目录中&#xff09; mkdir /mnt/cdrom mount -o loop ./CentOS-Stream-8-aarch64-20220913-dvd1.iso /mnt/cdrom ls /mnt/cdrom 3.编…

奇偶函数的性质及运算

目录 定义 注意 特征 运算 拓展 定义 设函数f(x)的定义域D&#xff1b; 如果对于函数定义域D内的任意一个x&#xff0c;都有f(-x)&#xff0d;f&#xff08;x&#xff09;&#xff0c;那么函数f&#xff08;x&#xff09;就叫做奇函数。如果对于函数定义域D内的任意一个x…

【前端】 如何在 Vue.js 中使用 Mock 数据:教程与技巧

如何在 Vue.js 中使用 Mock 数据&#xff1a;教程与技巧 在开发过程中&#xff0c;为了测试和开发前端功能&#xff0c;你常常需要用到模拟&#xff08;mock&#xff09;数据。Vue.js 提供了灵活的方式来处理数据请求和更新&#xff0c;但在没有真实后端的情况下&#xff0c;我…

在 VueJS 中使用事件委托处理点击事件(事件委托,vue事件委托,什么是事件委托,什么是vue的事件委托)

前言 在开发 Vue 项目时&#xff0c;我们经常需要处理大量的点击事件。为每个可点击的元素单独添加事件监听器不仅会增加代码的复杂度&#xff0c;还会降低性能。事件委托是一种有效的优化方式&#xff0c;它可以显著减少事件监听器的数量&#xff0c;提高代码的可维护性和执行…

SSM禾泽校园学生商品交易平台-计算机毕设定制-附项目源码(可白嫖)50284

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对禾泽校园学生商品交易平台等问题&#xff0…

部署PXE

一 准备工作 1.rhel7主机 2.开启主机图形init 5 开图形 3.配置网络可用 4.关闭vmware dhcp功能 将VMnet8本地DHCP服务关闭 二 部署kickstart 1.安装kichstart并开启 2.安装httpd并启动 3.测试 4.配置kickstart 左上角文件保存 在vim ks.cfg中配置软件 共享 测试 四 DHCP 1.…

mysql操作(进阶)

1.数据库约束 数据库自动对数据的合法性进行校验检查的一系列机制&#xff0c;目的是为了保证数据库中能够避免被插入或者修改一些非法数据。 &#xff08;1&#xff09;mysql中提供了以下的约束&#xff1a; a.NOT NULL&#xff1a;指定某列不能为null b.UNIQUE&#xff1…

防火墙工具iptables应用详解

文章目录 前言一、Netfilter内核二、Netfilter与iptables的关系三、iptables的表与链四、iptables的常用命令与参数五、 iptables使用案例 前言 iptables是Linux系统中一款强大的防火墙工具&#xff0c;它基于Netfilter内核模块&#xff0c;允许管理员定义数据包的转发、过滤和…

RabbitMQ中如何防止消息堆积的情况发生?

RabbitMQ中如何防止消息堆积的情况发生&#xff1f; 消息堆积是消息队列系统中常见的问题&#xff0c;尤其是在高负载环境下。RabbitMQ作为一个流行的消息代理系统&#xff0c;也不可避免地会遇到这种情况。为了防止消息堆积&#xff0c;我们可以采取以下几种方法&#xff1a;…

基于node.js中国传统节日介绍网站32006-计算机毕业设计项目选题推荐(附源码)

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;中国传统节日介绍网站当然也不能排除在外。中国传统节日介绍网站是以实际运用为开发背景&#xff0c;运用软件工程原理和…

Ubuntu22.04系统下,图像修复项目CodeFormer的部署——点动科技

Ubuntu22.04系统下&#xff0c;图像修复项目CodeFormer的部署——点动科技 一、前言&#xff1a;二、开始2.1 ubuntu和docker基本环境配置1.更新包列表&#xff1a;2. 安装docker依赖3. 添加docker密钥4.添加阿里云docker软件源5.安装docker6.安装完成docker测试7. docker配置国…

windows11远程桌面如何打开

随着远程办公的普及&#xff0c;选择合适的远程桌面工具变得尤为重要。在Windows 11上&#xff0c;用户可以利用系统自带的远程桌面功能&#xff0c;或选择更专业的第三方解决方案&#xff0c;如Splashtop。本文将详细介绍如何在Windows 11上启用远程桌面&#xff0c;并对比Win…

C语言——位运算

一、位运算符和位运算 C语言提供如下表所列出的位运算符&#xff1a; 说明&#xff1a; (1)位运算符中除&#xff5e;以外&#xff0c;均为二目(元)运算符&#xff0c;即要求两侧各有一个运算量。 (2)运算量只能是整型或字符型的数据&#xff0c;不能为实型数…

简单的docker学习 第4章 docker容器

第4章 Docker容器 4.1 容器基础 4.1.1 容器启动流程 通过 docker run 命令可以启动运行一个容器。该命令在执行时首先会在本地查找指定的镜像&#xff0c;如果找到了&#xff0c;则直接启动&#xff0c;否则会到镜像中心查找。如果镜像中心存在该镜像&#xff0c;则会下载到…

读零信任网络:在不可信网络中构建安全系统10认证身份

1. 用户所知道的信息 1.1. 只有用户本人知道的信息 1.2. 密码 1.2.1. 密码是常用的认证机制 1.2.2. 密码验证就是确认用户“所知”性的较好途径 1.2.3. 用户可以利用密码管理器来便捷地管理多个高强度密码&#xff0c;从而有效降低数据泄露风险 1.2.4. 长度足够长 1.2.4.1…

Docker数据管理,数据卷,容器服务器数据卷

一、容器的数据管理介绍 1.1 Docker容器分层 Docker镜像由多个只读层叠加而成&#xff0c;启动容器时&#xff0c;Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。 如果运行中的容器修改了现有的一个已经存在的文件&#xff0c;那该文件将会从读写层下面的只读层复制到…

GroupMamba实战:使用GroupMamba实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

基于NSGAII的的柔性作业调度优化算法MATLAB仿真,仿真输出甘特图

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于NSGAII的的柔性作业调度优化算法MATLAB仿真,仿真输出甘特图,完工时间:,延期,机器负载,机器能耗。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 &a…

Stack Overflow2024年度调查:76%的程序员正在或计划使用AI工具!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工具测评,AI效率提升,AI行业洞察。关注我,AI之路不迷路,2024我们一起变强。 1. 最受…