Qt QListView自定义树状导航控件

        大部分的软件都有多个页面,这时候就需要一个导航栏控件,通过在导航栏中选择某一栏,同时显示对应的页面。

        本文代码效果如下:

        本文的导航栏控件基于大佬 feiyangqingyun 的导航栏控件博客Qt/C++编写自定义控件46-树状导航栏_qt之实现自定义树状图控件-CSDN博客做了美化,修复了一些会导致崩溃的bug。

        本文代码:https://download.csdn.net/download/Sakuya__/89420773?spm=1001.2014.3001.5501icon-default.png?t=N7T8https://download.csdn.net/download/Sakuya__/89420773?spm=1001.2014.3001.5501        也可以在这里下载大佬的代码学习:NavListView: Qt 自定义的树形导航控件icon-default.png?t=N7T8https://gitee.com/qt-open-source-collection/NavListView


代码之路

NavListView.h

#ifndef NAVLISTVIEW_H
#define NAVLISTVIEW_H


#include <QStyledItemDelegate>
#include <QAbstractListModel>
#include <QListView>
#include <vector>

class NavListView;

class NavDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    NavDelegate(QObject *parent);
    ~NavDelegate();

protected:
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const ;
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

private:
    NavListView *nav;
};


class NavModel : public QAbstractListModel
{
    Q_OBJECT
public:
    NavModel(QObject *parent);
    ~NavModel();

public:
    struct TreeNode {
        QString iconName;
        QString label;
        int level;
        bool collapse;
        bool theFirst;
        bool theLast;
        QString info;
        std::list<TreeNode *> children;
    };

    struct ListNode {
        QString label;
        TreeNode *treeNode;
    };

protected:
    int rowCount(const QModelIndex &parent) const;
    QVariant data(const QModelIndex &index, int role) const;

private:
    std::vector<TreeNode *> treeNode;
    std::vector<ListNode> listNode;

public slots:
    void readData(QString path);
    void setData(QStringList listItem);
    void collapse(const QModelIndex &index);

private:
    void refreshList();
};

class NavListView : public QListView
{
    Q_OBJECT
public:
    enum IcoStyle {IcoStyle_Cross = 0, IcoStyle_Triangle = 1};
    NavListView(QWidget *parent);
    ~NavListView();

    bool getInfoVisible() const {
        return infoVisible;
    }

    bool getLineVisible() const {
        return lineVisible;
    }

    bool getIcoColorBg() const {
        return icoColorBg;
    }

    IcoStyle getIcoStyle() const {
        return style;
    }

    QColor getColorLine() const {
        return colorLine;
    }
    /// ====== 获取背景颜色函数
    QColor getColorBgNormal() const{
        return colorBgNormal;
    }
    QColor getColorBgSelected() const{
        return colorBgSelected;
    }
    QColor getColorBgHover() const{
        return colorBgHover;
    }
    QColor getColorBgNormalLeval2() const{
        return colorBgNormalLeval2;
    }
    QColor getColorBgSelectedLeval2() const{
        return colorBgSelectedLeval2;
    }
    QColor getColorBgHoverLeval2() const{
        return colorBgHoverLeval2;
    }
    /// ====== 获取文字颜色函数
    QColor getColorTextNormal() const {
        return colorTextNormal;
    }
    QColor getColorTextSelected() const {
        return colorTextSelected;
    }
    QColor getColorTextHover() const {
        return colorTextHover;
    }
    QColor getColorTextNormalLeval2() const {
        return colorTextNormalLeval2;
    }
    QColor getColorTextSelectedLeval2() const {
        return colorTextSelectedLeval2;
    }
    QColor getColorTextHoverLeval2() const {
        return colorTextHoverLeval2;
    }

public slots:
    // 读取xml文件数据
    void readData(QString xmlPath);

    // 设置数据集合
    void setData(QStringList listItem);

    // 设置当前选中行
    void setCurrentRow(int row);

    // 设置是否显示提示信息
    void setInfoVisible(bool infoVisible);

    // 设置是否显示间隔线条
    void setLineVisible(bool lineVisible);

    // 设置伸缩图片是否采用背景色
    void setIcoColorBg(bool icoColorBg);

    // 设置伸缩图片样式
    void setIcoStyle(IcoStyle style);

    /// ====== 设置各种前景色背景色选中色
    void setColorLine(QColor colorLine);
    void setColorBg(QColor colorBgNormal,     QColor colorBgSelected,   QColor colorBgHover);
    void setColorText(QColor colorTextNormal, QColor colorTextSelected, QColor colorTextHover);
    void setColorBgLeval2(QColor colorBgNormal,     QColor colorBgSelected,   QColor colorBgHover);
    void setColorTextLeval2(QColor colorTextNormal, QColor colorTextSelected, QColor colorTextHover);


private:
    NavModel *model;
    NavDelegate *delegate;

    bool infoVisible;               // 是否显示提示信息
    bool lineVisible;               // 是否显示分割线条
    bool icoColorBg;                // 伸缩图片是否使用颜色
    IcoStyle style;                 // 图标样式
    QColor colorLine;               // 线条颜色
    /// ====== leval为1时的效果
    QColor colorBgNormal;           // 正常背景色
    QColor colorBgSelected;         // 选中背景色
    QColor colorBgHover;            // 悬停背景色
    QColor colorTextNormal;         // 正常文字颜色
    QColor colorTextSelected;       // 选中文字颜色
    QColor colorTextHover;          // 悬停文字颜色
    /// ====== leval为2时的效果
    QColor colorBgNormalLeval2;     // 正常背景颜色
    QColor colorBgSelectedLeval2;   //
    QColor colorBgHoverLeval2;      //
    QColor colorTextNormalLeval2;   // 正常文字颜色
    QColor colorTextSelectedLeval2; //
    QColor colorTextHoverLeval2;    //
};

#endif // NAVLISTVIEW_H

NavListView.cpp

#include "NavListView.h"

#include <QPainter>
#include <QFile>
#include <qdom.h>
#include <QDebug>

NavDelegate::NavDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
    nav = (NavListView *)parent;
}

NavDelegate::~NavDelegate()
{

}

QSize NavDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    NavModel::TreeNode *node = (NavModel::TreeNode *)index.data(Qt::UserRole).toULongLong();
    if (node->level == 1)
    {
        return QSize(192, 71);
    }
    else
    {
        return QSize(182, 48);
    }
}

void NavDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    painter->setRenderHint(QPainter::Antialiasing);
    NavModel::TreeNode *node = (NavModel::TreeNode *)index.data(Qt::UserRole).toULongLong();

    QColor colorBg;
    QColor colorText;
    QFont  fontText;
    int    iconSize = 0, leftMargin = 0, topMargin = 0;
    if(1 == node->level)
    {
        if (option.state & QStyle::State_Selected)
        {
            colorBg   = nav->getColorBgSelected();
            colorText = nav->getColorTextSelected();
        }
        else if (option.state & QStyle::State_MouseOver)
        {
            colorBg   = nav->getColorBgHover();
            colorText = nav->getColorTextHover();
        }
        else
        {
            colorBg   = nav->getColorBgNormal();
            colorText = nav->getColorTextNormal();
        }
        iconSize    = 32;
        leftMargin  = 32;
        topMargin   = 20;
        fontText.setPixelSize(20);
        painter->setBrush(QBrush(nav->getColorBgNormal()));
        painter->setPen(Qt::transparent);
        painter->drawRoundedRect(option.rect, 8, 20, Qt::RelativeSize);
    }
    else if(2 == node->level)
    {
        if (option.state & QStyle::State_Selected)
        {
            colorBg   = nav->getColorBgSelectedLeval2();
            colorText = nav->getColorTextSelectedLeval2();
        }
        else if (option.state & QStyle::State_MouseOver)
        {
            colorBg = nav->getColorBgHoverLeval2();
            colorText = nav->getColorTextHoverLeval2();
        }
        else
        {
            colorBg   = nav->getColorBgNormalLeval2();
            colorText = nav->getColorTextNormalLeval2();
        }
        iconSize   = 24;
        leftMargin = 25;
        topMargin  = 13;
        fontText.setPixelSize(18);

        QRect rectLevel2 = option.rect;
        rectLevel2.setX(option.rect.x() + 12);
        if (node->theFirst)
        {
            rectLevel2.setHeight(option.rect.height() + 4);
            rectLevel2.setWidth(option.rect.width() + 8);
            painter->setBrush(QBrush(nav->getColorBgNormalLeval2()));
            painter->setPen(Qt::transparent);
            painter->drawRoundedRect(rectLevel2, 8, 20, Qt::RelativeSize);
        }
        else if (node->theLast)
        {
            rectLevel2.setY(option.rect.y() - 4);
            rectLevel2.setWidth(option.rect.width() + 8);
            painter->setBrush(QBrush(nav->getColorBgNormalLeval2()));
            painter->setPen(Qt::transparent);
            painter->drawRoundedRect(rectLevel2, 8, 20, Qt::RelativeSize);
        }
        else
        {
            painter->fillRect(rectLevel2, nav->getColorBgNormalLeval2());
        }
    }

    /// ====== 菜单选项背景颜色
    if (1 == node->level && option.state & QStyle::State_Selected)
    {
        QRect rectMenu = option.rect;
        rectMenu.setWidth(option.rect.width()  - 20);
        rectMenu.setHeight(option.rect.height()- 10);
        rectMenu.setX(option.rect.x() + 10);
        rectMenu.setY(option.rect.y() + 10);
        painter->setBrush(QBrush(colorBg));
        painter->setPen(Qt::transparent);
        painter->drawRoundedRect(rectMenu, 8, 20, Qt::RelativeSize);
    }

    /// ====== 绘制图标
    QPixmap pixMap;
    pixMap.load(node->iconName);
    QRect rectIcon = option.rect;
    rectIcon.setX(option.rect.x()+leftMargin);
    rectIcon.setY(option.rect.y()+topMargin);
    rectIcon.setWidth(iconSize);
    rectIcon.setHeight(iconSize);
    painter->drawPixmap(rectIcon, pixMap);

    /// ====== 绘制条目文字
    if(option.state & QStyle::State_Selected)
    {
        painter->setOpacity(1);
    }
    else
    {
        painter->setOpacity(0.5);
    }
    painter->setPen(QPen(colorText));
    int margin = 72;
    if (node->level == 2)
    {
        margin = 84;
    }
    QRect rect = option.rect;
    rect.setX(rect.x() + margin);
    painter->setFont(fontText);
    painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, index.data(Qt::DisplayRole).toString());

    painter->setOpacity(1);
    /// ====== 绘制分割线
    QRect rectLine = option.rect;
    rectLine.setX(option.rect.x()+16);
    rectLine.setY(option.rect.y()-1);
    rectLine.setWidth(168);
    rectLine.setHeight(1);
    QPixmap pixMapLine;
    pixMapLine.load(":/Images/Line.png");
    painter->drawPixmap(rectLine, pixMapLine);
}


NavModel::NavModel(QObject *parent)	: QAbstractListModel(parent)
{

}

NavModel::~NavModel()
{
    for (std::vector<TreeNode *>::iterator it = treeNode.begin(); it != treeNode.end();) {
        for (std::list<TreeNode *>::iterator child = (*it)->children.begin(); child != (*it)->children.end();) {
            delete(*child);
            child = (*it)->children.erase(child);
        }
        delete(*it);
        it = treeNode.erase(it);
    }
}

void NavModel::readData(QString path)
{
    QFile xml(path);

    if (!xml.open(QIODevice::ReadOnly | QIODevice::Text)) {
        return;
    }
    QDomDocument doc;
    if (!doc.setContent(&xml, false))
    {
        return;
    }

    treeNode.clear();
    listNode.clear();

    QDomNode root = doc.documentElement().firstChildElement("layout");
    QDomNodeList children = root.childNodes();

    for (int i = 0; i != children.count(); ++i)
    {
        QDomElement nodeInfo = children.at(i).toElement();
        TreeNode *node = new TreeNode;
        node->label    = nodeInfo.attribute("label");
        node->collapse = nodeInfo.attribute("collapse").toInt();
        node->info     = nodeInfo.attribute("info");
        node->level    = 1;

        QDomNodeList secondLevel = nodeInfo.childNodes();
        for (int j = 0; j != secondLevel.count(); ++j)
        {
            QDomElement secNodeInfo = secondLevel.at(j).toElement();
            TreeNode *secNode = new TreeNode;
            secNode->label = secNodeInfo.attribute("label");
            secNode->info  = secNodeInfo.attribute("info");
            secNode->collapse = false;
            secNode->level    = 2;
            secNode->theLast  = (j == secondLevel.count() - 1 && i != children.count() - 1);
            node->children.push_back(secNode);
        }

        treeNode.push_back(node);
    }

    refreshList();
    beginResetModel();
    endResetModel();
}

void NavModel::setData(QStringList listItem)
{
    int count = listItem.count();

    if (count == 0) {
        return;
    }
    treeNode.clear();
    listNode.clear();

    // listItem格式: 标题|父节点标题(父节点为空)|是否展开|提示信息
    for (int i = 0; i < count; i++)
    {
        QString item = listItem.at(i);
        QStringList list = item.split("|");

        if (list.count() < 4)
        {
            continue;
        }
        // 首先先将父节点即父节点标题为空的元素加载完毕
        QString title       = list.at(0);
        QString fatherTitle = list.at(1);
        QString collapse    = list.at(2);
        QString info        = list.at(3);
        QString iconFile    = list.at(4);
        if (fatherTitle.isEmpty())
        {
            TreeNode *node = new TreeNode;
            node->label     = title;
            node->collapse  = collapse.toInt();
            node->info      = info;
            node->level     = 1;
            node->iconName  = iconFile;
            // 先计算该父节点有多少个子节点
            int secCount = 0;
            for (int j = 0; j < count; j++)
            {
                QString secItem = listItem.at(j);
                QStringList secList = secItem.split("|");

                if (secList.count() < 4)
                {
                    continue;
                }

                QString secFatherTitle  = secList.at(1);
                if (secFatherTitle == title)
                {
                    secCount++;
                }
            }
            // 查找该父节点是否有对应子节点,有则加载
            int currentCount = 0;
            for (int j = 0; j < count; j++)
            {
                QString secItem = listItem.at(j);
                QStringList secList = secItem.split("|");

                if (secList.count() < 4)
                {
                    continue;
                }
                QString secTitle        = secList.at(0);
                QString secFatherTitle  = secList.at(1);
                QString secInfo         = secList.at(3);
                QString secIconName     = secList.at(4);

                if (secFatherTitle == title)
                {
                    currentCount++;
                    TreeNode *secNode = new TreeNode;
                    secNode->label    = secTitle;
                    secNode->info     = secInfo;
                    secNode->collapse = false;
                    secNode->level    = 2;
                    secNode->theFirst = (currentCount == 1);
                    secNode->theLast  = (currentCount == secCount);
                    secNode->iconName = secIconName;
                    node->children.push_back(secNode);
                }
            }
            treeNode.push_back(node);
        }
    }
    refreshList();
    beginResetModel();
    endResetModel();
}

int NavModel::rowCount(const QModelIndex &parent) const
{
    return listNode.size();
}

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

    if (index.row() >= listNode.size() || index.row() < 0) {
        return QVariant();
    }

    if (role == Qt::DisplayRole) {
        return listNode[index.row()].label;
    } else if (role == Qt::UserRole) {
        return reinterpret_cast<quint64>(listNode[index.row()].treeNode);
    }
    return QVariant();
}

void NavModel::refreshList()
{
    listNode.clear();

    for (std::vector<TreeNode *>::iterator it = treeNode.begin(); it != treeNode.end(); ++it) {
        ListNode node;
        node.label = (*it)->label;
        node.treeNode = *it;

        listNode.push_back(node);

        if ((*it)->collapse) {
            continue;
        }

        for (std::list<TreeNode *>::iterator child = (*it)->children.begin(); child != (*it)->children.end(); ++child) {
            ListNode node;
            node.label = (*child)->label;
            node.treeNode = *child;
            node.treeNode->theLast = false;
            listNode.push_back(node);
        }

        if (!listNode.empty()) {
            listNode.back().treeNode->theLast = true;
        }
    }
}

void NavModel::collapse(const QModelIndex &index)
{
    TreeNode *node = listNode[index.row()].treeNode;

    if (node->children.size() == 0) {
        return;
    }

    node->collapse = !node->collapse;

    if (!node->collapse) {
        beginInsertRows(QModelIndex(), index.row() + 1, index.row() + node->children.size());
        endInsertRows();
    } else {
        beginRemoveRows(QModelIndex(), index.row() + 1, index.row() + node->children.size());
        endRemoveRows();
    }

    // 刷新放在删除行之后,放在删除行之前可能导致rowCount返回数据错误
    refreshList();
}

NavListView::NavListView(QWidget *parent) : QListView(parent)
{
    infoVisible = true;
    lineVisible = true;
    icoColorBg = false;
    style = NavListView::IcoStyle_Cross;
    colorLine         = QColor(214, 216, 224);
    colorBgNormal     = QColor(239, 241, 250);
    colorBgSelected   = QColor(133, 153, 216);
    colorBgHover      = QColor(209, 216, 240);
    colorTextNormal   = QColor(58, 58, 58);
    colorTextSelected = QColor(255, 255, 255);
    colorTextHover    = QColor(59, 59, 59);

    this->setMouseTracking(true);
    model = new NavModel(this);
    delegate = new NavDelegate(this);
    connect(this, SIGNAL(clicked(QModelIndex)), model, SLOT(collapse(QModelIndex)));
}

NavListView::~NavListView()
{
    delete model;
    delete delegate;
}

void NavListView::readData(QString xmlPath)
{
    model->readData(xmlPath);
    this->setModel(model);
    this->setItemDelegate(delegate);
}

void NavListView::setData(QStringList listItem)
{
    model->setData(listItem);
    this->setModel(model);
    this->setItemDelegate(delegate);
}

void NavListView::setCurrentRow(int row)
{
    QModelIndex index = model->index(row, 0);
    setCurrentIndex(index);
}

void NavListView::setInfoVisible(bool infoVisible)
{
    this->infoVisible = infoVisible;
}

void NavListView::setLineVisible(bool lineVisible)
{
    this->lineVisible = lineVisible;
}

void NavListView::setIcoColorBg(bool icoColorBg)
{
    this->icoColorBg = icoColorBg;
}

void NavListView::setIcoStyle(NavListView::IcoStyle style)
{
    this->style = style;
}

void NavListView::setColorLine(QColor colorLine)
{
    this->colorLine = colorLine;
}

void NavListView::setColorBg(QColor colorBgNormal,  ///< 正常背景颜色
                             QColor colorBgSelected,///< 选中背景颜色
                             QColor colorBgHover)   ///< 鼠标悬停背景颜色
{
    this->colorBgNormal   = colorBgNormal;
    this->colorBgSelected = colorBgSelected;
    this->colorBgHover    = colorBgHover;
}
void NavListView::setColorText(QColor colorTextNormal,  ///< 正常字体颜色
                               QColor colorTextSelected,///< 选中字体颜色
                               QColor colorTextHover)   ///< 鼠标悬停字体颜色
{
    this->colorTextNormal   = colorTextNormal;
    this->colorTextSelected = colorTextSelected;
    this->colorTextHover    = colorTextHover;
}
void NavListView::setColorBgLeval2(QColor _colorBgNormalLeval2,
                                   QColor _colorBgSelectedLeval2,
                                   QColor _colorBgHoverLeval2)
{
    this->colorBgNormalLeval2   = _colorBgNormalLeval2;
    this->colorBgSelectedLeval2 = _colorBgSelectedLeval2;
    this->colorBgHoverLeval2    = _colorBgHoverLeval2;
}
void NavListView::setColorTextLeval2(QColor _colorTextNormalLeval2,
                                     QColor _colorTextSelectedLeval2,
                                     QColor _colorTextHoverLeval2)
{
    this->colorTextNormalLeval2   = _colorTextNormalLeval2;
    this->colorTextSelectedLeval2 = _colorTextSelectedLeval2;
    this->colorTextHoverLeval2    = _colorTextHoverLeval2;
}

NavigationList.h

#ifndef NAVIGATIONLIST_H
#define NAVIGATIONLIST_H

#include <QWidget>
#include <QPainter>
#include <QStyleOption>
#include <QDebug>

QT_BEGIN_NAMESPACE
namespace Ui { class NavigationList; }
QT_END_NAMESPACE

class NavigationList : public QWidget
{
    Q_OBJECT
public:
    explicit NavigationList(QWidget *parent = nullptr);
    ~NavigationList();
    void initTreeView();

protected:
    void paintEvent(QPaintEvent* _event) override;

public slots:
    void slotListViewPressed(const QModelIndex &);

signals:
    void signalPageSwitch(QString page);      // 页面切换信号

private:
    Ui::NavigationList *ui;
    bool m_isHideAdditional = true;
};
#endif // NAVIGATIONLIST_H

NavigationList.cpp

#include "NavigationList.h"
#include "ui_NavigationList.h"

NavigationList::NavigationList(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::NavigationList)
{
    ui->setupUi(this);
    initTreeView();

    connect(ui->listViewNavigation, &NavListView::pressed, this, &NavigationList::slotListViewPressed);
    ui->listViewNavigation->setCurrentRow(0);
}

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

void NavigationList::paintEvent(QPaintEvent* _event)
{
    Q_UNUSED(_event)
    QStyleOption n_styleOption;
    n_styleOption.init(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &n_styleOption, &painter, this);
}

void NavigationList::initTreeView()
{
    ui->listViewNavigation->setIcoColorBg(false);
    ui->listViewNavigation->setColorLine(QColor("#FFFFFF"));
    ui->listViewNavigation->setColorBg(QColor("#016BFF"),
                                          QColor("#2A83FF"),
                                          QColor("#2A83FF"));
    ui->listViewNavigation->setColorText(QColor("#FFFFFF"),
                                            QColor("#FFFFFF"),
                                            QColor(0, 0, 0));
    ui->listViewNavigation->setColorBgLeval2(QColor("#EBF1FF"),QColor("#EBF1FF"),QColor("#EBF1FF"));
    ui->listViewNavigation->setColorTextLeval2(QColor("#000000"),
                                                  QColor("#000000"),
                                                  QColor("#6D6D6D"));
    // 设置数据方式
    QStringList listItem;
    listItem.append(QString::fromLocal8Bit("Tab1||0||:/Images/1.png|"));
    listItem.append(QString::fromLocal8Bit("Tab2||0||:/Images/2.png|"));
    listItem.append(QString::fromLocal8Bit("Tab3||1||:/Images/3.png|"));
    listItem.append(QString::fromLocal8Bit("Tab4|Tab3|||:/Images/4.png|"));
    listItem.append(QString::fromLocal8Bit("Tab5|Tab3|||:/Images/5.png|"));
    listItem.append(QString::fromLocal8Bit("Tab6|Tab3|||:/Images/6.png|"));
    listItem.append(QString::fromLocal8Bit("Tab7|Tab3|||:/Images/7.png|"));
    listItem.append(QString::fromLocal8Bit("Tab8||0||:/Images/8.png|"));
    listItem.append(QString::fromLocal8Bit("Tab9||0||:/Images/9.png|"));
    ui->listViewNavigation->setData(listItem);
}

void NavigationList::slotListViewPressed(const QModelIndex &)
{
    // 获取到点击的某一行,再根据点击显示对应的界面
    QModelIndex index = ui->listViewNavigation->currentIndex();
    QString text = index.data().toString();
    emit signalPageSwitch(text);
}

NavigationList.ui

        只有一个QListView控件,被提升成了上面的NavListView类

        其中listViewNavigation控件添加了如下的样式表:

NavDelegate
{
    background-color:"#016BFF";
}
QListView#listViewNavigation
{
    border-top-left-radius: 8px;
    border-bottom-left-radius: 8px;
    background-color:"#016BFF";
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络期末复习1(最后一天才开始学版)

1.一个PPP帧的数据部分&#xff08;用十六进制写出&#xff09;是7D 5E FE 27 7D 5D 7D 5D 65 7D 5E。试问真正的数据是&#xff08;用十六进制写出&#xff09; 由于PPP帧的标志字段为7E,因此,为了区别标志字段和信息字段,将信息字段中出现的每一个0x7E转变成(0x7D,0x5E),0x7…

LeetCode --- 401周赛

题目列表 3178. 找出 K 秒后拿着球的孩子 3179. K 秒后第 N 个元素的值 3180. 执行操作可获得的最大总奖励 I 3181. 执行操作可获得的最大总奖励 II 一、找出K秒后拿着球的孩子 这题可以直接模拟&#xff0c;从前往后&#xff0c;再从后往前走k次&#xff0c;最后直接返回…

【尚庭公寓SpringBoot + Vue 项目实战】公寓管理(十一)

【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09;1、业务介绍2、逻辑模型介绍3、接口开发3.1、保存或更新公寓信息3.2、根据条件分页查询详细信息3.3、根据ID获…

Carsim高级开发:VS Connect通讯开发指南

文章目录 前言一、VS Connect 概念引入二、VS Connect 通讯框架三、Carsim 工程配置1、车辆模型配置2、procedure配置3、Run Control配置4、受控车辆名称配置 四、VS Connect Server代码1、打开Sln工程2、代码修改 五、VS Connect Client代码1、函数的调用关系2、carsim_variab…

【JAVA开发笔记】实战演练,如何用EasyExcel导出表格,并且自定义合并单元格

目录 1. 前言 2. EasyExcel简介 3. EasyExcel简单导出案例讲解 3.1 EasyExcel依赖引入 3.2 测试类创建 3.3 Excel导出实现 4. EasyExcel合并单元案例讲解 4.1 实现自定义合并策略 4.2 使用自定义合并策略 5. 总结 1. 前言 项目上&#xff0c;需将一个列表数据导出Ex…

16. 第十六章 类和函数

16. 类和函数 现在我们已经知道如何创建新的类型, 下一步是编写接收用户定义的对象作为参数或者将其当作结果用户定义的函数. 本章我会展示函数式编程风格, 以及两个新的程序开发计划.本章的代码示例可以从↓下载. https://github.com/AllenDowney/ThinkPython2/blob/master/c…

(源码)供应商电子招投标管理系统实现方案和功能说明

采购在线招投标供应商管理系统是一个集成了多个关键功能的综合性系统&#xff0c;旨在优化采购流程、提高效率和确保透明度。以下是关于您提到的五个核心功能的详细解释&#xff1a; 供应商管理 此功能允许企业记录和管理供应商的基本信息&#xff0c;如公司名称、联系方式、主…

了解并解决 Flutter 中的灰屏问题

生产中的 flutter 应用程序中的灰屏是一种通用占位符&#xff0c;当框架遇到问题无法渲染预期用户界面时就会显示。是的&#xff0c;所以基本上是出现问题时的后备指示器。 有趣的是&#xff0c;这只出现在发布模式下。在任何其他模式下运行都会显示红色错误屏幕&#xff0c;并…

apt-get update和apt-get upgrade的区别

apt-get update apt-get update 命令用于更新本地软件包列表。具体来说&#xff0c;做了以下事情&#xff1a; ①从 /etc/apt/sources.list 文件和 /etc/apt/sources.list.d/ 目录下的所有文件中读取软件源配置。 ②连接到这些软件源&#xff0c;并下载最新的软件包列表。 ③将…

前端老古董execCommand——操作 选中文本 样式

文章目录 ⭐前言⭐exe command api用法&#x1f496; example示例&#x1f496; 测试效果 ⭐execommand和getSelection 的联系⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于 前端老古董execCommand——操作选中文本。 execommand 当一个 HTML 文…

【Linux】进程_4

文章目录 五、进程4. 进程状态5. 进程优先级6. 进程的调度和转换 未完待续 五、进程 4. 进程状态 当进程属于挂起状态时&#xff0c;进程的可执行程序代码和数据均会被从内存中换入到磁盘中&#xff0c;此时进程的PCB并没有消失&#xff0c;只要操作系统还需要管理这个进程&a…

ChatGPT关联技术

ChatGPT关联技术 一、前馈神经网络二、序列到序列模型&#xff08;Seq2Seq&#xff09;三、自注意力机制四、多头自注意力机制五、自监督学习六、Transformer模型七、语言生成技术八、多语种语言模型九、预训练语言模型十、生成式预训练模型&#xff08;GPT&#xff09;十一、近…

【odoo】odoo.conf文件配置

概要 odoo.conf 文件是 Odoo 服务器的配置文件&#xff0c;它用于定义和管理 Odoo 运行时的各种参数。这个文件包含了许多配置选项&#xff0c;可以帮助管理员根据特定的需求和环境来调整 Odoo 服务器的行为。 主要功能 数据库连接设置&#xff1a;定义 Odoo 连接到 PostgreSQL…

使用tkinter创建带有图标的菜单栏

使用tkinter创建带有图标的菜单栏 效果代码代码解析创建主窗口加载图标创建菜单栏添加文件菜单添加带图标的菜单项 Tkinter 的默认菜单外观较为简单&#xff0c;可以通过自定义和添加图标&#xff0c;让菜单显示更好看。 效果 代码 import tkinter as tk from tkinter import …

【SpringBoot】SpringBoot:构建安全的Web应用程序

文章目录 引言为什么需要安全Spring Security概述配置Spring Security添加依赖基本配置 用户认证创建用户实体类创建用户存储库自定义用户服务更新安全配置 用户授权更新用户实体类更新自定义用户服务更新安全配置 防护措施防止SQL注入使用参数化查询 防止跨站脚本&#xff08;…

Java17 --- RabbitMQ之插件使用

目录 一、Federation插件 1.1、运行两个rabbitmq实例 1.2、启用插件 1.3、在下游端点添加上游端点 1.4、创建策略 1.6、测试 二、联邦队列 2.1、创建策略 2.2、创建交换机与队列 2.2.1、创建52000的队列与交换机 2.2.2、创建62000的队列 三、Shovel 3.1、启…

WNR最便捷美观的开源桌面计时器工具

华丽外观&#xff0c;功能全面。工作和休息的完美计时器。跨平台支持&#xff0c;无论是Windows、Mac还是Linux&#xff0c;WNR都能轻松驾驭。 超强全屏专注模式 对于寻找高效工作/休息管理工具却屡屡受挫的用户&#xff0c;WNR的“全屏专注模式”无疑是终极解决方案。它确保在…

Android 蓝牙配对Settings应用里面的简要流程记录

Android 蓝牙配对Settings应用里面的简要流程记录 文章目录 Android 蓝牙配对Settings应用里面的简要流程记录一、前言二、Settings蓝牙配对的关键代码1、接收蓝牙请求的地方 AndroidManifest.xml2、BluetoothPairingRequest3、BluetoothPairingService4、BluetoothPairingDial…

利用机器学习重构视频中的人脸

引言 中国与英国的研究团队携手合作&#xff0c;开创了一种创新的视频面孔重塑技术。这项技术能够以极高的一致性对视频中的面部结构进行逼真的放大和缩小&#xff0c;且避免了常见伪影的产生。 从研究人员选取的YouTube视频样例中可见&#xff0c;经过处理后&#xff0c;女演…

LC1020:飞地的数量

题目 给你一个大小为 m x n 的二进制矩阵 grid &#xff0c;其中 0 表示一个海洋单元格、1 表示一个陆地单元格。 一次 移动 是指从一个陆地单元格走到另一个相邻&#xff08;上、下、左、右&#xff09;的陆地单元格或跨过 grid 的边界。 返回网格中 无法 在任意次数的移动…