Qt扫盲-Qt Paint System 概述

Qt Paint System 概述

  • 一、概述
  • 二、绘图设备和后端
    • 1. Widget
    • 2. Image
    • 3. Pixmap
    • 4. OpenGL绘制设备
    • 5. Picture
    • 6. 自定义绘制后端
  • 三、绘图与填充
    • 1. Drawing
    • 2. 填充 Filling
  • 四、坐标系统
    • 1. 渲染
    • Window-Viewport转换
  • 五、读写图像文件
    • 1. QMovie
  • 六、绘图相关设备

一、概述

Qt的paint系统可以使用相同的API在屏幕和打印设备上进行绘图,它主要是基于QPainter、QPaintDevice和QPaintEnengine类。

QPainter用于执行绘制操作,QPaintDevice是一个二维空间的抽象,可以使用QPainter在其上进行绘制,QPaintEngine提供了 QPainter 用于在不同类型设备上绘制的界面。QPaintEngine 类由 QPainter 和 QPaintDevice 在内部被使用,并且对我们应用开发程序员隐藏,除非我们创建自己的绘图设备类型。

这种方法的主要好处是,所有绘制都遵循相同的绘制通道,这使得添加新功能的支持变得容易,并为不支持的功能提供默认实现。换句话说就是扩展性很强的。

二、绘图设备和后端

QPaintDevice 类是可绘制对象的基类,即 QPainter 可以在任何 QPaintDevice 的子类上绘制。QPaintDevice 的绘图功能由 QWidget、QImage、QPixmap、QPicture、QPrinter 和 QOpenGLPaintDevice 实现。

下面提到的这些类都是继承了 QPaintDevice 因此就具备了 绘制的功能

1. Widget

QWidget类是Qt Widgets模块中用户界面元素的基类。它从window系统接收鼠标、键盘和其他事件,并在屏幕上显示自己。就是窗体系统中的重要一环

2. Image

QImage类提供了一个独立于硬件的图像表示,为I/O和直接像素访问和操作进行了设计和优化。QImage支持多种图像格式,包括单色、8位、32位和alpha混合图像。

使用QImage作为绘制设备的两个优点:

  1. 可以以一种平台无关的方式保证任何绘制操作的像素准确性。
  2. 绘图可以在当前GUI线程之外的另一个线程中执行。

3. Pixmap

QPixmap类是为在屏幕上显示图像而设计和优化的屏幕外图像表示。与 QImage 不同,pixmap中的像素数据是内部的,由底层窗口系统管理,即像素只能通过 QPainter 函数或将 QPixmap 转换为 QImage 来访问。

为了优化使用QPixmap绘图,Qt提供了QPixmapCache类,该类可用于存储临时的pixmap,这些临时的pixmap生成成本很高,而不会使用超过缓存限制的存储空间。

Qt还提供了QBitmap便利类,它继承了QPixmap。QBitmap保证单色(1位深度)像素图,主要用于创建自定义QCursor和QBrush对象,构造QRegion对象。

4. OpenGL绘制设备

如前所述,Qt提供了一些类,使得在Qt应用程序中使用OpenGL变得容易。例如,QOpenGLPaintDevice启用了用于QPainter渲染的OpenGL API。

5. Picture

QPicture类是一个记录和回放QPainter命令的绘制设备。图片以独立于平台的格式将 painter 命令序列化到IO设备。QPicture也是分辨率独立的,即一个 QPicture 可以在不同的设备(例如svg, pdf, ps,打印机和屏幕)上显示,看起来相同。

Qt提供了 QPicture::load() 和 QPicture::save() 函数以及用于加载和保存图片的流操作符。

6. 自定义绘制后端

对新的后端的支持可以通过从QPaintDevice类派生并重新实现虚拟的 QPaintDevice::paintEngine() 函数来告诉 QPainter 应该使用哪个绘制引擎在这个特定的设备上绘制。

要真正能够在设备上绘制,这个绘制引擎必须是通过派生QPaintDevice 类创建的自定义绘制引擎。

三、绘图与填充

1. Drawing

QPainter提供了高度优化的函数来完成大多数GUI程序所需的绘图。它可以绘制任何东西,从简单的图形基元(由QPoint、QLine、QRect、QRegion和QPolygon类表示)到复杂的形状,如矢量路径。在Qt矢量路径由QPainterPath类表示。QPainterPath为绘制操作提供了一个容器,使图形形状能够被构建和重用。

在这里插入图片描述

1. QPainterPath
QPainterPath 是由直线和曲线组成的对象。例如,矩形由直线组成,椭圆由曲线组成。

与普通的绘制操作相比,painter paths的主要优点是复杂的形状只需要创建一次;然后只需调用QPainter::drawPath()函数就可以多次绘制它们。

QPainterPath对象可用于填充、轮廓和裁剪。要为给定的painter路径生成可填充的轮廓,使用QPainterPathStroker类。

线和轮廓使用QPen类绘制。一支笔是由它的样式(即它的线条类型)、宽度、笔刷、端点的绘制方式(cap-style)以及两条连接的线之间的连接方式(join-style)来定义的。钢笔的笔刷是一个QBrush对象,用于填充钢笔生成的笔触,即QBrush类定义了填充模式。

QPainter还可以绘制对齐的文本和像素地图。

绘制文本时,字体使用 QFont 类指定。Qt 将使用指定属性的字体,如果不存在匹配的字体,Qt将使用安装的最接近的字体。实际使用的字体属性可以使用 QFontInfo 类取得。此外,QFontMetrics 类提供字体测量,QFontDatabase 类提供有关底层窗口系统中可用字体的信息。

通常,QPainter在一个“自然”坐标系中绘制,但它能够使用 QTransform 类执行 视图 和 世界 坐标系之间的转换。有关更多信息,请参见坐标系统,它也描述了渲染过程,即逻辑表示和渲染像素之间的关系,以及反锯齿绘制的好处。

2. 反锯齿的绘图
绘制时,像素渲染由 QPainter::Antialiasing 渲染提示控制。枚举 QPainter::RenderHint 用于指定 QPainter 的标志,这些标志可能被任何给定的引擎使用,也可能不被任何给定的引擎使用。

QPainter::Antialiasing 值表示如果可能的话,引擎应该消除图元的边缘,即通过使用不同的颜色强度平滑边缘。

在这里插入图片描述

2. 填充 Filling

使用QBrush类填充形状。画笔是由它的颜色和样式(即它的填充模式)定义的。

Qt中的任何颜色都由QColor类表示,该类支持RGB、HSV和CMYK颜色模型。QColor还支持alpha混合轮廓和填充(指定透明效果),并且该类与平台和设备无关(使用QColormap类将颜色映射到硬件)。
在这里插入图片描述

可用的填充图案由Qt::BrushStyle枚举描述。这些包括基本模式,从统一的颜色到非常稀疏的模式,各种线条组合,梯度填充和纹理。Qt提供了QGradient类来定义自定义的渐变填充,而使用QPixmap类来指定纹理模式。

1. QGradient
QGradient类与QBrush类结合使用来指定梯度填充。
在这里插入图片描述

Qt 目前支持三种类型的渐变填充:线性渐变在起点和终点之间插入颜色,径向渐变在焦点和圆周上的终点之间插入颜色,圆锥渐变在中心点周围插入颜色。

四、坐标系统

坐标系统由QPainter类控制。与QPaintDevice和QPaintEngine类一起,QPainter构成了Qt绘画系统的基础。QPainter用于执行绘制操作,QPaintDevice是一个二维空间的抽象,可以使用QPainter在其上进行绘制,QPaintEngine提供了 QPainter 用于在不同类型设备上绘制的界面。

QPaintDevice 类是可绘制对象的基类:它的绘制功能由QWidget、QImage、QPixmap、QPicture和QOpenGLPaintDevice类继承。绘制设备的默认坐标系统起源于左上角。x值向右增大,y值向下增大。在基于像素的设备上,默认单位是一个像素,在打印机上是一个点(1/72英寸)。

逻辑QPainter坐标到物理QPaintDevice坐标的映射是由QPainter的转换矩阵、视口和 “窗口” 处理的。逻辑坐标系统和物理坐标系统默认重合。QPainter还支持坐标变换(例如旋转和缩放)。

1. 渲染

1. 逻辑表示
图形基元的大小(宽度和高度)总是对应于它的数学模型,而忽略渲染时使用的笔的宽度:
在这里插入图片描述

2. 非反锯齿绘画
绘制时,像素渲染由QPainter::Antialiasing渲染参数控制。

RenderHint枚举用于指定QPainter的标志,任何给定的引擎都可能使用这些标志,也可能不使用。QPainter::Antialiasing值表示如果可能的话,引擎应该消除图元的边缘,即通过使用不同的颜色强度平滑边缘。

但默认情况下,painter是带锯齿渲染的的,并且适用其他规则:当使用单像素宽的笔渲染时,像素将被渲染到数学定义的点的右侧和下方。例如:

在这里插入图片描述

当使用偶数像素的笔进行渲染时,像素将围绕数学定义的点进行对称渲染,而使用奇数像素的笔进行渲染时,空闲像素将被渲染到数学点的右侧和下方,就像 1 像素的情况一样。具体的例子请参见下面的QRectF图。

在这里插入图片描述

请注意,由于历史原因,QRect::right()和QRect::bottom()函数的返回值偏离了矩形的真正右下角。

QRect的right()函数返回left() + width() - 1,而 bottom()函数返回 top() + height() - 1。上图中的绿色点显示了这些函数的返回坐标。

我们建议你直接使用QRectF: QRectF类使用浮点坐标在平面中定义一个矩形来保证精度(QRect使用整数坐标),而QRectF::right()和QRectF::bottom()函数则返回真正的右下角。

或者,使用QRect,应用x() + width()和y() + height()来找到右下角,避免使用right()和bottom()函数。

3. 反锯齿的绘画
如果你设置了QPainter的反锯齿渲染提示,像素将在数学定义点的两侧对称渲染:
在这里插入图片描述
4. 转换

默认情况下,QPainter在关联设备自己的坐标系统上操作,但它也完全支持仿射坐标变换。
在这里插入图片描述

我们可以使用QPainter::scale()函数按给定的偏移量缩放坐标系统,我们可以使用QPainter::rotate()函数顺时针旋转它,并且可以使用QPainter::translate()函数平移它(即向点添加给定的偏移量)。

你也可以使用QPainter::shear()函数围绕原点旋转坐标系统。所有的转换操作都是在QPainter的转换矩阵上进行的,你可以使用QPainter::worldTransform()函数来获取这个矩阵。矩阵将平面上的一个点变换为另一个点。

如果你需要反复使用相同的变换,你也可以使用 QTransform 对象以及 QPainter::worldTransform() 和 QPainter::setWorldTransform() 函数。你可以在任何时候通过调用 QPainter::save() 函数来保存 QPainter 的转换矩阵,该函数将矩阵保存在内部堆栈上。QPainter::restore() 函数弹出它。

在各种绘图设备上重用相同的绘图代码时,经常需要转换矩阵。如果没有变换,结果将与绘制设备的分辨率紧密绑定。打印机的分辨率很高,例如每英寸600点,而屏幕的分辨率通常在每英寸72到100点之间。

Analog Clock示例展示了如何使用QPainter的转换矩阵绘制自定义控件的内容。
我们建议在进一步阅读之前编译并运行此示例。特别是,尝试将窗口大小调整为不同的大小。

在这里插入图片描述

  void AnalogClockWindow::render(QPainter *p){static const QPoint hourHand[3] = {QPoint(7, 8),QPoint(-7, 8),QPoint(0, -40)};static const QPoint minuteHand[3] = {QPoint(7, 8),QPoint(-7, 8),QPoint(0, -70)};QColor hourColor(127, 0, 127);QColor minuteColor(0, 127, 127, 191);p->setRenderHint(QPainter::Antialiasing);p->translate(width() / 2, height() / 2);int side = qMin(width(), height());p->scale(side / 200.0, side / 200.0);

我们转换坐标系统,使点(0,0)位于控件的中心,而不是位于左上角。我们还按边/ 100缩放系统,边是控件的宽度或高度,以最短的为准。我们希望时钟是方的,即使设备不是方的。

这将给我们一个200 × 200的正方形区域,原点(0,0)在中心,我们可以在上面绘图。我们绘制的内容将显示在适合控件的最大可能的正方形中。

另请参见窗口-视口转换部分。

      QTime time = QTime::currentTime();p->save();p->rotate(30.0 * ((time.hour() + time.minute() / 60.0)));p->drawConvexPolygon(hourHand, 3);p->restore();

我们通过旋转坐标系并调用QPainter::drawConvexPolygon()来绘制时钟的时针。由于旋转,它被画在了正确的方向上。
多边形被指定为一个交替的x, y值数组,存储在hourHand静态变量中(在函数开始处定义),它对应于四个点(2,0),(0,2),(- 2,0)和(0,-25)。

对代码周围的 QPainter::save() 和 QPainter::restore() 的调用保证了后面的代码不会受到我们使用的转换的干扰。

      p->save();p->rotate(6.0 * (time.minute() + time.second() / 60.0));p->drawConvexPolygon(minuteHand, 3);p->restore();

我们对时钟的分针也是这样做的,分针由四个点 (1,0)、(0,1)、(- 1,0) 和 (0,-40) 定义。这些坐标指定了一个比分针更细更长的指针。

      p->setPen(minuteColor);for (int j = 0; j < 60; ++j) {if ((j % 5) != 0)p->drawLine(92, 0, 96, 0);p->rotate(6.0);}

最后,我们绘制时钟面,它由12条30度间隔的短线组成。

Window-Viewport转换

当使用QPainter绘图时,我们使用逻辑坐标指定点,然后将其转换为绘制设备的物理坐标。

逻辑坐标到物理坐标的映射是由QPainter的世界变换 worldTransform() (在变换部分描述)和 QPainter 的 viewport() 和 window() 处理的。视口表示指定任意矩形的物理坐标。“窗口”在逻辑坐标中描述相同的矩形。默认情况下,逻辑和物理坐标系统是重合的,相当于绘制设备的矩形。

使用窗口-视口转换,我们可以使逻辑坐标系统符合我们的偏好。所述还可用于使所述绘图代码独立于所述QPaintDevice 。例如,你可以通过调用QPainter::setwinwindow()函数,使逻辑坐标从(-50,-50)扩展到(50,50),中间是(0,0):

  QPainter painter(this);painter.setWindow(QRect(-50, -50, 100, 100));

现在,逻辑坐标(-50,-50)对应于绘制设备的物理坐标(0,0)。独立于绘制设备,我们的绘制代码将始终对指定的逻辑坐标进行操作。相当于我们可以手动的设置这种坐标关系。自己定义这种坐标的方便关系。

通过设置“窗口”或视口矩形,可以执行坐标的线性变换。请注意,“窗口”的每个角落都映射到viewport的相应角落,反之亦然。出于这个原因,让视口和“窗口”保持相同的宽高比以防止变形通常是一个好主意:

  int side = qMin(width(), height())int x = (width() - side / 2);int y = (height() - side / 2);painter.setViewport(x, y, side, side);

如果我们将逻辑坐标系统设置为正方形,我们也应该使用QPainter::setViewport()函数将视口设置为正方形。在上面的例子中,我们将其设置为适合绘制设备矩形的最大正方形。通过在设置窗口或视口时考虑绘制设备的大小,可以保持绘制代码独立于绘制设备。

请注意,窗口-视口转换只是一个线性转换,即它不执行裁剪。这意味着如果你在当前设置的“窗口”之外绘制,你的绘画仍然会使用相同的线性代数方法转换到视口。

在这里插入图片描述

视口、“窗口” 和 变换矩阵 决定了逻辑QPainter坐标如何映射到绘制设备的物理坐标。默认情况下,世界变换矩阵是单位矩阵,“窗口”和视口设置等同于绘制设备的设置,即世界、“窗口”和设备坐标系是等效的,但正如我们所看到的,系统可以使用转换操作和窗口-视口转换来操纵。

五、读写图像文件

读取图像最常见的方法是通过QImage和QPixmap的构造函数,或者调用QImage::load()和QPixmap::load()函数。此外,Qt提供了QImageReader类,它提供了对进程的更多控制。根据图像格式的底层支持,类提供的函数可以节省内存并加快图像加载速度。

同样,Qt提供了QImageWriter类,它支持在存储图像之前设置特定格式的选项,如伽马值、压缩级别和质量。如果我们不需要这些选项,我们可以使用QImage::save()或QPixmap::save()代替。

在这里插入图片描述

1. QMovie

QMovie是一个用于显示动画的方便类,在内部使用QImageReader类。创建后,QMovie类为运行和控制给定动画提供了各种函数。

QImageReader和QImageWriter类依赖于QImageIOHandler类,QImageIOHandler类是Qt中所有图像格式的通用图像I/O接口,QImageReader和QImageWriter内部使用QImageIOHandler对象来为Qt添加对不同图像格式的支持。
QImageReader::supportedImageFormats()和QImageWriter::supportedImageFormats()函数提供了支持的文件格式列表。Qt默认支持几种文件格式,此外还可以通过插件添加新格式。目前支持的格式在QImageReader和QImageWriter类文档中列出。
Qt的插件机制也可以用来编写自定义图像格式处理程序。这是通过从QImageIOHandler类派生,并创建一个QImageIOPlugin对象来完成的,该对象是创建QImageIOHandler对象的工厂。当插件安装后,QImageReader和QImageWriter会自动加载插件并开始使用它。

六、绘图相关设备

Paint 相关功能
QBitmap单色(1位深度)像素图
QBrush定义由QPainter绘制的形状的填充模式
QColor基于RGB、HSV或CMYK值的颜色
QColorSpace色彩空间抽象
QColorTransform颜色空间之间的转换
QColormap将独立于设备的QColors映射到依赖于设备的像素值
QConicalGradient与QBrush组合使用指定一个锥形梯度刷
QFont指定用于绘制文本的字体查询
QFontMetrics字体度量信息
QFontMetricsF字体度量信息
QGenericMatrix表示N列M行NxM变换矩阵的模板类
QGradient与QBrush组合使用来指定梯度填充
QIcon可伸缩的图标在不同的模式和状态
QIconEngineQIcon渲染器的抽象基类
QImage独立于硬件的图像表示,允许直接访问像素数据,并可以用作绘制设备
QImageReader格式独立接口,用于从文件或其他设备读取图像
QImageWriter格式独立接口,用于将图像写入文件或其他设备
QLine使用整数精度的二维向量
QLineF二维向量使用浮点精度
QLinearGradient与QBrush组合使用来指定一个线性梯度刷
QMargins定义矩形的四个边距
QMarginsF定义矩形的四个边距
QPagedPaintDevice表示支持多个页面的绘制设备
QPaintDevice可以用QPainter绘制的对象的基类
QPaintEngineQPainter如何在给定平台上绘制到给定设备的抽象定义
QPainter在部件和其他绘制设备上执行低级绘制
QPainterPath用于绘制操作的容器,使图形能够被构建和重用
QPainterPathStroker用于为给定的绘制路径生成可填充的轮廓
QPdfWriter类以生成可用作绘图设备的pdf
QPen定义一个QPainter应该如何绘制线条和形状的轮廓
QPixmap可以用作绘画设备的屏幕外图像表示
QPoint使用整数精度定义平面中的一个点
QPointF在平面中使用浮点精度定义一个点
QPolygon使用整数精度的点向量
QPolygonF使用浮点精度的点向量
QRadialGradient使用组合与QBrush指定一个径向梯度刷
QRect使用整数精度在平面内定义一个矩形
QRectF在平面中使用浮点精度定义一个矩形
QRegion指定绘制器的剪辑区域
QRgba64Struct包含64位RGB颜色
QSize使用整数点精度定义二维对象的大小
QSizeF使用浮点精度定义二维对象的大小
QStylePainter用于在窗口组件中绘制QStyle元素的便利类
QSupportedWritingSystems在使用内部Qt fontdatabase注册字体时使用
QSvgGenerator用于创建SVG绘图的绘图设备
QSvgRenderer用于将SVG文件的内容绘制到绘图设备上
QSvgWidget用于显示可伸缩矢量图形(SVG)文件内容的控件
QTransform指定坐标系统的2D变换
QVector2D表示二维空间中的向量或顶点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/38081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】P2 SELECT 与 SQL注释

SELECT 检索单个列检索多个列检索所有列不重复的结果 DISTINCT限制结果 LIMIT 与 OFFSET注释行内注释多行注释 检索单个列 从 Products 表中检索一个名为 prod_name 的列&#xff1b; SELECT prod_name FROM Products;【1】返回的数据可能是无序的&#xff0c;除非规定了顺序…

7.5.tensorRT高级(2)-RAII接口模式下的生产者消费者多batch实现

目录 前言1. RAII接口模式封装生产者消费者2. 问答环节总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-RAI…

原生JS手写扫雷小游戏

场景 实现一个完整的扫雷游戏需要一些复杂的逻辑和界面交互。我将为你提供一个简化版的扫雷游戏示例&#xff0c;帮助你入门。请注意&#xff0c;这只是一个基本示例&#xff0c;你可以根据自己的需求进行扩展和改进。 思路 创建游戏板&#xff08;Grid&#xff09;&#xff1…

软考:中级软件设计师:文件管理,索引文件结构,树型文件结构,位示图,数据传输方式,微内核

软考&#xff1a;中级软件设计师: 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &#xff08;1…

小森动画回忆录(二)-浏览哆啦a梦的四次元口袋

// DoraemonProps结构用于存储单个道具信息 struct DoraemonProps{// 道具名称string name;// 道具用途string UseOfProps; };// 从文件加载哆啦A梦道具信息到vector void LoadDoraemonProps(vector<DoraemonProps>& DoraemonProps) {// 创建文件输入流ifstream str…

人脸识别技术应用安全管理规定(试行)

近年来&#xff0c;人脸识别技术不断成熟&#xff0c;已大量应用于治安管理、金融支付、门禁考勤等诸多领域&#xff0c;极大便捷了公众生活。然而&#xff0c;人脸识别技术在得到广泛应用的同时&#xff0c;仍存在一些不规范现象。人脸识别因其技术特点&#xff0c;涉及公众敏…

node.js 基础高并发案例

什么是高并发 高并发是指系统在同一时间段内需要处理大量的并发请求或同时进行大量的操作。在计算机领域中&#xff0c;高并发通常指的是在短时间内有大量的用户或客户端同时访问系统或进行操作&#xff0c;对系统的并发处理能力提出了较高的要求。 高并发的特点包括 大量的…

Python学习笔记第五十五天(Pandas CSV文件)

Python学习笔记第五十五天 Pandas CSV 文件read_csv()to_string()to_csv() 数据处理head()tail()fillna() info() 后记 Pandas CSV 文件 CSV&#xff08;Comma-Separated Values&#xff0c;逗号分隔值&#xff0c;有时也称为字符分隔值&#xff0c;因为分隔字符也可以不是逗号…

【嵌入式学习笔记】嵌入式入门7——IIC总线协议

1.IIC简介 IIC即Inter Integrated Circuit&#xff0c;集成电路总线&#xff0c;是一种同步&#xff0c;串行&#xff0c;半双工通信总线。 IIC总线协议——总线就是传输数据通道&#xff0c;协议就是传输数据的规则&#xff0c;有以下特点&#xff1a; 由时钟线SCL和数据线S…

ES踩坑记录之集群间通信异常造成节点无法加入

问题描述 公司新搭了一套ES集群&#xff0c;4台机器&#xff0c;ES版本7.5.0&#xff0c;前期搭建十分顺利&#xff0c;但集群运行一段时间后会出现问题。问题具体体现为节点间通讯异常&#xff0c;集群会重新选主&#xff0c;但选主之后只能通过新的主节点进行集群操作&#…

【Linux】可重入函数 volatile关键字 以及SIGCHLD信号

可重入函数 volatile关键字 以及SIGCHLD信号 一、可重入函数1、引入2、可重入函数的判断 二、volatile关键字1、引入2、关于编译器的优化的简单讨论 三、SIGCHLD信号 一、可重入函数 1、引入 我们来先看一个例子来帮助我们理解什么是可重入函数&#xff1a; 假设我们现在要对…

EthGlobal 巴黎站 Chainlink 获奖项目介绍

在 Web3 中&#xff0c;每一周都至关重要。项目的发布、版本的发布以及协议的更新以惊人的速度推出。开发者必须保持学习&#xff0c;随时了解最新的工具&#xff0c;并将所有他们所学的东西&#xff08;无论是旧的还是新的&#xff09;联系起来&#xff0c;以构建推动 Web3 技…

PLUS操作流程、应用与实践,多源不同分辨率数据的处理、ArcGIS的应用、PLUS模型的应用、InVEST模型的应用

PLUS模型是由中国地质大学&#xff08;武汉&#xff09;地理与信息工程学院高性能空间计算智能实验室开发&#xff0c;是一个基于栅格数据的可用于斑块尺度土地利用/土地覆盖(LULC)变化模拟的元胞自动机(CA)模型。PLUS模型集成了基于土地扩张分析的规则挖掘方法和基于多类型随机…

Word转PDF在线转换如何操作?分享转换技巧

现如今&#xff0c;pdf转换器已成为大家日常办公学习必不可少的工具&#xff0c;市场上的pdf转换器主要有两种类型&#xff0c;一种是需要下载安装的&#xff0c;另一种是网页版&#xff0c;打开就可以使用的&#xff0c;今天小编给大家推荐一个非常好用的网页版pdf转换器&…

基于jvm-sandbox的imock开发指南

基于jvm-sandbox的imock开发指南 团队今年的指标是为公司提供一个方法级的mock平台&#xff0c; 这个重要的任务落在了我的身上。 0、明确团队的需求 支持java后端服务方法级别的mock&#xff0c;对没有测试环境的第三方服务进行mock&#xff0c;增加团队覆盖率。 启用&#x…

PDF换行的难度,谁能解决?

换行的时候确认不了长度&#xff1a; import java.awt.*;public class Test {public static void main(String[] args) {String str1 "淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘淘";String str2 "AAAAAAAAAAAAAAAAAAAAAAAAA…

实验篇——亚细胞定位

实验篇——亚细胞定位 文章目录 前言一、亚细胞定位的在线网站1. UniProt2. WoLFPSORT3. BUSCA4. TargetP-2.0 二、代码实现1. 基于UniProt&#xff08;不会&#xff09;2. 基于WoLFPSORT后续&#xff08;已完善&#xff0c;有关代码放置于[python爬虫学习&#xff08;一&#…

一零七零、Redis基础稳固篇

Redis是什么&#xff0c;优缺点&#xff1f; Redis本质是一个K-V类型的内存数据库 纯内存操作&#xff0c;每秒可处理超过10w的读写操作 优点&#xff1a; 读写性能极高 非阻塞IO 单线程 支持持久化 支持事务 数据结构丰富 缺点&#xff1a; 容易受到物理内存的限制 主机宕机可…

【JAVA】日志

输出语句日志输出位置只能是控制台可以将日志信息写入文件或数据库中取消日志需要修改代码&#xff0c;灵活性差只需修改日志文件多线程性能较差性能较好 日志规范接口&#xff1a;Commons Logging(JCL)、Simple Logging Facade for Java(slf4j) 日志实现框架&#xff1a;Log…

软件测试简历撰写与优化,让你面试邀约率暴增99%!

如何撰写一份优秀的简历呢&#xff1f;&#xff1f;这是一个求职者都会遇到的问题&#xff0c;今天就来详细带大家写一份软件测试工程师职位的简历&#xff01;希望能给各位软件测试求职者一个带来帮助&#xff01; 个人简历是求职者给招聘单位发的一份简要介绍。包含自己的基本…