当前位置: 首页 > 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 与 保存按…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...

2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版

1.题目描述 2.思路 当前的元素可以重复使用。 &#xff08;1&#xff09;确定回溯算法函数的参数和返回值&#xff08;一般是void类型&#xff09; &#xff08;2&#xff09;因为是用递归实现的&#xff0c;所以我们要确定终止条件 &#xff08;3&#xff09;单层搜索逻辑 二…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...