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.hqwc.cn/news/73991.html

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

相关文章

生成国密SM2密钥对

在线生成国密密钥对 生成的密钥对要妥善保管&#xff0c;丢失是无法找回的。

Windows小记

一、域控制器升级的先决条件验证失败。 新建域时&#xff0c;本地 Administrator 帐户将成为域 Administrator 帐户。无法新建域&#xff0c;因为本地 Administrator 帐户密码不符合要求。 目前&#xff0c;本地 Administrator 帐户不需要密码。我们建议你使用网络用户命令行工…

linux 查看文件被那个进程所调用

使用lsof 命令 显示文件被哪个进程所占用 lsof /var/log/messagesCOMMAND&#xff1a;进程的名称PID&#xff1a;进程标识符USER&#xff1a;进程所有者FD&#xff1a;文件描述符&#xff0c;应用程序通过文件描述符识别该文件。如cwd、txt等TYPE&#xff1a;文件类型&#…

Linux 基础命令

文件系统 Linux文件系统结构与Windows有些不同。Linux在文件系统的基础上没有物理驱动器&#xff08;例如C&#xff1a;驱动器&#xff09;&#xff0c; 而是使用逻辑文件系统。在文件系统结构的最顶层是/&#xff0c;它通常被称为文件系统的根&#xff0c;就好像它是一个倒置 …

网络综合布线实训室建设方案

一、网络综合布线系统概述 网络综合布线系统是为了满足数据通信需求而设计和建立的一套基础设施。它提供了数据传输、信号传输和电力供应的基础结构&#xff0c;支持各种网络设备和终端设备之间的连接。 网络综合布线系统通常包括以下组成部分&#xff1a; 1&#xff09; 数据…

2023.8.8巨人网络数据开发工程师面试复盘

1 概述 问题一览 总体感觉良好&#xff0c;通过面试官的介绍可知这个岗位偏向离线数仓。 1.自我介绍 2.询问了其中一段实习经历 3.讲下你说用过的Linux命令 4.讲下HIVE的内部表和外部表有什么不同 *5.讲下你使用过的Hive函数&#xff08;好好在复习下多准备几个吧&#xff09…

JS的解析与Js2Py使用

JS的解析与Js2Py使用 JS的解析事件监听器搜索关键字请求关联JS文件 Js2PyJs2Py的简单使用安装Js2Py执行JavaScript代码调用JavaScript函数 Js2Py的应用示例创建JavaScript文件使用JavaScript JS的解析 在一个网站中&#xff0c;登录密码通常是会进行加密操作的&#xff0c;那么…

H3C交换机如何配置本地端口镜像并在PC上使用Wireshake抓包

环境: H3C S6520-26Q-SI version 7.1.070, Release 6326 Win 10 专业版 Wireshake Version 4.0.3 问题描述: H3C交换机如何配置本地端口镜像并在PC上使用Wireshake抓包 解决方案: 配置交换机本地端口镜像 1.进入系统视图,并创建本地镜像组1 <H3C>system-vie…

C++ 面向对象三大特性——继承

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;C 继承 ☂️<3>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<4>前言&#xff1a;面向对象三大特性的&#xff0c;封装&#xff0c;继承&#xff0c;多态&#xff…

MongoDB升级经历(4.0.23至5.0.19)

MongoDB从4.0.23至5.0.19升级经历 引子&#xff1a;为了解决MongoDB的两个漏洞决定把MongoDB升级至最新版本&#xff0c;期间也踩了不少坑&#xff0c;在这里分享出来供大家学习与避坑~ 1、MongoDB的两个漏洞 漏洞1&#xff1a;MongoDB Server 安全漏洞(CVE-2021-20330) 漏洞2…

Unity用NPOI创建Exect表,保存数据,和修改删除数据。以及打包后的坑——无法打开新创建的Exect表

先说坑花了一下午才找到解决方法解决&#xff0c; 在Unity编辑模式下点击物体创建对应的表&#xff0c;获取物体名字与在InputText填写的注释数据。然后保存。创建Exect表可以打开&#xff0c;打包PC后&#xff0c;点击物体创建的表&#xff0c;打不开文件破损 解决方法&#…

在 ubuntu 18.04 上使用源码升级 OpenSSH_7.6p1到 OpenSSH_9.3p1

1、检查系统已安装的当前 SSH 版本 使用命令 ssh -V 查看当前 ssh 版本&#xff0c;输出如下&#xff1a; OpenSSH_7.6p1 Ubuntu-4ubuntu0.7, OpenSSL 1.0.2n 7 Dec 20172、安装依赖&#xff0c;依次执行以下命令 sudo apt update sudo apt install build-essential zlib1g…