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

【Qt】图片绘制不清晰的问题

背景

实现一个图片浏览器,可以支持放大/缩小查看图片。主要组件如下:

// canvaswidget.h
#ifndef CANVASWIDGET_H
#define CANVASWIDGET_H#include <QWidget>class CanvasWidget : public QWidget
{Q_OBJECT
public:explicit CanvasWidget(QImage img, QWidget *parent = nullptr);void zoomIn();void zoomOut();signals:protected:QSize sizeHint();void paintEvent(QPaintEvent *event) override;void wheelEvent(QWheelEvent *event) override;private:qreal scale;QPixmap pixmap;
};#endif // CANVASWIDGET_H
// canvaswidget.cpp
#include "canvaswidget.h"
#include <QWheelEvent>
#include <QPainter>
#include <QPixmap>CanvasWidget::CanvasWidget(QImage img, QWidget *parent): QWidget{parent}, scale(1.0)
{pixmap = QPixmap::fromImage(img);
}void CanvasWidget::zoomIn() {scale = fmin(scale + 0.1, 10);update();
}void CanvasWidget::zoomOut() {scale = fmax(scale - 0.1, 0.1);update();
}void CanvasWidget::paintEvent(QPaintEvent *event) {if(!pixmap) {return QWidget::paintEvent(event);}QPainter p(this);p.setRenderHint(QPainter::Antialiasing);p.setRenderHint(QPainter::SmoothPixmapTransform);p.scale(scale, scale);p.drawPixmap(0,0,pixmap); // draw image
}void CanvasWidget::wheelEvent(QWheelEvent *event)
{if(event->modifiers() == Qt::ControlModifier) {QPointF delta = event->angleDelta();int v_delta = delta.y();if(v_delta > 0) {zoomIn();} else {zoomOut();}update();adjustSize();} else {QWidget::wheelEvent(event);}
}
QSize CanvasWidget::sizeHint()
{return QSize(800,800);
}

问题

在这种实现方式下,缩小图片时,图片会变得非常模糊,有非常明显的锯齿问题。
如下图所示,A是Windows自带图片查看器的效果,B是上述实现的效果。可以看出虽然B比A更大,但却更不清晰,有明显的锯齿。

在这里插入图片描述

尝试解决

为了解决这个不清晰的问题,尝试了很多种方案,方案及其实现方法如下:

不scale QPainter,而是在指定区域绘制Pixmap

p.drawPixmap(0,0,pixmap.size().width() * scale, pixmap.size().height * scale, pixmap);

使用QGraphicsView绘制图片

    QPixmap pixmap("/path/to/image.png");QGraphicsScene scene;QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);scene.addItem(item);QGraphicsView view;view.resize(800,600);view.setScene(&scene);// Optionally set view propertiesview.setRenderHint(QPainter::Antialiasing);   // Improve rendering qualityview.setDragMode(QGraphicsView::ScrollHandDrag); // Enable draggingview.setAlignment(Qt::AlignCenter);           // Center the imageview.fitInView(item, Qt::KeepAspectRatio);    // Scale to fit the view// Show the viewview.show();

使用QWebEngineView绘制图片

    QWebEngineView web_view;QString htmlContent = R"(<!DOCTYPE html><html><head><style>body { margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; }img { max-width: 100%; max-height: 100%; }</style></head><body><img src="/path/to/image.png" alt="Image Not Found"></body></html>)";web_view.setHtml(htmlContent, QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/"));web_view.resize(800, 600);web_view.show();

将图片作为texture在QOpenGLWidget中绘制图片

#ifndef OPENGLIMAGE_H
#define OPENGLIMAGE_H#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <memory>class OpenGLImage : public QOpenGLWidget, protected QOpenGLFunctions
{Q_OBJECT
public:explicit OpenGLImage(QWidget *parent = nullptr);~OpenGLImage();QSize minimumSizeHint() const override;QSize sizeHint() const override;void loadImage(QString& path);QMatrix4x4 getViewMatrix() const;QMatrix4x4 getModelMatrix() const;protected:void initializeGL() override;void paintGL() override;void resizeGL(int width, int height) override;void wheelEvent(QWheelEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void keyPressEvent(QKeyEvent *event) override;void keyReleaseEvent(QKeyEvent* event) override;private:void setupDefaultShaderProgram();void setupDefaultTransform();void drawImage();void moveImage(const QPointF& cursorPos);void rotateImage(const QPointF& cursorPos);std::unique_ptr<QOpenGLShaderProgram> shaderProgram;std::unique_ptr<QOpenGLTexture> texture;std::unique_ptr<QImage> image;QOpenGLBuffer vbo;QOpenGLVertexArrayObject vao;QOpenGLBuffer ebo;bool isTextureSync;QColor clearColor;float norm_h;QSize viewSize;QVector3D cameraPos;QVector3D imagePos;QVector3D imageAngle;float viewAngle;float focalLength;QPointF lastClickPos;bool isRotMode;
};#endif // OPENGLIMAGE_H
#include "glimageview.h"
#include <vector>
#include <QtMath>
#include <iostream>
#include <QResizeEvent>#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1#define DEFAULT_CAMERA_POS_X (0.0f)
#define DEFAULT_CAMERA_POS_Y (0.0f)
#define DEFAULT_CAMERA_POS_Z (-2.0f)#define CLIP_NEAR (0.01f)
#define CLIP_FAR (100.0f)#define MIN_FOCAL 1.0f
#define MAX_FOCAL 150.0fOpenGLImage::OpenGLImage(QWidget *parent): QOpenGLWidget(parent),shaderProgram(nullptr),texture(nullptr),image(nullptr),isTextureSync(false),clearColor(Qt::gray),norm_h(-1.0f),viewSize(640,640),ebo(QOpenGLBuffer::Type::IndexBuffer),viewAngle(45.0f),isRotMode(false)
{focalLength = 1/qTan(qDegreesToRadians(viewAngle/2.0f));
}OpenGLImage::~OpenGLImage()
{
}void OpenGLImage::initializeGL()
{initializeOpenGLFunctions();setupDefaultShaderProgram();
}void OpenGLImage::paintGL()
{glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);drawImage();
}void OpenGLImage::resizeGL(int width, int height)
{viewSize = QSize(width, height);
}QSize OpenGLImage::minimumSizeHint() const
{int min_h = (int)(320.0f * norm_h);return QSize(320, min_h);
}QSize OpenGLImage::sizeHint() const
{return viewSize;
}void OpenGLImage::wheelEvent(QWheelEvent *event)
{QPoint numDegrees = event->angleDelta() / 8;float degree = (float)numDegrees.y() * -1.0f;degree /= 2.0f;if (viewAngle+degree > MIN_FOCAL && viewAngle+degree < MAX_FOCAL) {viewAngle += degree;focalLength = 1/qTan(qDegreesToRadians(viewAngle/2.0f));}event->accept();update();
}void OpenGLImage::drawImage() {if (image.get() == nullptr) return;glViewport(0, 0, viewSize.width(), viewSize.height());// qDebug() << viewSize.width() << ", " << viewSize.height() << "\n";// setup vertex array objectif (!vao.isCreated()){vao.create();}vao.bind();// setup vertex buffer objectstd::vector<GLfloat> coords;// bottom left;coords.push_back(-1.0f);coords.push_back(-1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(0.0f);coords.push_back(0.0f);// bottom rightcoords.push_back(1.0f);coords.push_back(-1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(1.0f);coords.push_back(0.0f);// top rightcoords.push_back(1.0f);coords.push_back(1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(1.0f);coords.push_back(1.0f);// top leftcoords.push_back(-1.0f);coords.push_back(1.0f * norm_h);coords.push_back(0.0f);// tex coordinatecoords.push_back(0.0f);coords.push_back(1.0f);if (!vbo.isCreated()){vbo.create();}vbo.bind();vbo.allocate(coords.data(), coords.size()*sizeof(GLfloat));// setup vertex element object// [bl, br, tr, tl]static const std::vector<GLuint> indices {0, 1, 2,2, 3, 0};if (!ebo.isCreated()){ebo.create();}ebo.bind();ebo.allocate(indices.data(), indices.size()*sizeof(GLuint));// associate vertex and buffershaderProgram->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);shaderProgram->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);shaderProgram->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 5 * sizeof(GLfloat));shaderProgram->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat));// assign transform matricesQMatrix4x4 projection; // projection matrxi must update everytime!float ratio = ((float)viewSize.width())/((float)viewSize.height());projection.perspective(viewAngle, ratio, CLIP_NEAR, CLIP_FAR);QMatrix4x4 model = getModelMatrix();model.rotate(imageAngle.x(), 0.0f, 1.0f, 0.0f);model.rotate(imageAngle.y()*-1.0f, 1.0f, 0.0f, 0.0f);shaderProgram->setUniformValue("model", model);QMatrix4x4 viewMat = getViewMatrix();shaderProgram->setUniformValue("view", viewMat);shaderProgram->setUniformValue("projection", projection);// setup textureif (texture.get() == nullptr || !isTextureSync) {QImage& img = *image.get();texture = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(img));isTextureSync = true;}texture->bind();glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0 );
}void OpenGLImage::setupDefaultShaderProgram()
{QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);const char *vsrc ="attribute highp vec3 vertex;\n""uniform mediump mat4 model;\n""uniform mediump mat4 view;\n""uniform mediump mat4 projection;\n""\n""attribute mediump vec2 texCoord;\n""varying mediump vec2 texc;\n""void main(void)\n""{\n""    gl_Position = projection * view * model * vec4(vertex, 1.0f);\n""    texc = texCoord;\n""}\n";vshader->compileSourceCode(vsrc);QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);const char *fsrc ="uniform sampler2D texture;\n""varying mediump vec2 texc;\n""void main(void)\n""{\n""    gl_FragColor = texture2D(texture, texc);\n""}\n";fshader->compileSourceCode(fsrc);shaderProgram = std::unique_ptr<QOpenGLShaderProgram>(new QOpenGLShaderProgram(this));shaderProgram->addShader(vshader);shaderProgram->addShader(fshader);// assign locations of vertex and texture coordinatesshaderProgram->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);shaderProgram->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);shaderProgram->link();shaderProgram->bind();shaderProgram->setUniformValue("texture", 0);
}void OpenGLImage::setupDefaultTransform() {cameraPos = QVector3D(DEFAULT_CAMERA_POS_X, DEFAULT_CAMERA_POS_Y, DEFAULT_CAMERA_POS_Z);imagePos = QVector3D();imageAngle = QVector3D();
}void OpenGLImage::loadImage(QString& path) {QImage* p = new QImage(QImage(path).mirrored());image = std::unique_ptr<QImage>(p);isTextureSync = false;norm_h = (float)((float)image->height()/(float)image->width());int h = (int)((float)viewSize.width()*norm_h);viewSize = QSize(viewSize.width(), h);resize(viewSize);setupDefaultTransform();
}QMatrix4x4 OpenGLImage::getViewMatrix() const {QVector3D up(0.0f, 1.0f, 0.0f);QMatrix4x4 ret;ret.translate(cameraPos);QVector3D center(cameraPos.x(), cameraPos.y(), imagePos.z());ret.lookAt(QVector3D(), center, up);return ret;
}QMatrix4x4 OpenGLImage::getModelMatrix() const {QMatrix4x4 ret;ret.translate(imagePos);return ret;
}void OpenGLImage::mousePressEvent(QMouseEvent *event) {lastClickPos = event->localPos();qDebug() << lastClickPos;
}// movement is weird somehow...
void OpenGLImage::mouseMoveEvent(QMouseEvent *event) {if (isRotMode) {rotateImage(event->localPos());} else {moveImage(event->localPos());}lastClickPos = event->pos();event->accept();update();
}void OpenGLImage::moveImage(const QPointF &cursorPos) {QPointF delta = cursorPos-lastClickPos;float factor = qAbs(imagePos.z()-cameraPos.z()) / focalLength;factor /= (qMax(viewSize.width(), viewSize.height()));factor *= 3.5f;qDebug() << "dx=" << delta.x();qDebug() << "dy=" << delta.y();qDebug() << "L=" << (imagePos.z()-cameraPos.z());qDebug() << "focalLength=" << focalLength;qDebug() << "factor" << factor;delta *= factor;imagePos += QVector3D(delta.x(), -1.0f*delta.y(), 0.0f);
}void OpenGLImage::rotateImage(const QPointF &cursorPos) {QPointF delta = cursorPos-lastClickPos;delta.setX(delta.x() / (qreal)viewSize.width());delta.setX(delta.x() * 180.0f);delta.setY(delta.y() / (qreal)viewSize.height());delta.setY(delta.y() * -180.0f);qDebug() << delta;imageAngle += QVector3D(delta.x(), delta.y(), 0.0f);
}void OpenGLImage::mouseReleaseEvent(QMouseEvent *event) {
}void OpenGLImage::keyPressEvent(QKeyEvent *event) {if (event->key() == Qt::Key_Control) {qDebug() << "ctrl is pressed";isRotMode = true;} else {// call base class method as event is not handled.QOpenGLWidget::keyPressEvent(event);}
}void OpenGLImage::keyReleaseEvent(QKeyEvent *event) {if (event->key() == Qt::Key_Control) {qDebug() << "ctrl is released";isRotMode = false;} else {// call base class method as event is not handled.QOpenGLWidget::keyReleaseEvent(event);}
}

如下图所示,不同方案的效果略有不同,但所有方案都会出现缩小后图片变模糊的问题:
在这里插入图片描述

问题所在

最终在网友们的帮助下,发现了问题所在:这些实现方法在修改图片大小时都会对图片进行压缩。

比如void QPainter::drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source),在指定矩形区域内绘制图片,如果指定的矩形区域比图片本身尺寸小,绘制过程中就会对图片进行压缩,导致图片变得模糊。

如果想要将图片变小的同时,保持图片的清晰度,应该直接使用QPixmap的scaled函数:

p.drawPixmap(0,0,pixmap.scaled(pixmap.size() * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation));

效果如下,左边是新的实现方法的效果,右边是Windows自带的图片查看软件的效果:
在这里插入图片描述

其实我一开始的实现方法不算错,甚至是官方建议的,在QPixmap的文档中提到:

In some cases it can be more beneficial to draw the pixmap to a painter with a scale set rather than scaling the pixmap. This is the case when the painter is for instance based on OpenGL or when the scale factor changes rapidly.

图片查看器其实就会频繁改变scale按照建议就是应该采用修改QPainter的scale的方法,但这种方法确实会导致图片清晰度变低,出现模糊的问题。

相关文章:

【Qt】图片绘制不清晰的问题

背景 实现一个图片浏览器&#xff0c;可以支持放大/缩小查看图片。主要组件如下&#xff1a; // canvaswidget.h #ifndef CANVASWIDGET_H #define CANVASWIDGET_H#include <QWidget>class CanvasWidget : public QWidget {Q_OBJECT public:explicit CanvasWidget(QImag…...

2008年IMO几何预选题第3题

设有两个圆凸内接四边形 A B Q D ABQD ABQD 和 B P Q C BPQC BPQC, 在线段 P Q PQ PQ 上存在一点 E E E, 使得, ∠ E A P ∠ E D Q \angle EAP\angle EDQ ∠EAP∠EDQ, ∠ E B P ∠ E C Q \angle EBP\angle ECQ ∠EBP∠ECQ. 求证: A A A, B B B, C C C, D D D 四点共…...

NAT拓展

NAT ALG&#xff08;NAT应用级网&#xff09; 为某些应用层协议&#xff0c;因为其报文内容可能携带IP相关信息&#xff0c;而普通NAT转化无法将这些IP转化&#xff0c;从而导致协议无法正常运行 例如FTP&#xff0c;DHCP&#xff0c;RSTP&#xff0c;ICMP&#xff0c;IPSEC…...

Flink四大基石之State

State state 可以理解为-- 历史计算结果 有状态计算和无状态计算 无状态计算: 不需要考虑历史数据, 相同的输入,得到相同的输出!如:map, 将每个单词记为1, 进来一个hello, 得到(hello,1),再进来一个hello,得到的还是(hello,1) 有状态计算: 需要考虑历史数据, 相同的输入,可…...

Spacy小笔记:zh_core_web_trf、zh_core_web_lg、zh_core_web_md 和 zh_core_web_sm区别

Spacy小笔记 最近频繁用到spacy&#xff0c;就小记一下。 2024.11.29 zh_core_web_trf、zh_core_web_lg、zh_core_web_md 和 zh_core_web_sm区别 首先&#xff0c;它们都是预训练的中文模型&#xff1a; zh_core_web_trf:395M 架构: 基于 Transformer 架构&#xff08;bert…...

第六届智能控制、测量与信号处理国际学术会议 (ICMSP 2024)

重要信息 2024年11月29日-12月1日 中国陕西西安石油大学雁塔校区 大会官网&#xff1a;www.icmsp.net 大会简介 第六届智能控制、测量与信号处理国际学术会议&#xff08;ICMSP 2024&#xff09;由西安石油大学、中海油田服务股份有限公司、浙江水利水电学院与中国石油装备…...

docker服务容器化

docker服务容器化 1 引言2 多个容器间网络联通2.1 单独创建关联2.2 创建时关联 3 服务搭建3.1 镜像清单3.2 容器创建 4 联合实战4.2 flink_sql之kafka到starrocks4.2 flink_sql之mysql到starrocks 5 文献借鉴 1 引言 ​ 利用docker可以很效率地搭建服务&#xff0c;本文在win1…...

【QT】控件8

1.QDial 通过调节旋钮位置来控制窗口的不透明度&#xff1a; void Widget::on_dial_valueChanged(int value) {qDebug()<<value;this->setWindowOpacity((double)value/100); }效果演示&#xff1a; 2.Date/Time Edit 计算两个日期的差值 ui界面设计 计算按钮按下…...

漫谈推理谬误——错误因果

相关文章 漫谈推理谬误——错误假设-CSDN博客文章浏览阅读736次&#xff0c;点赞22次&#xff0c;收藏3次。在日常生活中&#xff0c;我们会面临各种逻辑推理&#xff0c;有些看起来一目了然&#xff0c;有些非常的科学严谨&#xff0c;但也有很多似是而非&#xff0c;隐藏了陷…...

【数据结构】队列实现剖析:掌握队列的底层实现

在计算机科学中&#xff0c;**队列&#xff08;Queue&#xff09;**是一种常见的数据结构&#xff0c;它遵循先进先出&#xff08;FIFO&#xff0c;First In First Out&#xff09;的原则。队列的应用非常广泛&#xff0c;例如任务调度、资源管理、进程通信等。本篇文章旨在为计…...

【C++】IO库(二):文件输入输出

8.2 文件输入输出 头文件 fstream 定义了三个类型来之支持文件IO&#xff0c;分别是&#xff1a; ifstream&#xff1a;从一个给定文件读取数据&#xff1b;ofstream&#xff1a;向一个给定文件写入数据&#xff1b;fstream&#xff1a;读写给定文件。 在 C 当中&#xff0c…...

105.【C语言】数据结构之二叉树求总节点和第K层节点的个数

目录 1.求二叉树总的节点的个数 1.容易想到的方法 代码 缺陷 思考:能否在TreeSize函数内定义静态变量解决size的问题呢? 其他写法 运行结果 2.最好的方法:分而治之 代码 运行结果 2.求二叉树第K层节点的个数 错误代码 运行结果 修正 运行结果 其他写法 1.求二…...

力扣637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。 提示&#xff1a; 树中节点数量在 [1, 104] 范围内-231 < Node.val < 231 - 1 代码&#xff1a; /*** Definition for a binary tree node.* stru…...

【前端】Next.js 服务器端渲染(SSR)与客户端渲染(CSR)的最佳实践

关于Next.js 服务器端渲染&#xff08;SSR&#xff09;与客户端渲染&#xff08;CSR&#xff09;的实践内容方面&#xff0c;我们按下面几点进行阐述。 1. 原理 服务器端渲染 (SSR): 在服务器上生成完整的HTML页面&#xff0c;然后发送给客户端。这使得用户在首次访问时能够…...

路径规划之启发式算法之一:A-Star(A*)算法

A*算法是一种启发式搜索算法&#xff0c;常用于解决路径规划问题。 一、A*算法的定义与原理 A*算法是一种用于在图形或网格中查找最短路径的算法。它在搜索过程中综合考虑了每个节点的实际距离&#xff08;g值&#xff09;和预估距离&#xff08;h值&#xff09;&#xff0c;以…...

Android复习代码1-4章

public class RudioButton extends AppCompatActivity {Overrideprotected void onCreate(Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_rudio_button);// 找到RadioGroup和TextView的实例RadioGroup radioGrou…...

【问题】webdriver.Chrome()设置参数executable_path报不存在

场景1: 标红报错unresolved reference executable_path 场景2: 执行报错TypeError: __init__() got an unexpected keyword argument executable_path 原因&#xff1a; 上述两种场景是因为selenium4开始不再支持某些初始化参数。比如executable_path 解决&#xff1a; 方案…...

win10系统安装docker-desktop

1、开启Hyper-v ———————————————— Hyper-V 是微软提供的一种虚拟化技术&#xff0c;它允许你在同一台物理计算机上运行多个独立的操作系统实例。这种技术主要用于开发、测试、以及服务器虚拟化等领域。 —————————————————————— &#…...

小程序-基于java+SpringBoot+Vue的乡村研学旅行平台设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…...

组件A底部栏(position: fixed )事件使用$emit更新内容失败bug解决

今天遇到一个很离奇的bug&#xff0c;记录一下 问题&#xff1a;在组件内底部栏使用$emit触发按钮事件但打印出来的值是初始化的值&#xff0c;更新的值被重置导致更新失败 原因&#xff1a;组件内底部使用了 position: fixed; 固定&#xff0c; 导致组件内插槽 this 与 保存按…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...