.Net平台下OpenGL绘制图形(2)(VS2019,Winform,C#)

news2025/1/21 15:26:31

本节主要讲诉图形绘制的原理,使用介绍和代码演示。

  • 原理介绍

  我们先来讲讲OpenGL的图形绘制。其实,所有的图形都是由许多个小图形连接而成的。你可以理解为是图片的像素,一张彩图是由很多个色彩不一的像素点组合而成。要实现色彩绚丽的图形设计,你需要理解两点成线,三点成面,多面成形的原理。在这里,我们通过简单的程序演示一下点到线,线到面,面到形的过程。

   在此,先介绍一下几个常用的函数和绘制原理。

  1. 坐标原点变换:Translate(float x, float y, float z) ,你也可以理解为是坐标轴变换。默认设定的视角和世界坐标都是在同个原点,打个比方:我们看手机,假设手机是原点,我们视角默认也是原点的话,我们脑壳都得钻手机里面。对吧,我们不这么看手机,基本都是把手机拉远,以一种舒服的角度进行操作,这就是在物品的变换了。所以我们,在绘制图形前最好设定合适的坐标轴位置,同时也需要考虑视点变换的设置值。我们输入图形的坐标仍是按照原点来输入的,不会受到Translate的影响;他影响的只是整体的坐标轴变换,他的值是不需要做改变的。当然了,你也可以直接全部修改图形的坐标值,不过这样就太麻烦了,没必要;直接修改初始化的视角变换值也是可以的。

  2. 绘制点,线,面的方式:以Begin(BeginMode mode)为首开始绘制mode类型的图形,Vertex(float x, float y, float z)为图形顶点,依次连接各个顶点形成图形,以End()结束绘制。理论上来说,只要你给出图形的所有顶点,牛鬼蛇神都给你搞出来,一点问题也没有(除了可能会卡之外)。以画线为例:

  gl.Begin(OpenGL.GL_LINES);
  gl.Vertex(-1.0f, 0.0f, 0.0f);
  gl.Vertex(1.0f, 0.0f, 0.0f);
  gl.End();

  3. 赋予颜色:Color(float red, float green, float blue)

  在每个图形顶点前加上设定颜色,图形的绘制选择就更加多样;同时,不同顶点间采用不同的颜色会产生渐变色差,非常好看。

  • 演示代码

  我们先添加一个坐标系变化,然后。选择绘制一条线,接着绘制一个三角形,最后绘制一个角锥。这就是由点到线,线到面,面到形的过程,所有的图形都是这样组合衔接而来的。

  1.首先,画一条线,颜色设定为白色(背景是黑色)

#region 点到线
            gl.Begin(OpenGL.GL_LINES);
        gl.Color(1.0f, 1.0f, 1.0f);
            gl.Vertex(-2.0f, 0.0f, 0.0f);//左顶点
            gl.Vertex(2.0f, 2.0f, 0.0f);//右顶点
            gl.End();
            #endregion

 2.接着,来画个面,再稍微加点颜色变化#region 线成面(三角形)
             

  gl.Begin(OpenGL.GL_TRIANGLES);//第一个面
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                #endregion

 

3.接着,来画个角锥,第四个点颜色选择白色区分开。角锥也就是由四个面组合而成的,所以我们再加上三个面(注意每个点坐标和对应颜色要相同)

#region 面组合成体
                gl.Begin(OpenGL.GL_TRIANGLES);//第二个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第三个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第四个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                #endregion

 

我们会发现,界面没什么变化。嗯,大伙看看我们的第四个顶点在哪里。坐标(0,0,-2),相对于其他四个点,他的位置是靠里面的。因为我们此时的视角是在正值的。额,对了,还得说说视角的事,视角受到初始化设置的视点变换设置。

  // 设置当前矩阵模式,对投影矩阵应用随后的矩阵操作
  gl.MatrixMode(OpenGL.GL_PROJECTION);

  // 创建透视投影变换
  gl.Perspective(30.0f, (double)Width / (double)Height, 5, 100.0);

  // 视点变换
  gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);

  //此时的视角在这里,可以理解为是坐标点(0,5,0)往空间原点处看

   程序的前端添加了Translate(0.0f, 0.0f, -5.0f) ,相当于把绘制的图形往屏幕内移动。这样会有利于我们查看图形。(Z轴的话法线是垂直屏幕往外的)

  说回正题,第四个顶点是在已经画好的三角形的里面,所以我们看不到,那我们就稍微的旋转一下看看效果,如下图所示。

 附上全部代码,本代码是在“.Net平台下OpenGL绘制图形(1)(VS2019,Winform,C#)“基础上增加的

using SharpGL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SharpGLFormsApp1
{
    public partial class Form1 : Form
    {

        private bool drawLine = false;
        private bool drawArea = false;
        private bool drawVolume = false;
        private bool flagRotateX = false;
        private bool flagRotateY = false;
        private bool flagRotateZ = false;
        private float rotation_X = 0.0f;
        private float rotation_Y = 0.0f;
        private float rotation_Z = 0.0f;





        /// <summary>
        /// 默认绘画模式为线条
        /// </summary>
        private uint _model = OpenGL.GL_LINE_LOOP;

        /// <summary>
        /// X轴坐标
        /// </summary>
        private float _x = 0;

        /// <summary>
        /// Y轴坐标
        /// </summary>
        private float _y = 0;

        /// <summary>
        /// Z轴坐标
        /// </summary>
        private float _z = 0;


        public Form1()
        {
            InitializeComponent();

        }

        /// <summary>
        /// 复位事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            _x = _y = _z = 0;
            tbX.Value = tbY.Value = tbZ.Value = Convert.ToInt32(_x);
            label1.Text = "X轴" ;
            label2.Text = "Y轴";
            label3.Text = "Z轴";
        }

        /// <summary>
        /// 线条选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbline_CheckedChanged(object sender, EventArgs e)
        {
            _model = OpenGL.GL_LINE_LOOP;
        }

        /// <summary>
        /// 球面事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbfull_CheckedChanged(object sender, EventArgs e)
        {
            _model = OpenGL.GL_QUADS;
        }

        /// <summary>
        /// 控件绘图事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void openGLControl1_GDIDraw(object sender, RenderEventArgs args)
        {
            // 创建一个GL对象
            OpenGL gl = this.openGLControl1.OpenGL;

            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);	// 清空屏幕
            gl.LoadIdentity();					// 重置
            gl.Translate(0.0f, 0.0f, -6.0f);	// 设置坐标,距离屏幕距离为6

            gl.Rotate(_x, 1.0f, 0.0f, 0.0f);	// 绕X轴旋转
            gl.Rotate(_y, 0.0f, 1.0f, 0.0f);	// 绕Y轴旋转
            gl.Rotate(_z, 0.0f, 0.0f, 1.0f);	// 绕Z轴旋转

            gl.Begin(_model);				    // 绘制立方体
            gl.Color(0.0f, 1.0f, 0.0f);			// 设置颜色
            //绘制其中一个面
            gl.Vertex(1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);

            //如下类同
            gl.Color(1.0f, 0.5f, 0.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);

            gl.Color(1.0f, 0.0f, 0.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);

            gl.Color(1.0f, 1.0f, 0.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(1.0f, 1.0f, -1.0f);

            gl.Color(0.0f, 0.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, 1.0f);
            gl.Vertex(-1.0f, 1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, -1.0f);
            gl.Vertex(-1.0f, -1.0f, 1.0f);

            gl.Color(1.0f, 0.0f, 1.0f);
            gl.Vertex(1.0f, 1.0f, -1.0f);
            gl.Vertex(1.0f, 1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, 1.0f);
            gl.Vertex(1.0f, -1.0f, -1.0f);
            gl.End();						// 结束绘制
        }

        /// <summary>
        /// X轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbX_Scroll(object sender, EventArgs e)
        {
            int x = tbX.Value;
            _x = x;
            label1.Text = "X:" + x;
        }

        /// <summary>
        /// Y轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbY_Scroll(object sender, EventArgs e)
        {
            int y = tbY.Value;
            _y = y;
            label2.Text = "Y:" + y;
        }
        /// <summary>
        ///Z轴拖动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbZ_Scroll(object sender, EventArgs e)
        {
            int z = tbZ.Value;
            _z = z;
            label3.Text = "Z:" + z;
        }

        private void openGLControl2_GDIDraw(object sender, RenderEventArgs args)
        {
            SharpGL.OpenGL gl = this.openGLControl2.OpenGL;
            //清除深度缓存 
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

            //重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();

            //坐标轴变换位置到(0.0f, 0.0f, -5.0f),这样我们的坐标轴就相当于往屏幕内走5个单位
            gl.Translate(0.0f, 0.0f, -5.0f);

            if (flagRotateX)
            {
                rotation_X += 1f;
                gl.Rotate(rotation_X, 1.0f, 0.0f, 0.0f);//rotationX:角度
            }
            if (flagRotateY)
            {
                rotation_Y += 1f;
                gl.Rotate(rotation_Y, 0.0f, 1.0f, 0.0f);//rotationY:角度
            }
            if (flagRotateZ)
            {
                rotation_Z += 1f;
                gl.Rotate(rotation_Z, 0.0f, 0.0f, 1.0f);//rotationZ:角度
            }

            if (drawLine)
            {
                #region 点到线
                gl.Begin(OpenGL.GL_LINES);
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(-2.0f, -1.0f, 0.0f);//左顶点
                gl.Vertex(2.0f, 2.0f, 0.0f);//右顶点
                gl.End();
                #endregion
            }
            if (drawArea)
            {
                #region 线成面(三角形)
                gl.Begin(OpenGL.GL_TRIANGLES);//第一个面
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                #endregion
            }
            if (drawVolume)
            {
                #region 面组合成体
                gl.Begin(OpenGL.GL_TRIANGLES);//第二个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第三个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 1.0f, 0.0f);
                gl.Vertex(-1.0f, -1.0f, 0.0f);//左顶点 
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                gl.Begin(OpenGL.GL_TRIANGLES);//第四个面
                gl.Color(1.0f, 1.0f, 1.0f);
                gl.Vertex(0.0f, 0.0f, -2.0f);//第四个点
                gl.Color(0.0f, 0.0f, 1.0f);
                gl.Vertex(1.0f, -1.0f, 0.0f);//右顶点
                gl.Color(1.0f, 0.0f, 0.0f);
                gl.Vertex(0.0f, 1f, 0.0f);//顶点
                gl.End();
                #endregion
            }

            gl.Flush();   //强制刷新
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            OpenGL g2 = openGLControl2.OpenGL;
            g2.ClearColor(0, 0, 0, 0);
        }

        private void openGLControl2_Resize(object sender, EventArgs e)
        {
            OpenGL gl = openGLControl2.OpenGL;

            // 设置当前矩阵模式,对投影矩阵应用随后的矩阵操作
            gl.MatrixMode(OpenGL.GL_PROJECTION);

            // 重置当前指定的矩阵为单位矩阵,将当前的用户坐标系的原点移到了屏幕中心
            gl.LoadIdentity();

            // 创建透视投影变换
            gl.Perspective(30.0f, (double)Width / (double)Height, 5, 100.0);

            // 视点变换
            gl.LookAt(0, 5, 0, 0, 0, 0, 0, 1, 0);

            // 设置当前矩阵为模型视图矩阵
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
        }

        private void ckline_CheckedChanged(object sender, EventArgs e)
        {
            drawLine = this.ckline.Checked;
        }

        private void ckarea_CheckedChanged(object sender, EventArgs e)
        {
            drawArea = this.ckarea.Checked;
        }
 

        private void ckvol_CheckedChanged(object sender, EventArgs e)
        {
            drawVolume = this.ckvol.Checked;
        }

        private void ckx_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateX = this.ckx.Checked;
        }

        private void cky_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateY = this.cky.Checked;
        }

        private void ckz_CheckedChanged(object sender, EventArgs e)
        {
            flagRotateZ = this.ckz.Checked;
        }
    }
}

效果:

 

 

 

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

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

相关文章

安装旧版本chrome 浏览器方法

1、下载 国内推荐下载网址&#xff1a;https://www.slimjet.com/chrome/google-chrome-old-version.php 我自己目前再用的103.0.5060.53版本&#xff0c;也可以到我网盘下载[若失效可联系我更新]。 2、安装之前&#xff0c;请先卸载干净当前版本 打开控制面板&#xff0c;找打…

挣值管理专题

挣值管理 基本思路 该方法的基本思想是应用统计学的原理&#xff0c;通过引进一个中间变量即“挣值”来帮助项目管理者分析项目成本的变动情况&#xff0c;并给出项目成本与工期相关变化的信息及对项目成本发展趋势作出预测与决策。 挣值的定义 挣值是一个表示项目“已完成作业…

Linux多路复用机制原理分析--select/poll

前言 Linux访问设备的IO模型主要有五种&#xff0c;分别是非阻塞IO模型、阻塞IO模型、IO多路复用模型、信号驱动模型以及异步IO模型。本文主要分析IO多路复用模型&#xff0c;Linux下的IO多路复用模型主要有select/poll/epoll等机制实现。 IO多路复用模型可以实现以非阻塞的方…

Dijkstra算法图解,C++实现Dijkstra算法

目录 Dijkstra算法简介数据结构抽象初始化开始计算第一轮计算第二轮计算第三轮计算第四轮计算算法总结 C实现Dijkstra算法 Dijkstra算法简介 Dijkstra算法计算是从一个顶点到其余各顶点的最短路径算法&#xff0c;解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起…

1929-2022年全球气象站点的逐日平均能见度

气象数据是我们在各项研究中都非常常用的数据&#xff0c;之前我们分享过全球范围的1929-2022年的具体到气象站点的逐日气象数据&#xff0c;包括平均气温、最高气温、最低气温、平均风速&#xff08;可查看之前的文章获取&#xff09;。 本次我们带来的是全球范围的1929-2022…

单链表的成环问题

前言&#xff1a;链表成环问题不仅考察双指针的用法&#xff0c;该问题还需要一定的数学推理和分析能力&#xff0c;看似简单的题目实则细思缜密&#xff0c;值得斟酌~ 目录 1.问题背景引入-判断链表是否成环&#xff1a; 1.1.正解&#xff1a;快慢指针 1.2 STL的集合判重 …

kubespray部署k8s 1.26集群安装指南

Kubespray 是一个自由开源的工具&#xff0c;它提供了 Ansible 剧本(playbook) 来部署和管理 Kubernetes 集群。它旨在简化跨多个节点的 Kubernetes 集群的安装过程&#xff0c;允许用户快速轻松地部署和管理生产就绪的 Kubernetes 集群。 它支持一系列操作系统&#xff0c;包…

Spring的第十五阶段:Spring的事务管理(02)

1、自定义设置回滚异常 rollbackFor和rollbackForClassName回滚的异常 /*** Transactional 表示使用通知( 启用事务 ) <br/>* rollbackFor 属性可以自定义哪些异常可以回滚事务 <br/>* rollbackForClassName 属性可以自定义哪些全类名的异常回滚事务 <br/>…

Java实现八大排序

&#x1f495;“汲取知识&#xff0c;分享快乐&#xff0c;让生命不留遗憾”&#x1f495; &#x1f386;作者&#xff1a;不能再留遗憾了&#x1f386; &#x1f43c;专栏&#xff1a;Java学习&#x1f43c; &#x1f3c0;该文章主要内容&#xff1a;直接插入排序、希尔排序、…

VMware安装Ubuntu系统

VMware安装Ubuntu系统 1.首先选择文件&#xff0c;点击新建虚拟机 2.选择自定义&#xff0c;点击下一步 3.点击下一步 4.选择稍后安装操作系统&#xff0c;点击下一步 5.选择Linus操作系统&#xff0c;版本选择Ubuntu64位&#xff0c;点击下一位 6.自己看图 7. 这里根据自…

「2023 最新」 Github、Gitlab Git 工作流「常用」 git 命令、规范以及操作总结 Rebase

Git commit 规范 关于提交信息的格式&#xff0c;可以遵循以下的规则&#xff1a; feat: 新特性&#xff0c;添加功能fix: 修改 bugrefactor: 代码重构docs: 文档修改style: 代码格式修改test: 测试用例修改chore: 其他修改, 比如构建流程, 依赖管理 Git 基础知识 当我们通过…

ThinkPHP6,视图的安装及模板渲染和变量赋值 view::fetch() ,view::assgin() ,助手函数

ThinkPHP6&#xff0c;视图的安装及模板渲染和变量赋值 tp6视图功能由\think\View类配合视图驱动&#xff08;也即模板引擎驱动&#xff09;类一起完成&#xff0c;新版仅内置了PHP原生模板引擎&#xff08;主要用于内置的异常页面输出&#xff09;&#xff0c;如果需要使用其…

mysql数据库的数据类型 -- 4

目录 数据类型 4.1&#xff1a;数据类型的分类 4.2&#xff1a;数值类型 4.3&#xff1a;字符类型 4.5&#xff1a;enum和set类型 数据类型 4.1&#xff1a;数据类型的分类 数值类型 描述 TINYINT [UNSIGNED]整数&#xff0c;占用1字节SMALLINT [UNSIGNED] 整数&#xf…

springboot+vue滴答拍摄影项目(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的滴答拍摄影项目。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌…

JAVA程序员不得不知道的String类

文章目录 目录 文章目录 前言 String类的重要性: 一.String类简介 二.String底层源码剖析 三.字符串构造 三.字符串的比较 四.String类常用方法 1.字符串查找 2.字符串转化 2.1 大小写转换 2.2 数组转字符串 2.3数值和字符串转化 2.4 格式化 ​编辑 3 字符串替换 ​…

【19】SCI易中期刊推荐——计算机 | 人工智能领域(中科院2区)

💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…

实验四 Spark Streaming

实验四 Spark Streaming 1.实验目的 1. 熟悉编写 Spark Streaming 程序处理流数据的方法。 2.实验内容 1. 实时统计贷款金额 模拟解决贷款金额的实时统计问题。假设某外企客户贷款金额数据如下&#xff08;json 格式&#xff09;&#xff0c; 第一项是客户名称&#xff08;…

[Data structure]双链表 | 一文带你了解线性数据结构之一的双链表

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;数据结构 双链表 1、简介2、常见操作3、时间复杂度4、代码实现思路总览5、Node6、DoubleLinkedList6.1、添加节点…

设计模式——对象创建模式之工厂模式

文章目录 前言一、“单一职责” 模式二、Factory Method 工厂方法1、动机2、模式定义3、伪代码示例4、结构 总结 前言 一、“单一职责” 模式 通过“对象创建”模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&…

Linux系统之dstat命令的基本使用

Linux系统之dstat命令的基本使用 一、dstat命令介绍1. dstat简介2. dstat特点 二、本次实践介绍1. 本地环境规划2. 本次实践介绍 三、本地环境检查1. 检查操作系统版本2. 查看系统内核版本3. 检查本地yum仓库源状态 三、安装dstat工具1. 搜索dstat软件2. 安装dstat工具3. 查看d…