MV结构下设置Qt表格的代理
目录
预备知识
模型
关联
刷新
示例
代理
模型
界面
结果
完整资料见:
所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客,如设置QTableView的内容自动换行(2)_qstandarditem 文本换行显示-CSDN博客
如何截获QTableView的鼠标事件?_qtableview里面捕获鼠标移动事件-CSDN博客
QAbstractItemModel数据更新-CSDN博客
Qt如何正确的显示、修改表格(QTableView)的内容_qt tableview修改表格内容-CSDN博客
我已经花了很多笔墨描述Qt表格的软件设计方法。在本篇文章中,我将介绍如何编辑表格--表格代理。
预备知识
模型
模型用来存储表格数据。这个类通常派生自QAbstractTableModel。这个派生类的通常由如下几个部分组成:
成员变量:
m_data m_data通常是一个list,vector或者map等常见的数据结构。
用来存储数据。
以下为虚函数:
columnCount 列数
rowCount 行数
data 表格显示的内容
flags flags决定了各个单元格可否被编辑。假如不需要编辑表格,
也可以不重写此虚函数
headerData headerData返回值决定了各行/列标题名称
setData setData决定了编辑单元格以后,编辑结果如何影响m_data。
假如不需要编辑表格,也可以不重写此虚函数
关联
通过QTableView::setModel()建立与模型的关联
刷新
当m_data发生变化时,或者界面需要刷新时,刷新动作由dataChanged信号触发。很多人奇怪,怎么没看到对应dataChanged的槽函数?Qt内部已经将dataChanged与对应的槽函数做了关联,开发者不必操心,只要发出信号即可。
示例
代理
专门建立一个代理类
#include "EdtDelegate.h"EdtDelegate::EdtDelegate(int iMin, int iMax, QObject *parent): QStyledItemDelegate(parent)
{m_pIntVld = new QIntValidator(iMin, iMax, this);
}EdtDelegate::~EdtDelegate()
{}QWidget *EdtDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option */,const QModelIndex &/* index */) const
{QLineEdit *editor = new QLineEdit(parent);editor->setValidator(m_pIntVld);return editor;
}void EdtDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();QLineEdit *Edt = static_cast<QLineEdit*>(editor);Edt->setText(qstrTxt);
}void EdtDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{QLineEdit *edt = static_cast<QLineEdit*>(editor);auto qstrTxt = edt->text();model->setData(index, qstrTxt, Qt::EditRole);
}void EdtDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
{editor->setGeometry(option.rect);
}
#include "ComboDelegate.h"#include <QComboBox>ComboDelegate::ComboDelegate(QStringList qstrlst, QObject *parent): QStyledItemDelegate(parent), m_qstrlst(qstrlst){}QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/* option */,const QModelIndex &/* index */) const{QComboBox *editor = new QComboBox(parent);editor->addItems(m_qstrlst);return editor;}void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const{QString qstrTxt = index.model()->data(index, Qt::DisplayRole).toString();QComboBox *cmbBox = static_cast<QComboBox*>(editor);cmbBox->setCurrentText(qstrTxt);}void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const{QComboBox *cmbBox = static_cast<QComboBox*>(editor);auto qstrTxt = cmbBox->currentText();model->setData(index, qstrTxt, Qt::EditRole);}void ComboDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/* index */) const{editor->setGeometry(option.rect);}
这里有人会问,createEditor里面有new的动作,为什么没看到释放?createEditor返回一个指针。Qt内部有一套机制,在编辑结束后,自动释放该指针。
模型
#include "Model.h"//Model
Model::Model(int iTotalCol, QStringList qstrlstHeader, QList<int> lstNonEditableCols,QObject *parent) : QAbstractTableModel(parent),m_lstNonEditableCols(lstNonEditableCols),m_iTotalCol(iTotalCol), m_qstrlstHeader(qstrlstHeader)
{}int Model::rowCount(const QModelIndex &) const
{return m_data.size();
}int Model::columnCount(const QModelIndex &) const
{return m_iTotalCol;
}QVariant Model::data(const QModelIndex &index, int role) const
{int i = index.row(), j = index.column();if ((i >= 0) && (i < m_data.size())){if(m_data.at(i).size() > j){if(role == Qt::DisplayRole){//m_data的类型是QList<QStringList>,每一个QStringList对应表格里一行数据//m_data.at(i).at(j)对应的就是第i行,第j列的数据return m_data.at(i).at(j);}else if(role == Qt::TextAlignmentRole)return Qt::AlignCenter;else{}}else{return QString("");}}else{}return QVariant();
}QVariant Model::headerData(int section, Qt::Orientation orientation, int role) const
{if(role == Qt::DisplayRole){if(orientation == Qt::Horizontal)//横向排列的标题栏,也就是各个列的标题{if(m_qstrlstHeader.size() > section)return m_qstrlstHeader.at(section);else{return QString("");}}else{//纵向排列的标题栏,也就是各个行的标题return QString("");}}else if(role == Qt::TextAlignmentRole){//文字对齐方式设置为居中对齐return Qt::AlignCenter;}else{}return QAbstractTableModel::headerData(section, orientation, role);
}void Model::vSetData(QList<QStringList> & lstData)
{m_data.clear();m_data.append(lstData);//发出dataChanged信号,界面上才更新表格内容emit dataChanged(createIndex(0,0), createIndex(0, columnCount()-1));
}Qt::ItemFlags Model::flags(const QModelIndex &index) const
{if(m_lstNonEditableCols.contains(index.column()))//假如index对应的列是不可编辑的列return QAbstractTableModel::flags(index);else//假如index对应的列是可编辑的列,就给它添加ItemIsEditable属性return Qt::ItemIsEditable | QAbstractTableModel::flags(index);
}bool Model::setData(const QModelIndex &index, const QVariant &value, int role)
{if(role == Qt::EditRole){//编辑单元格之后,用编辑结果更新对应的m_dataint row = index.row(), col = index.column();QStringList qstrlst = m_data.at(row);qstrlst.replace(col, value.toString());m_data.replace(row, qstrlst);}return true;
}
界面
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_pModel = new Model(4, {"1", "2", "3", "4"}, {0,1});ui->tableView->setModel(m_pModel);//setEditTriggers(QTableView::DoubleClicked);注明触发编辑单元格的方式是鼠标双击ui->tableView->setEditTriggers(QTableView::DoubleClicked);QList<QStringList> lstqstrlst;lstqstrlst<<QStringList{"a", "b", "c", "d"};//向表格中注入数据m_pModel->vSetData(lstqstrlst);m_scpCmbDelg.reset(new ComboDelegate({"a","b","c"}, this));//表格第2列采用combobox代理(其实是第3列,因为从0开始)ui->tableView->setItemDelegateForColumn(2, m_scpCmbDelg.data());m_scpEdtDelg.reset(new EdtDelegate(0,10, this));//表格第3列采用lineedit代理ui->tableView->setItemDelegateForColumn(3, m_scpEdtDelg.data());
}MainWindow::~MainWindow()
{delete ui;
}
结果
双击第一列、第二列,无法编辑单元格。但是双击第三列,可以编辑combobox;双击第四列,可以编辑lineedit:
qt代理,访问csdn金色熊族,获取完整信息
完整资料见:
【免费】介绍如何给Qt表格添加代理资源-CSDN文库
相关文章:
MV结构下设置Qt表格的代理
目录 预备知识 模型 关联 刷新 示例 代理 模型 界面 结果 完整资料见: 所谓MV结构,是“model-view”(模型-视图)的简称。也就是说,表格的数据保存在model中,而视图由view实现。在我前面的很多博客…...
C++:多继承习题2
题目内容: 分别声明Teacher类和Cadre类,采用多重继承派生出新类Teacher_Dadre。要求: (1)在两个基类中都包含姓名、年龄、性别、地址和电话。 (2)在Teacher类中包含title数据成员,Ca…...
DeepSeek--通向通用人工智能的深度探索者
一、词源与全称 “DeepSeek"由"Deep”(深度)与"Seek"(探索)组合而成,中文译名为"深度求索"。其全称为"深度求索人工智能基础技术研究有限公司",英文对应"De…...
Spring MVC中HandlerInterceptor和Filter的区别
目录 一、处理阶段 二、功能范围 三、参数访问 四、配置方式 五、使用场景说明 在Spring MVC中,HandlerInterceptor和Filter都是用于拦截请求的重要组件,但它们在多个方面存在显著的差异。本文将详细解析这两种拦截机制的区别,并结合使用…...
Linux 部署 Java 项目:Tomcat、Redis、MySQL 教程
在 Linux 服务器上部署 Java 项目通常需要配置应用服务器(如 Tomcat)、数据库(如 MySQL)和缓存服务器(如 Redis)。本文将详细介绍如何在 Linux 环境中部署一个 Java 项目,涵盖 Tomcat、Redis 和…...
C语言------数组从入门到精通
1.一维数组 目标:通过思维导图了解学习一维数组的核心知识点: 1.1定义 使用 类型名 数组名[数组长度]; 定义数组。 // 示例: int arr[5]; 1.2一维数组初始化 数组的初始化可以分为静态初始化和动态初始化两种方式。 它们的主要区别在于初始化的时机和内存分配的方…...
工作总结:git篇
文章目录 前言基础Gerrit1.克隆2.新建本地分支和checkout3.添加到暂存区新增文件到暂存区修改已经添加到暂存区的文件取消添加到暂存区的文件 4.提交到本地仓库在不重复提交的情况下,修改本次提交 5.提交到远程仓库6.评审其他辅助命令 前言 目前也算是工作一段时间…...
2024年终总结——今年是蜕变的一年
2024年终总结 摘要前因转折找工作工作的成长人生的意义 摘要 2024我从国企出来,兜兜转转还是去了北京,一边是工资低、感情受挫,一边是压力大、项目经历少,让我一度找不到自己梦寐以求的工作,我投了一家又一家ÿ…...
Linux环境基础开发工具的使用(apt, vim, gcc, g++, gbd, make/Makefile)
什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安 装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的…...
宫本茂的游戏设计思想:有趣与风格化
作为独立游戏开发者之一,看到任天堂宫本茂20年前的言论后,深感认同。 游戏研发思想,与企业战略是互为表里的,游戏是企业战略的具体战术体现,虚空理念的有形载体。 任天堂长盛不衰的关键就是靠简单有趣的游戏…...
[JMCTF 2021]UploadHub
题目 上传.htaccess就是修改配置文件 <FilesMatch .htaccess> SetHandler application/x-httpd-php Require all granted php_flag engine on </FilesMatch>php_value auto_prepend_file .htaccess #<?php eval($_POST[md]);?>SetHandler和ForceType …...
树和图的实现与应用:C语言实践详解
树和图的实现与应用:C语言实践详解 树和图是两种重要的非线性数据结构,在计算机科学中有着广泛的应用。从基本的二叉树到复杂的图算法(如最短路径和最小生成树),这些结构能够帮助我们高效解决实际问题。本文将从基础出发,逐步深入,讲解如何用C语言实现树和图,并探讨其…...
DeepSeek助力学术文献搜索!
搜集文献 宝子们如果是第一次发表学术论文,论文往往是会署名多个作者。在这种情况下,即便成功发表了论文,独立撰作或主导写作的挑战仍旧存在。那么,怎样才能独立地完成一篇属于自己的学术论文呢?对于初次尝试学术论文…...
新项目上传gitlab
Git global setup git config --global user.name “FUFANGYU” git config --global user.email “fyfucnic.cn” Create a new repository git clone gitgit.dev.arp.cn:casDs/sawrd.git cd sawrd touch README.md git add README.md git commit -m “add README” git push…...
t113 procd-init文件系统增加自己的程序文件
tina 默认为 procd-init ,可以通过Tina procd-init 与 busybox-init 切换 | 全志在线开发者论坛 默认的procd-init系统的文件夹在tina-sdk/target/allwinner/t113-round/base-files, 把文件或者文件夹放这里会在编译pack的时候打包到文件系统...
vue中的el是指什么
简介: 在Vue.js中,el指的是Vue实例的挂载元素。 具体来说,el是一个选项,用于指定Vue实例应该挂载到哪个DOM元素上。通过这个选项,Vue可以知道应该从哪个元素开始进行模板编译和渲染。它可以是一个CSS选择器字符串&…...
渗透测试之WAF规则触发绕过规则之规则库绕过方式
目录 Waf触发规则的绕过 特殊字符替换空格 实例 特殊字符拼接绕过waf Mysql 内置得方法 注释包含关键字 实例 Waf触发规则的绕过 特殊字符替换空格 用一些特殊字符代替空格,比如在mysql中%0a是换行,可以代替空格 这个方法也可以部分绕过最新版本的…...
前端【11】HTML+CSS+jQUery实战项目--实现一个简单的todolist
前端【8】HTMLCSSjavascript实战项目----实现一个简单的待办事项列表 (To-Do List)-CSDN博客 学过jQUery可以极大简化js代码的编写,基于之前实现的todolist小demo,了解如何使用 jQuery 来实现常见的动态交互功能。 修改后的js代码 关键点解析 动态添加…...
Vscode的AI插件 —— Cline
简介 vscode的一款AI辅助吃插件,主要用来辅助创建和编辑文件,探索大型项目,使用浏览器并执行终端命令(需要多个tokens),可以使用模型上下文协议(MCP)来创建新工具并扩展自己(比较慢…...
HTML表单深度解析:GET 和 POST 提交方法
系列文章目录 01-从零开始学 HTML:构建网页的基本框架与技巧 02-HTML常见文本标签解析:从基础到进阶的全面指南 03-HTML从入门到精通:链接与图像标签全解析 04-HTML 列表标签全解析:无序与有序列表的深度应用 05-HTML表格标签全面…...
CycleGAN模型解读(附源码+论文)
CycleGAN 论文链接:Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks 官方链接:pytorch-CycleGAN-and-pix2pix 老规矩,先看看效果 总体流程 先简单过一遍流程,细节在代码里说。CycleGAN有…...
WebAssembly(Wasm)详解
WebAssembly 详解:开启 Web 应用的新纪元 引言 WebAssembly(简称 Wasm)是一种革命性的技术,它为 Web 应用带来了接近原生的性能,并支持使用多种编程语言进行开发。本文将深入探讨 WebAssembly 的方方面面,…...
基于物联网设计的疫苗冷链物流监测系统
一、前言 1.1 项目开发背景 随着全球经济的发展和物流行业的不断创新,疫苗和生物制品的运输要求变得越来越高。尤其是疫苗的冷链物流,温度、湿度等环境因素的控制直接关系到疫苗的质量和效力,因此高效、可靠的冷链监控系统显得尤为重要。冷…...
RabbitMQ 多种安装模式
文章目录 前言一、Windows 安装 RabbitMq1、版本关系2、Erlang2.1、下载安装 Erlang 23.12.2、配置 Erlang 环境变量 3、RabbitMQ3.1、下载安装 RabbitMQ 3.8.93.2、环境变量3.3、启动RabbitMQ 管理插件3.3、RabbitMQ3.4、注意事项 二、安装docker1、更新系统包:2、…...
视频拼接,拼接时长版本
目录 视频较长,分辨率较大,这个效果很好,不耗用内存 ffmpeg imageio,适合视频较短 视频较长,分辨率较大,这个效果很好,不耗用内存 ffmpeg import subprocess import glob import os from nats…...
【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解
Linux学习笔记: https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言: 前面我们已经将进程通信部分讲完了,现在我们来讲一个进程部分也非常重要的知识点——信号,信号也是进程间通信的一…...
有限元分析学习——Anasys Workbanch第一阶段笔记梳理
第一阶段笔记主要源自于哔哩哔哩《ANSYS-workbench 有限元分析应用基础教程》 张晔 主要内容导图: 笔记导航如下: Anasys Workbanch第一阶段笔记(1)基本信息与结果解读_有限元分析变形比例-CSDN博客 Anasys Workbanch第一阶段笔记(2)网格单元与应力奇…...
【YOLOv11改进- 注意力机制】YOLOv11+SCSA注意力机制(2024): 最新空间和通道协同注意力,助力YOLOv11有效涨点;包含二次创新
YOLOV11目标检测改进实例与创新改进专栏 专栏地址:YOLOv11目标检测改进专栏,包括backbone、neck、loss、分配策略、组合改进、原创改进等; 本文介绍 本文给大家带来的改进内容是在YOLOv11中添加SCSA注意力机制,助力有效涨点。作者提出了一种新的空间与通道协同注意模块(S…...
科技快讯 | 理想官宣:正式收费!WeChat 港币钱包拓宽商户网络;百川智能发布深度思考模型Baichuan-M1-preview
理想官宣:正式收费! 1月23日,理想汽车宣布,理想超充站超时占用费正式运营。触发超时占用费的条件为充电结束后15分钟内未将充电枪插回充电桩,收费标准为2元/分钟,单次封顶200元。理想汽车将在充电结束的四个…...
LLM架构与优化:从理论到实践的关键技术
标题:“LLM架构与优化:从理论到实践的关键技术” 文章信息摘要: 文章探讨了大型语言模型(LLM)开发与应用中的关键技术,包括Transformer架构、注意力机制、采样技术、Tokenization等基础理论,以…...
深入理解Pytest中的Setup和Teardown
关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 对于简单程序而言,使用 Pytest 运行测试直截了当。然而,当你…...
PostgreSQL 约束
PostgreSQL 约束 引言 在数据库设计中,约束是确保数据完整性和一致性的关键工具。PostgreSQL,作为一款功能强大的开源关系型数据库管理系统,提供了丰富的约束类型来满足不同的数据库设计需求。本文将详细介绍PostgreSQL中的各种约束,包括其定义、用途和实现方法。 一、约…...
JAVA 接口、抽象类的关系和用处 详细解析
接口 - Java教程 - 廖雪峰的官方网站 一个 抽象类 如果实现了一个接口,可以只选择实现接口中的 部分方法(所有的方法都要有,可以一部分已经写具体,另一部分继续保留抽象),原因在于: 抽象类本身…...
【微服务与分布式实践】探索 Dubbo
核心组件 服务注册与发现原理 服务提供者启动时,会将其服务信息(如服务名、版本、所在节点的网络地址等)注册到注册中心。服务消费者则可以从注册中心发现可用的服务提供者列表,并与之通信。注册中心会存储服务的信息,…...
lightweight-charts-python 包 更新 lightweight-charts.js 的方法
lightweight-charts-python 是 lightweight-charts.js 的 python 包装,非常好用 lightweight-charts 更新比较频繁,导致 lightweight-charts-python 内置的 lightweight-charts 经常不是最新的。 新的 lightweight-charts 通常可以获得性能改进和bug修复…...
作業系統:設計與實現-母本
2023 南京大學《作業系統:設計與實現》 課程主頁(含講義):https://jyywiki.cn/OS/2023/ 【Python 实现操作系统模型 [南京大学2023操作系统-P4] (蒋炎岩)-哔哩哔哩】 https://b23.tv/jakxDbh 用Python实现操作系统模型讲义 一、操作系统基础概念 1.1 定义 操作系统(Oper…...
穿心莲内酯(andrographolide)生物合成CYP72-文献精读106
Two CYP72 enzymes function as Ent-labdane hydroxylases in the biosynthesis of andrographolide in Andrographis paniculata 两种CYP72酶在穿心莲(Andrographis paniculata)中作为Ent-labdane羟化酶,在穿心莲内酯(andrograp…...
IDM-VTON本地部署教程:双重编码 + 文字提示,解锁真实野外试穿
一、介绍 IDM-VTON:改进扩散模型,实现真实的野外虚拟试穿。 技术原理:改进扩散模型,利用视觉编码器提取服装高级语义信息并与交叉注意力层融合,通过并行 UNet 结构的 GarmentNet 捕捉服装低级特征并与自注意力层结合&…...
【微服务与分布式实践】探索 Sentinel
参数设置 熔断时长 、最小请求数、最大RT ms、比例阈值、异常数 熔断策略 慢调⽤⽐例 当单位统计时⻓内请求数⽬⼤于设置的最⼩请求数⽬,并且慢调⽤的⽐例⼤于阈值,则接下来的熔断时⻓内请求会⾃动被熔断 异常⽐例 当单位统计时⻓内请求数⽬⼤于设置…...
云计算与虚拟化技术讲解视频分享
互联网各领域资料分享专区(不定期更新): Sheet 前言 由于内容较多,且不便于排版,为避免资源失效,请用手机点击链接进行保存,若链接生效请及时反馈,谢谢~ 正文 链接如下(为避免资源失效&#x…...
[c语言日寄]越界访问:意外的死循环
【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋:这是一个专注于C语言刷题的专栏,精选题目,搭配详细题解、拓展算法。从基础语法到复杂算法,题目涉及的知识点全面覆盖,助力你系统提升。无论你是初学者,还是…...
数据结构---哈希表
基本概念 哈希函数(Hash Function)是一种将输入的数据(通常是任意大小的)映射到固定大小的输出(通常是一个固定长度的值)的函数。这个输出值通常称为“哈希值”(Hash Value)或“哈希…...
【C语言----数组详解】
目录 ---------------------------------------begin--------------------------------------- 一、什么是数组 二、数组的声明和初始化 1. 数组的声明 2. 数组的初始化 三、数组元素的访问 四、数组的遍历 五、数组的应用 六、多维数组 七、总结 --------------------…...
C语言字符串详解
1. C语言中的字符串基础 C语言中的字符串是程序设计中不可忽视的部分。与现代高级编程语言不同,C语言对字符串的处理方式直接、灵活,并且强大。在C语言中,字符串并不是一种特殊的数据类型,而是字符数组的一种表现形式。字符串通常…...
基础IO(2)
基础IO(2) 理解“⼀切皆⽂件” ⾸先,在windows中是⽂件的东西,它们在linux中也是⽂件;其次⼀些在windows中不是⽂件的东西,⽐如进程、磁盘、显⽰器、键盘这样硬件设备也被抽象成了⽂件,你可以使…...
深入理解 Python 中的 `__all__`:控制模块的公共接口
在 Python 编程中,模块化设计是构建可维护和可扩展代码的关键。模块不仅帮助我们组织代码,还能通过隐藏实现细节来提高代码的可读性和安全性。Python 提供了多种机制来控制模块的可见性,其中 __all__ 是一个非常重要但常被忽视的特性。本文将…...
Python面试宝典7 | 正则表达式的match()与search(),精准匹配与全局搜索
今天,我们来聊聊Python正则表达式中两个常用的方法:match()和search()。它们都用于在字符串中查找匹配的模式,但有着重要的区别。 理论篇:匹配的起始位置 match()和search()最主要的区别在于它们匹配的起始位置: ma…...
代码随想录算法训练营第三十八天-动态规划-完全背包-279.完全平方数
把目标值当作背包容量,每个平方数当作物品,题目变更为装满指定容量的背包,最小用几个物品会不会出现拼凑不出来的情况?不会,因为有数字1,对任意正整数百分百能拼凑出来因此此题目与上一道题就变得一模一样了…...
996引擎 - NPC-添加NPC引擎自带形象
996引擎 - NPC-添加NPC引擎自带形象 截图参考添加NPC参考资料截图参考 添加NPC 编辑NPC表:Envir\DATA\cfg_npclist.xls 1.1. 需要临时隐藏NPC时可以在id前加 // 1.2. 如果NPC朝向不对,可以调整dir 列。(按8方向,上是0顺时针数。我这里给的4) 1.3. 形象代码:NPC代码、怪物…...
基于 NodeJs 一个后端接口的创建过程及其规范 -- 【elpis全栈项目】
基于 NodeJs 一个后端接口的创建过程及其规范 一个接口的诞生: #mermaid-svg-46HXZKI3fdnO0rKV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-46HXZKI3fdnO0rKV .error-icon{fill:#552222;}#mermaid-sv…...