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

Qt实现简单的漫游器

文章目录

  • Qt的OpenGL窗口
  • GLSL的实现
  • 摄像机类的实现
  • 简单的漫游器

Qt的OpenGL窗口

 Qt主要是使用QOpenGLWidget来实现opengl的功能。
 QOpenGLWidget 提供了三个便捷的虚函数,可以重载,用来重新实现典型的OpenGL任务:

  • paintGL:渲染OpenGL场景。widget 需要更新时调用。
  • resizeGL:设置OpenGL视口、投影等。widget 调整大小(或首次显示)时调用。
  • initializeGL:设置OpenGL资源和状态。第一次调用 resizeGL() / paintGL() 之前调用一次。
  • 如果需要从paintGL()以外的位置触发重新绘制(典型示例是使用计时器设置场景动画),则应调用widget的update()函数来安排更新。
  • 调用paintGL()、resizeGL()或initializeGL()时,widget 的OpenGL呈现上下文将变为当前。如果需要从其他位置(例如,在 widget 的构造函数或自己的绘制函数中)调用标准OpenGL API函数,则必须首先调用makeCurrent()。
  • QOpenGLFunctions_X_X_Core 提供OpenGL X.X版本核心模式的所有功能。是对OpenGL函数的封装:
  • initializeOpenGLFunctions:初始化OpenGL函数,将Qt里的函数指针指向显卡的函数。
#include <QOpenGLWidget> 
#include <QOpenGLFunctions_3_3_Core> class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core 
{ 
Q_OBJECT 
public: 
explicit MyOpenGLWidget (QWidget *parent = nullptr); 
protected: 
virtual void initializeGL(); 
virtual void resizeGL(int w, int h); 
virtual void paintGL(); 
};
void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();
}
void MyOpenGLWidget::resizeGL(int w, int h)
{Q_UNUSED(w);Q_UNUSED(h);
}
void MyOpenGLWidget::paintGL()
{glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

在这里插入图片描述

以上是最简单的实现版本。

GLSL的实现

 由于是最简单的漫游器,所以我们实现的版本只需要一个顶点着色器和一个片段着色器即可。
shapes.vert

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;out vec2 texCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;void main(){gl_Position = projection * view * model * vec4(aPos, 1.0f);texCoord = aTexCoord;
}

shapes.frag

#version 330 core
out vec4 FragColor;
in vec2 texCoord;uniform sampler2D texturewall;
uniform sampler2D texturesmile;
uniform sampler2D textureSmall;uniform float ratio;
void main(){FragColor = mix(texture(texturewall,texCoord),texture(texturesmile,texCoord),ratio);
}

摄像机类的实现

 这边实现了一个可以对模型进行上下左右移动,移动视角,放大缩小的操作。
摄像机类初始化了几个变量

// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;

偏航角默认为90度,灵敏度主要用于控制鼠标移动时视角的变化量。

#ifndef CAMERA_H
#define CAMERA_H#include<QMatrix4x4>#include <vector>// 移动方向枚举量. 是一种抽象,以避开特定于窗口系统的输入方法
// 我们这里是WSAD
enum Camera_Movement {FORWARD,BACKWARD,LEFT,RIGHT
};// 默认值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;// 一个抽象的camera类,用于处理输入并计算相应的Euler角度、向量和矩阵,以便在OpenGL中使用
class Camera
{
public:// camera AttributesQVector3D Position;QVector3D Front;QVector3D Up;QVector3D Right;QVector3D WorldUp;// euler Anglesfloat Yaw;float Pitch;// camera optionsfloat MovementSpeed;float MouseSensitivity;float Zoom;// constructor with vectorsCamera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM){Position = position;WorldUp = up;Yaw = yaw;Pitch = pitch;updateCameraVectors();}// constructor with scalar valuesCamera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM){Position = QVector3D(posX, posY, posZ);WorldUp = QVector3D(upX, upY, upZ);Yaw = yaw;Pitch = pitch;updateCameraVectors();}// returns the view matrix calculated using Euler Angles and the LookAt MatrixQMatrix4x4 GetViewMatrix(){QMatrix4x4 theMatrix;theMatrix.lookAt(Position, Position + Front, Up);return theMatrix;}// 处理从任何类似键盘的输入系统接收的输入。接受摄像机定义枚举形式的输入参数(从窗口系统中提取)void ProcessKeyboard(Camera_Movement direction, float deltaTime){float velocity = MovementSpeed * deltaTime;if (direction == FORWARD)Position += Front * velocity;if (direction == BACKWARD)Position -= Front * velocity;if (direction == LEFT)Position -= Right * velocity;if (direction == RIGHT)Position += Right * velocity;}// 处理从鼠标输入系统接收的输入。需要x和y方向上的偏移值。void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true){xoffset *= MouseSensitivity;yoffset *= MouseSensitivity;Yaw   += xoffset;Pitch += yoffset;// 确保当投球超出边界时,屏幕不会翻转if (constrainPitch){if (Pitch > 89.0f)Pitch = 89.0f;if (Pitch < -89.0f)Pitch = -89.0f;}// 使用更新的Euler角度更新前、右和上矢量updateCameraVectors();}// 处理从鼠标滚轮事件接收的输入。仅需要在垂直车轮轴上输入void ProcessMouseScroll(float yoffset){Zoom -= (float)yoffset;if (Zoom < 1.0f)Zoom = 1.0f;if (Zoom > 75.0f)Zoom = 75.0f;}private:// 根据相机的(更新的)Euler角度计算前矢量void updateCameraVectors(){// calculate the new Front vectorfloat PI=3.1415926;QVector3D front;front.setX(cos(Yaw*PI/180.0) * cos(Pitch*PI/180.0));front.setY( sin(Pitch*PI/180.0));front.setZ(sin(Yaw*PI/180.0) * cos(Pitch*PI/180.0));front.normalize();Front = front;// also re-calculate the Right and Up vectorRight = QVector3D::crossProduct(Front, WorldUp);// 标准化向量,因为向上或向下看得越多,向量的长度就越接近0,这会导致移动速度变慢。Right.normalize();Up    = QVector3D::crossProduct(Right, Front);Up.normalize();}
};
#endif

简单的漫游器

 漫游器的实现主要是通过Qt的窗口事件触发后将触发产生的位置偏量给摄像机类进行计算,从摄像机类中得到视图矩阵将模型的位置进行改变。
myopenglwidget.h


#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
#include <QElapsedTimer>
#include "camera.h"class MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{Q_OBJECT
public:enum Shape{None,Circle,Rect,Triangle};explicit MyOpenGLWidget(QWidget *parent = nullptr);~MyOpenGLWidget();void DrawShape(Shape shape);void setWireFrameMode(bool enterWireframe);void onTimeout();
protected:virtual void initializeGL();virtual void resizeGL(int w, int h);virtual void paintGL();
signals:
private:Shape m_shape;QOpenGLShaderProgram shaderProgram;QOpenGLTexture *textureWall;QOpenGLTexture *textureSmile;QOpenGLTexture *textureSmall;QTimer *m_timer;QElapsedTimer m_time;Camera m_camera;// QWidget interface
protected:void keyPressEvent(QKeyEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void wheelEvent(QWheelEvent *event) override;
};#endif // MYOPENGLWIDGET_H

myopenglwidget.cpp

#include "myopenglwidget.h"
#include <QImage>
#include <QKeyEvent>float vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};QVector<QVector3D> cubePositions= {QVector3D( 0.0f, 0.0f, 0.0f),QVector3D( 2.0f, 5.0f, -15.0f),QVector3D(-1.5f, -2.2f, -2.5f),QVector3D(-3.8f, -2.0f, -12.3f),QVector3D( 2.4f, -0.4f, -3.5f),QVector3D(-1.7f, 3.0f, -7.5f),QVector3D( 1.3f, -2.0f, -2.5f),QVector3D( 1.5f, 2.0f, -2.5f),QVector3D( 1.5f, 0.2f, -1.5f),QVector3D(-1.3f, 1.0f, -1.5f)
};#define TIMEOUT 100unsigned int indices[] = { // note that we start from 0!0, 1, 3, // first triangle1, 2, 3 // second triangle
};unsigned int VBO, VAO ,EBO;float ratio = 0.5;
QPoint deltaPos;MyOpenGLWidget::MyOpenGLWidget(QWidget *parent): QOpenGLWidget{parent}
{setFocusPolicy(Qt::StrongFocus);setMouseTracking(true);m_timer = new QTimer(this);connect(m_timer,&QTimer::timeout,this,&MyOpenGLWidget::onTimeout);m_timer->start(TIMEOUT);m_time.start();m_camera.Position = QVector3D(0.0,0.0,3.0);
}MyOpenGLWidget::~MyOpenGLWidget()
{if(!isValid()) return;makeCurrent();glDeleteBuffers(1,&VBO);glDeleteBuffers(1,&EBO);glDeleteVertexArrays(1,&VAO);doneCurrent();
}void MyOpenGLWidget::DrawShape(Shape shape)
{m_shape=shape;update();
}void MyOpenGLWidget::setWireFrameMode(bool enterWireframe)
{makeCurrent();if(enterWireframe)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);elseglPolygonMode(GL_FRONT_AND_BACK,GL_FILL);update();doneCurrent();
}void MyOpenGLWidget::onTimeout()
{update();
}void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();//创建VBO和VAO对象,并赋予IDglGenVertexArrays(1,&VAO);glGenBuffers(1,&VBO);//绑定VAO和VBO对象glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER,VBO);//为当前绑定到target的缓冲区对象创建一个新的数据存储。//如果data不是NULL,则使用来自此指针的数据初始化数据存储glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);//告知显卡如何解析缓冲里的属性值glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)0);//开启VAO管理的第一个属性值glEnableVertexAttribArray(0);//告知显卡如何解析缓冲里的属性值glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)(3*sizeof(float)));//开启VAO管理的第三个属性值glEnableVertexAttribArray(1);glBindBuffer(GL_ARRAY_BUFFER,0);bool success;shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":Shaders/shapes.vert");shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":Shaders/shapes.frag");success = shaderProgram.link();if(!success){qDebug()<<"Error:"<<shaderProgram.log();}shaderProgram.bind();shaderProgram.setUniformValue("ratio",ratio);shaderProgram.setUniformValue("texturewall",0);shaderProgram.setUniformValue("texturesmile",1);shaderProgram.setUniformValue("textureSmall",2);unsigned int EBO;glGenBuffers(1, &EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glEnable(GL_BLEND);glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);textureWall = new QOpenGLTexture(QImage(":Images/images/wall.jpg").mirrored());textureSmile = new QOpenGLTexture(QImage(":Images/images/awesomeface.png").mirrored());textureSmall = new QOpenGLTexture(QImage(":Images/images/small.png").mirrored());glBindVertexArray(0);}void MyOpenGLWidget::resizeGL(int w, int h)
{Q_UNUSED(w);Q_UNUSED(h);
}void MyOpenGLWidget::paintGL()
{QMatrix4x4 model;QMatrix4x4 view;QMatrix4x4 projection;view=m_camera.GetViewMatrix();glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);shaderProgram.bind();projection.perspective(m_camera.Zoom,(float)width()/(height()),0.1,100.0);shaderProgram.setUniformValue("projection", projection);shaderProgram.setUniformValue("view", view);glBindVertexArray(VAO);//glDrawArrays(GL_TRIANGLES, 0, 3);switch(m_shape){case Rect:textureWall->bind(0);textureSmile->bind(1);textureSmall->bind(2);//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);foreach (auto item, cubePositions){model.setToIdentity();model.translate(item);shaderProgram.setUniformValue("model", model);glDrawArrays(GL_TRIANGLES,0,36);}break;case None:break;case Triangle:break;case Circle:break;}}void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{float deltatime=TIMEOUT / 1000.0;switch(event->key()){case Qt::Key_Up:ratio += 0.1;break;case Qt::Key_Down:ratio -= 0.1;break;case Qt::Key_W: m_camera.ProcessKeyboard(FORWARD,deltatime);break;case Qt::Key_S: m_camera.ProcessKeyboard(BACKWARD,deltatime);break;case Qt::Key_D: m_camera.ProcessKeyboard(RIGHT,deltatime);break;case Qt::Key_A: m_camera.ProcessKeyboard(LEFT,deltatime);break;}if(ratio > 1) ratio = 1;if(ratio < 0) ratio = 0;makeCurrent();shaderProgram.bind();shaderProgram.setUniformValue("ratio",ratio);update();doneCurrent();
}void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{static QPoint lastPos(width()/2,height()/2);auto currentPos=event->pos();deltaPos=currentPos-lastPos;lastPos=currentPos;m_camera.ProcessMouseMovement(deltaPos.x(),-deltaPos.y());update();
}void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{   m_camera.ProcessMouseScroll(event->angleDelta().y()/120);update();
}

完整代码链接

相关文章:

Qt实现简单的漫游器

文章目录 Qt的OpenGL窗口GLSL的实现摄像机类的实现简单的漫游器 Qt的OpenGL窗口 Qt主要是使用QOpenGLWidget来实现opengl的功能。  QOpenGLWidget 提供了三个便捷的虚函数&#xff0c;可以重载&#xff0c;用来重新实现典型的OpenGL任务&#xff1a; paintGL&#xff1a;渲染…...

【c语言】文件操作

朋友们&#xff0c;大家好&#xff0c;今天分享给大家的是文件操作的相关知识&#xff0c;跟着我一起学习吧&#xff01;&#xff01; &#x1f388;什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件 程序文…...

【Unity】坐标转换经纬度方法(应用篇)

【Unity】坐标转换经纬度方法&#xff08;应用篇&#xff09; 解决地图中经纬度坐标转换与unity坐标互转的问题。使用线性变换的方法&#xff0c;理论上可以解决小范围内所以坐标转换的问题。 之前有写过[Unity]坐标转换经纬度方法&#xff08;原理篇),在实际使用中&#xff0c…...

element时间选择器el-date-picter使用disabledDate指定禁用的日期

需要的效果 <el-date-pickerclass"selectstyle"v-model"year"value-format"yyyy"type"year":picker-options"disabledCli"placeholder"选择年"> </el-date-picker>data() {return {disabledCli: {/…...

出学校干了 5 年外包,已经废了

如果不是女朋友和我提分手&#xff0c;我估计现在还没醒悟 本科大专&#xff0c;17年通过校招进入某软件公司做测试&#xff0c;干了接近5年的功能。 今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经…...

day-23 代码随想录算法训练营(19)part09

669.修剪二叉搜索树 思路一&#xff1a;根据二叉搜索树的特性进行中间值与去区间值判断&#xff0c;有三种情况&#xff1a;1.在区间中&#xff0c;所以左右子树都可能在区间中&#xff1b; 2.在区间外面的左侧&#xff0c;必然只有右子树可能存在区间中&#xff1b;3.在区间外…...

JVM编译优化

即时编译器 HotSpot虚拟机中内置了两个即时编译器,分别称为Client Compiler和Server Compiler,或者简称为C1编译器和C2编译器。Java8默认开启Server模式。用户可以使用“-client”或“-server”参数去指定编译模式。 C1编译器启动速度快,关注局部简单可靠的优化,比如方法…...

vue浏览器插件安装-各种问题

方法1&#xff1a;vue.js devtolls插件下载 https://blog.csdn.net/qq_55640378/article/details/131553642 下载地址&#xff1a; Tags vuejs/devtools GitHub npm install 或是 cnpm install 遇到的报错 设置淘宝镜像源&#xff08;推荐使用nrm&#xff0c;这一步是为…...

maven工具-maven的使用-镜像仓库、本地仓、IDEA使用maven

Maven 一、为什么使用maven 添加第三方jar包jar包之间的依赖关系处理jar包之间的冲突获取第三方jar包将项目拆分成多个工程模块实现项目的分布式部署 二、maven简介 ​ Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的…...

Mac鼠标增强工具Smooze Pro

Smooze Pro是一款Mac上的鼠标手势增强工具&#xff0c;可以让用户使用鼠标手势来控制应用程序和系统功能。 它支持多种手势操作&#xff0c;包括单指、双指、三指和四指手势&#xff0c;并且可以自定义每种手势的功能。例如&#xff0c;您可以使用单指向下滑动手势来启动Expos视…...

数据结构-单链表(C语言简单实现)

简介 以顺序结构进行数据存储时&#xff0c;它的特点就是可以用一组任意的存储单元存储数据元素&#xff0c;这组存储单元可以是连续的&#xff0c;也可以是不连续的&#xff0c;这些数据可以存在内存未被占用的任意位置。它也是有缺点的&#xff0c;就是在插入和删除时需要移…...

.netcore grpc身份验证和授权

一、鉴权和授权&#xff08;grpc专栏结束后会开启鉴权授权专栏欢迎大家关注&#xff09; 权限认证这里使用IdentityServer4配合JWT进行认证通过AddAuthentication和AddAuthorization方法进行鉴权授权注入&#xff1b;通过UseAuthentication和UseAuthorization启用鉴权授权增加…...

分布式 - 服务器Nginx:一小时入门系列之负载均衡

文章目录 1. 负载均衡2. 负载均衡策略1. 轮询策略2. 最小连接策略3. IP 哈希策略4. 哈希策略5. 加权轮询策略 1. 负载均衡 跨多个应用程序实例的负载平衡是一种常用技术&#xff0c;用于优化资源利用率、最大化吞吐量、减少延迟和确保容错配置。‎使用 nginx 作为非常有效的HT…...

Linux学习之基本指令二

-----紧接上文 在了解cat指令之前&#xff0c;我们首先要了解到Linux下一切皆文件&#xff0c;在学习c语言时我们就已经了解到了 对文件输入以及读入的操作&#xff08;向显示器打印&#xff0c;从键盘读取数据&#xff09;&#xff0c;对于Linux下文件的操作&#xff0c;也是…...

神经网络基础-神经网络补充概念-41-梯度的数值逼近

概念 梯度的数值逼近是一种用于验证梯度计算正确性的方法&#xff0c;它通过近似计算梯度来与解析计算的梯度进行比较。虽然数值逼近在实际训练中不常用&#xff0c;但它可以用来检查手动或自动求导的实现是否正确。 代码实现 import numpy as np# 定义函数 f(x) x^2 def f…...

tornado在模板中遍历二维数组

要在Tornado模板中遍历一个二维数组&#xff0c;你可以使用Tornado的模板语法来实现迭代和显示数组中的每个元素。 以下是一个示例&#xff0c;演示如何在Tornado模板中遍历和显示二维数组的内容&#xff1a; template.html: <!DOCTYPE html> <html> <head&g…...

前端-初始化Vue3+TypeScript

如果使用如下命令初始化项目&#xff0c;项目很干净&#xff0c;很适合了解项目的各个结构。 npm init vitelatest如果使用如下命令初始化项目&#xff0c;是可以选择你需要的组件 npm init vuelatest...

龙蜥社区安全联盟(OASA)正式成立,启明星辰、绿盟、360 等 23 家厂商重磅加入

7 月 28 日&#xff0c;由启明星辰、绿盟、360、阿里云、统信软件、浪潮信息、中兴通讯&#xff5c;中兴新支点、Intel、中科院软件所等 23 家单位共同发起的龙蜥社区安全联盟&#xff08;OASA&#xff0c;OpenAnolisSecurityAlliance&#xff09;&#xff08;以下简称“安全联…...

Flask-SQLAlchemy

认识Flask-SQLAlchemy Flask-SQLAlchemy 是一个为 Flask 应用增加 SQLAlchemy 支持的扩展。它致力于简化在 Flask 中 SQLAlchemy 的使用。SQLAlchemy 是目前python中最强大的 ORM框架, 功能全面, 使用简单。 ORM优缺点 优点 有语法提示, 省去自己拼写SQL&#xff0c;保证SQL…...

大数据bug-sqoop(二:sqoop同步mysql数据到hive进行字段限制。)

一&#xff1a;sqoop脚本解析。 #&#xff01;/bin/sh mysqlHost$1 mysqlUserName$2 mysqlUserPass$3 mysqlDbName$4 sql$5 split$6 target$7 hiveDbName$8 hiveTbName$9 partFieldName${10} inputDate${11}echo ${mysqlHost} echo ${mysqlUserName} echo ${mysqlUserPass} ec…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...