基于QT使用OpenGL,加载obj模型,进行鼠标交互
目录
- 功能分析(需求分析)
- 技术点分析
- OpenGL
- 立即渲染模式
- 可编程渲染管线模式
- QOpenGLWidget
- 派生类 glwidget逻辑
- glwidget.h
- glwidget.cpp
- 鼠标交互功能
- obj格式介绍
- 效果
- bunny
- Cayman_GT
功能分析(需求分析)
- 基于QT平台,使用OpenGL进行obj文件加载显示;
- 使用鼠标对场景进行缩放、移动、旋转交互;
技术点分析
OpenGL
OpenGL是基于C的,学习曲线比较抖,但是总的来说就是下面一幅图,

用语言简单的描述(个人理解,可能不太准确)是把cpu里内存里的3D数据,传输到显卡的内存里,以及如何转换成2D平面上像素点显示(也就是矩阵变换,在好多开源的框架里都进行了进一步封装,形成了渲染器、场景、相机等)。这个数据是顶点坐标、颜色等,传输跟送快递一样,除了要有数据本身之外,还要有其他信息,也就是要有个约定,到显卡拿到数据之后怎么解析。
有个网站比较有名learnopengl,可以对着学一遍,在网上找资料的时候,需要注意是立即渲染模式,还是可编程渲染管线模式,现在官方推荐是使用可编程渲染管线模式开发。
立即渲染模式
glBegin(GL_TRIANGLES)
glTranslatef(1,2,3);
// 其他操作
// glVertex*() 设置顶点坐标
// glColor*() 设置当前颜色
// glIndex*() 设置当前颜色表
// glNormal*() 设置法向坐标
// glEvalCoord*() 产生坐标
// glTexCoord*() 设置纹理坐标
// glEdgeFlag*() 控制边界绘制
// glMaterial*() 设置材质
glEnd()
可编程渲染管线模式
1、创建VBO顶点数据对象GLuint VBO;glGenBuffers(1,&VBO);
2、VBO与显卡缓存绑定glBindBuffer(GL_ARRAY_BUFFER, VBO)
3、绑定数据缓存对象glBufferData(GL_ARRAY_BUFFER,sizeof(vertexs),vertex,)
4、数据格式glVertexAttribPoint(0,3,GL_FLOAT,)
5、启用/绘制glEnableVertexAttribArray(0)glDrawArrays(GL_TRIANGLES, 0, 10);
6、最后关闭glBindBuffer(GL_ARRAY_BUFFER,0)glBindVertexArray(0);
以上两段代码只是展示两种模式区别,很明显立即渲染模式容易理解,但是性能有限制,可编程渲染管线模式理解和使用门槛高,但更能接触底层。
QOpenGLWidget
QT对OpenGL进行了封装,提供了QOpenGLWidget类,只需要对其继承,在initialzeGL(),resizeGL(),paintGL()逻辑下进行业务实现,包括VBO、VAO的创建与绑定,着色器程序的编译与链接等。
派生类 glwidget逻辑
先简单介绍派生类的写法,当然为了方便扩展和使用,抽象出了相机类、渲染器类、物体类,完整的工程代码资源可以下载参考,具体的可以根据自己要实现的功能进行编写。
glwidget.h
#ifndef GLWIDGET_H
#define GLWIDGET_H#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QMouseEvent>
#include <QTimer>
#include <QQuaternion>#include <vector>
#include <QKeyEvent>#include "utils/Common.h"
#include "genericRender.h"
#include "grid.h"
#include "coorsystem.h"
#include "camera.h"class glwidget :public QOpenGLWidget, QOpenGLFunctions_3_3_Core
{Q_OBJECT
public:glwidget(QWidget * parent = nullptr);//鼠标交互事件重写void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void wheelEvent(QWheelEvent *event) override;//键盘交互void keyReleaseEvent(QKeyEvent *event) override; //按键释放事件void keyPressEvent(QKeyEvent *event) override; //按键按下事件void slotTimeOut();
protected:virtual void initializeGL();virtual void resizeGL(int w, int h);virtual void paintGL();
public:GenericRender m_render;//渲染器Camera m_camera;//相机grid m_grid;//网格平面xycoorSystem m_coordsys;//坐标系QTimer tm_;
public:QList<int> keys;QTimer* keyRespondTimer; //头文件中添加成员static int mouse_button;static int modifier_key;
public://鼠标变量static double mouse_pos_x_old;static double mouse_pos_y_old;bool changeview_ = false; //改变视角的标志位float fov = 2.0f; //视野范围
};
#endif // GLWIDGET_H
glwidget.cpp
#include "glwidget.h"
#include "box.h"
int glwidget::mouse_button = -1;
int glwidget::modifier_key = 0;
double glwidget::mouse_pos_x_old = 0;
double glwidget::mouse_pos_y_old = 0;
glwidget::glwidget(QWidget * parent):QOpenGLWidget(parent)
{keyRespondTimer = new QTimer(this); //构造函数中创建定时器对象,并连接信号槽connect(keyRespondTimer, &QTimer::timeout, this, &glwidget::slotTimeOut);setFocusPolicy(Qt::StrongFocus);//否则进入不了键盘事件监听
}void glwidget::initializeGL()
{initializeOpenGLFunctions();glEnable(GL_DEPTH_TEST);m_render.init();m_camera.setMatPro(fov);QStringList renderfiles={":/obj/data/Cayman_GT.obj", ":/obj/data/bunny_10k.obj"};for(QString file : renderfiles){Box* b1 = new Box();b1->load(file);m_render.addBox(b1);}m_grid.initize();m_coordsys.initize();
}void glwidget::resizeGL(int w, int h)
{m_camera.setRatio((float)width() / (float)height());
}void glwidget::paintGL()
{glClearColor(1.0f, 1.0f, 1.0f, 0.1f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPolygonMode(GL_FRONT, GL_LINE);QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();QMatrix4x4 mMatrix;m_camera.setMatPro(fov);m_grid.paint(f,m_camera.getMatPro(),m_camera.getMatView(),mMatrix);m_coordsys.paint(f,m_camera.getMatPro(),m_camera.getMatView(),mMatrix);m_render.render(f,m_camera,mMatrix);
}void glwidget::mousePressEvent(QMouseEvent *event){mouse_pos_x_old = event->pos().x();mouse_pos_y_old = event->pos().y();mouse_button = event->button();
}void glwidget::mouseMoveEvent(QMouseEvent *event){int x = event->pos().x();int y = event->pos().y();double w = width(), h = height();double d_x = (mouse_pos_x_old - x)/w;double d_y = (mouse_pos_y_old - y)/h;if (mouse_button == Qt::LeftButton){foreach (int key, keys) {switch (key) {case Qt::Key_Control:m_camera.rotateY(-d_x*180*5);m_camera.rotateX(-d_y*180*5);break;case Qt::Key_Shift:m_camera.move(5*d_x, 5*d_y, 0);break;default:break;}}}mouse_pos_x_old = x;mouse_pos_y_old = y;this->repaint();
}void glwidget::mouseReleaseEvent(QMouseEvent *event){ //鼠标左键松开禁止改变相机视角changeview_ = false;
}void glwidget::wheelEvent(QWheelEvent *event){if (event->delta() > 0)fov-=2.0f;elsefov+=2.0f;if (fov<0.50f)fov = 0.5f;if (fov>=200.f)fov = 200.0;this->repaint();
}void glwidget::keyReleaseEvent(QKeyEvent *event)
{if(!event->isAutoRepeat()) //判断如果不是长按时自动触发的释放,就将key值从容器中删除keys.removeAll(event->key());if(keys.isEmpty()) //容器空了,关闭定时器keyRespondTimer->stop();
}void glwidget::keyPressEvent(QKeyEvent *event)
{if(!event->isAutoRepeat()) //判断如果不是长按时自动触发的按下,就将key值加入容器keys.append(event->key());if(!keyRespondTimer->isActive()) //如果定时器不在运行,就启动一下keyRespondTimer->start(4);
}void glwidget::slotTimeOut(){foreach (int key, keys) {switch (key) {case Qt::Key_D:break;case Qt::Key_Shift:modifier_key = Qt::Key_Shift;break;default:break;}}
}
鼠标交互功能
交互的功能实现是重载QOpenGLWidget的鼠标事件函数,修改相应的矩阵,也就对应最上面的相机变化、灯光变化等;
obj格式介绍
OBJ文件(.obj)包含有关3D对象的几何体的信息,下面是一个长方体的obj格式文件;
#
# Object file
#
mtllib Cube3x3x10.mtl
# Cube3x3x10\实体
v 0 0 0
v 3.00000002607703 0 0
v 3.00000002607703 0 9.99999977648258
v 0 0 9.99999977648258
v 3.00000002607703 3.00000002607703 9.99999977648258
v 0 3.00000002607703 9.99999977648258
v 0 0 9.99999977648258
v 3.00000002607703 0 9.99999977648258
v 0 3.00000002607703 9.99999977648258
v 0 3.00000002607703 0
v 0 0 0
v 0 0 9.99999977648258
v 0 3.00000002607703 0
v 3.00000002607703 3.00000002607703 0
v 3.00000002607703 0 0
v 0 0 0
v 3.00000002607703 3.00000002607703 0
v 3.00000002607703 3.00000002607703 9.99999977648258
v 3.00000002607703 0 9.99999977648258
v 3.00000002607703 0 0
v 3.00000002607703 3.00000002607703 9.99999977648258
v 3.00000002607703 3.00000002607703 0
v 0 3.00000002607703 0
v 0 3.00000002607703 9.99999977648258
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 0 0 -1
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vt 0 0
vt 0 0.00300000002607703
vt 0.00999999977648258 0.00300000002607703
vt 0.00999999977648258 0
vt 0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0
vt 0.00150000001303852 0
vt 0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0
vt 0.00499999988824129 0
vt 0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0.00300000002607703
vt -0.00150000001303852 0
vt 0.00150000001303852 0
vt 0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0.00300000002607703
vt -0.00499999988824129 0
vt 0.00499999988824129 0
vt 0.00999999977648258 0.00300000002607703
vt 0 0.00300000002607703
vt 0 0
vt 0.00999999977648258 0
o Cube3x3x10\实体
s off
# face 0
f 2/2/2 3/3/3 1/1/1
f 1/1/1 3/3/3 4/4/4
# face 1
f 5/5/5 6/6/6 8/8/8
f 8/8/8 6/6/6 7/7/7
# face 2
f 9/9/9 10/10/10 12/12/12
f 12/12/12 10/10/10 11/11/11
# face 3
f 13/13/13 14/14/14 16/16/16
f 16/16/16 14/14/14 15/15/15
# face 4
f 17/17/17 18/18/18 20/20/20
f 20/20/20 18/18/18 19/19/19
# face 5
f 21/21/21 22/22/22 24/24/24
f 24/24/24 22/22/22 23/23/23
其中
- mtllib Cube3x3x10.mtl 表示引用的材质文件的文件名
- v 0 0 0 表示一个点的xyz坐标,使用空格隔开
- vn 0 -1 0 表示一个点的法向量,使用空格隔开
- vt 0.09 0 表示uv纹理坐标,使用空格隔开
- f 2/2/2 3/3/3 1/1/1 表示一个面, 2/2/2依次为顶点索引,纹理坐标索引,法向索引,因为是三角面片,所以是三组,也有超多三个点的,自己造轮子的时候要注意
- o Cube 表示指定了模型名称为Cube
- s off 表示关闭光滑组
void ObjLoader::load(QString filename)
{// 打开文件QFile file(filename);if(!file.open(QIODevice::ReadOnly)){qDebug()<<"[Error] fail to open file: "<< filename;return;}// 读取文件QTextStream ts(&file);// 临时存储QVector<QVector3D> v;QVector<QVector3D> vn;QVector<QVector3D> vt;QVector<QStringList> str_faces;QVector<Face> faces;while(!ts.atEnd()){QStringList list = ts.readLine().split(QRegExp("(\\s+)"));list.removeAll(" ");if(list.size() == 0 )break;if(list[0] == "v")v.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),list[3].toFloat()));if(list[0] == "vn")vn.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),list[3].toFloat()));if(list[0] == "vt")vt.push_back(QVector3D(list[1].toFloat(),list[2].toFloat(),0));if(list[0] == "f")str_faces.push_back(list);}for( int i =0; i< str_faces.size(); i++){Face face;for( int j = 1; j<=3; j++) //obj中顶点索引是从1开始{QStringList list = str_faces[i][j].split("/");face.v[j-1] = list[0].toInt() -1;face.t[j-1] = list[1].toInt() -1;face.n[j-1] = list[2].toInt() -1;}faces.push_back(face);}for( int i = 0; i<faces.size();i++){QVector3D a,b,c,na,nb,nc;a = v[faces[i].v[0]];b = v[faces[i].v[1]];c = v[faces[i].v[2]];na = vn[faces[i].n[0]];nb = vn[faces[i].n[1]];nc = vn[faces[i].n[2]];mv.push_back(a.x());mv.push_back(a.y());mv.push_back(a.z());mv.push_back(b.x());mv.push_back(b.y());mv.push_back(b.z());mv.push_back(c.x());mv.push_back(c.y());mv.push_back(c.z());mn.push_back(na.x());mn.push_back(na.y());mn.push_back(na.z());mn.push_back(nb.x());mn.push_back(nb.y());mn.push_back(nb.z());mn.push_back(nc.x());mn.push_back(nc.y());mn.push_back(nc.z());}file.close();std::cout<< filename.toStdString() <<" id succeded!\t model_size:"<<mv.size()/3<<std::endl;
}
效果
暂时还不会弄视频或者动态图,先看个静态效果吧
bunny

Cayman_GT

相关文章:
基于QT使用OpenGL,加载obj模型,进行鼠标交互
目录 功能分析(需求分析)技术点分析OpenGL立即渲染模式可编程渲染管线模式 QOpenGLWidget派生类 glwidget逻辑glwidget.hglwidget.cpp 鼠标交互功能obj格式介绍 效果bunnyCayman_GT 功能分析(需求分析) 基于QT平台,使…...
三大赛题指南发布!2023 冬季波卡黑客松本周末开启 Workshop
2023 年一众黑客松赛事中,为什么我们建议您选择波卡黑客松大赛?或许答案在于——作为开发者极度友好的技术生态,波卡能够从参赛者的立场出发,为大家提供从 0 到 1 实现项目孵化成长的机会。这里聚集了一线技术专家的资源力量&…...
数据结构与算法(Java版) | 算法的空间复杂度简介
关于算法的空间复杂度,下面我给大家作一个简单介绍。 类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)定义为该算法所耗费的存储空间,同样,它也是问题规模n的一个函数。 其实,…...
大数据-之LibrA数据库系统告警处理(ALM-12037 NTP服务器异常)
告警解释 当NTP服务器异常时产生该告警。 当NTP服务器异常消除时,该告警恢复。 告警属性 告警ID 告警级别 可自动清除 12037 严重 是 告警参数 参数名称 参数含义 ServiceName 产生告警的服务名称。 RoleName 产生告警的角色名称。 HostName 异常N…...
烟草5G智慧工厂数字孪生可视化平台,赋能烟草工业数字化智慧转型
随着卷烟工厂提质增效需求增强,信息化建设推进及生产制造系统智能化改革发展,各生产单元逐步升级完善数字化,最终实现智能制造成为必然趋势。因此,5G卷烟加工工厂的数字化转型迫在眉睫。中国烟草制造行业正迈向全新的市场经济时代…...
PHP编写采集药品官方数据的程序
在 PHP 中编写爬虫程序,首先我们需要引入一些必要的库,如 curl 和 file_get_contents。然后,我们需要设置爬虫ip信息,以便我们可以从指定的爬虫ip服务器上获取数据。 // 引入必要的库 require_once curl.php;// 设置爬虫ip信息 $p…...
解决Jenkins执行git脚本时报错:No such device or address问题
问题现象: Jenkins执行BeanShell脚本时,报错:jenkins fatal: could not read Username for http://112.11.120.1: No such device or address 解决方案: 解决服务器拉取git仓库的代码权限,使用高级子模块克隆功能。…...
LCD英文字模库(16x8)模拟测试程序
字模 字模,就是把文字符号转换为LCD能识别的像素点阵信息。 电子发烧友可能都熟悉字模的用途。就是调用者通过向LCD模块发送字模数据,LCD根据字模数据在LCD面板上相应的像素描绘出图形或文字。 现在,大部分的LCD都内置了字模库,…...
二分法
文章目录 二分法概述二分 > value最左的位置二分 < value最右的位置局部最小值问题 二分法概述 什么是二分法呢?相信大家都有所了解,举个最经典的二分的例子。 给定一个整型有序数组,和一个值 v a l u e value value,如…...
Linux文件类型与权限及其修改
后面我们写代码时,写完可能会出现没有执行权限什么的,所以我们要知道文件都有哪些权限和类型。 首先 就像我们之前目录结构图里面有个/dev,它就是存放设备文件的,也就是说,哪怕是一个硬件设备,例如打印机啥的…...
RPC 框架 openfeign 介绍和学习使用总结
一、基本概念 RPC 远程过程调用(Remote Procedure Call)的缩写形式 Birrell 和 Nelson 在 1984 发表于 ACM Transactions on Computer Systems 的论文《Implementing remote procedure calls》对 RPC 做了经典的诠释。 RPC 是指计算机 A 上的进程&am…...
大厂真题:【DP/贪心】字节跳动2023秋招-小红的 01 串
题目描述与示例 题目描述 小红拿到了一个 01 串,她准备将若干个字符1 染成红色,将若干个字符0 染成蓝色,但有个限制:如果一个0 和一个1 相邻,那么它们不能同时染色。 小红想知道,最多可以染多少个字符&a…...
【技术类-01】doc转PDF程序卡死的解决方案,
摘要: 1、报错: raise AttributeError("%s.%s" % (self._username_, attr))) 2、表现:doc转PDF卡死(白条不动或出现以上英文) 3、解决:在docx保存代码行后面加上time.sleep(3) 4、…...
探索未来,开启无限可能:打造智慧应用,亚马逊云科技大语言模型助您一臂之力
文章目录 什么是大模型?大模型训练方法亚马逊云科技推出生成式AI新工具 —— aws toolkit使用教程 总结 什么是大模型? 近期,生成式大模型是人工智能领域的研究热点。这些生成式大模型,诸如文心一言、文心一格、ChatGPT、Stable …...
HTML点击链接强制触发下载
常见网页中会有很多点击链接即下载的内容,以下示范一下如何实现 <a href"文件地址" download"下载的文件名字(不包括后缀)">强制下载</a> 下面举个例子: <a href"./image/test.jpg"…...
Paimon 与 Spark 的集成(一)
Paimon Apache Paimon (incubating) 是一项流式数据湖存储技术,可以为用户提供高吞吐、低延迟的数据摄入、流式订阅以及实时查询能力。Paimon 采用开放的数据格式和技术理念,可以与 ApacheFlink / Spark / Trino 等诸多业界主流计算引擎进行对接…...
批量导入SQL Server中的建表、建存储过程和建调度作业的文件
要批量导入SQL Server中的建表、建存储过程和建调度作业的文件,可以按照以下步骤进行操作: 确保你拥有适当的权限:在导入这些文件之前,请确保你具有足够的权限来创建表、存储过程和调度作业。通常需要具备数据库管理员(…...
启动Hbase出现报错
报错信息:slave1:head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewanggiqi-regionserver-slavel.out’ for reading: No such file or direslave2: head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewangqiqi-regionserver-slave2.out’ for …...
【数据结构】——栈、队列简答题模板
目录 一、栈(一)栈的基本概念(二)栈的应用(三)栈的代码实现(四)递归算法(五)栈与队列的区别 二、队列(一)队列的基本概念(…...
基于若依的ruoyi-nbcio流程管理系统仿钉钉流程json转bpmn的flowable的xml格式(排它条件网关)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 这个章节来完成并行网关与排它条件网关的功能 1、前端 目前就修改了排它条件网关的前端条件部分…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
