前端图像处理(三)
目录
一、大文件分片
二、图片添加防篡改水印
2.1、主图+水印图(vue2)
2.2、主图+文字(vue3)
一、大文件分片
并行传输:多个数据块可以同时并行传输,利用多线程或多路复用技术提高传输效率;
减少延迟:通过将大文件分割成小块,可以减少单次传输的数据量,从而减少延迟;
以文件上传为例:
根据文件总大小将它分为N组线程,分割后按照下标排序整理,通过Promise.all拿到所有分组数据
//==========================1、index.js=====================
import { cutFile } from "./cutFile.js";
const inpFile = document.querySelector('input[type="file"]');
inpFile.onchange = async (e) => {const file = e.target.files[0];const chunks=await cutFile(file);console.log(chunks,'所有分块的数据');
};
//=======================2、cutFile.js============================
const CHUNK_SIZE = 1024 * 1024 * 5; //5MB
// hardwareConcurrency: 返回当前设备的逻辑处理器数量(即 CPU 核心数)
const THREAD_COUNT = navigator.hardwareConcurrency || 4; //最低4个线程
export function cutFile(file) {return new Promise((resolve) => {const chunkCount = Math.ceil(file.size / CHUNK_SIZE); // 分块的数量const threadChunkCount = Math.ceil(chunkCount / THREAD_COUNT); // 总共分为几组线程const result = new Array(chunkCount); // 初始化结果数组let finishCount = 0;for (let i = 0; i < THREAD_COUNT; i++) {// 创建一个线程,并分配任务const worker = new Worker("./worker.js", {type: "module",});let end = (i + 1) * threadChunkCount;const start = i * threadChunkCount;if (end > chunkCount) {end = chunkCount;}worker.postMessage({file,CHUNK_SIZE,startChunkIndex: start,endChunkIndex: end,});worker.onmessage = (e) => {// result.push(...e.data) 为啥不直接push ?进程完成时间不确定,会导致顺序错乱// 将结果放入 result 数组的正确位置:按照下标依次放入for (let j = start; j < end; j++) {result[j] = e.data[j - start];}worker.terminate();finishCount++;if (finishCount === THREAD_COUNT) {// 所有线程结束后解决 Promiseresolve(result);}};}});
}
//======================3、worker.js========================
import { creatChunk } from "./creatChunk.js";
onmessage = async (e) => {const {file,CHUNK_SIZE,startChunkIndex: start,endChunkIndex: end,} = e.data;const proms = [];for (let i = start; i < end; i++) {proms.push(creatChunk(file, i, CHUNK_SIZE));}const chunks = await Promise.all(proms);postMessage(chunks); // 发送所有分块的数据
};
//======================4、creatChunk.js========================
//SparkMD5 是一个用于计算 MD5 哈希值的库,它可以处理大文件而不会冻结浏览器界面
// import SparkMD5 from "./sparkmd5.js";
export function creatChunk(file, index, chunkSize) {return new Promise((resolve) => {const start = index + chunkSize;const end = start + chunkSize;//计算当前块的起始和结束索引// const spark = new SparkMD5.ArrayBuffer();//创建了一个新的 SparkMD5 实例const fileReader = new FileReader();//FileReader 对象用于读取文件内容const blob = file.slice(start, end);//从原始文件中切出当前块的 Blob 对象fileReader.onload = (e) => {// spark.append(e.target.result);resolve({start,end,index,// hash: spark.end(),blob,data: e.target.result,});};fileReader.readAsArrayBuffer(blob);//开始读取文件块的内容,并将结果作为 ArrayBuffer});
}
二、图片添加防篡改水印
2.1、主图+水印图(vue2)
addWatermarkToImage(baseImageUrl, watermarkUrl, callback) {fetch(baseImageUrl).then((response) => response.blob()).then((blob) => {const baseImage = new Image()baseImage.onload = () => {const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')canvas.width = baseImage.widthcanvas.height = baseImage.heightctx.drawImage(baseImage, 0, 0, baseImage.width, baseImage.height)fetch(watermarkUrl).then((response) => response.blob()).then((watermarkBlob) => {const watermark = new Image()watermark.onload = () => {// 计算水印的位置(中间)const x = (baseImage.width - watermark.width) / 2const y = (baseImage.height - watermark.height) / 2// 绘制水印图片ctx.globalAlpha = 0.2 // 设置水印透明度ctx.drawImage(watermark,x,y,watermark.width,watermark.height)canvas.toBlob(callback, 'image/png') // 将带水印的图片转换为 Blob 对象}watermark.src = URL.createObjectURL(watermarkBlob)})}baseImage.src = URL.createObjectURL(blob)})},
//==========================================添加水印================================
addMark(){this.addWatermarkToImage(this.img_url,this.waterMarkImg,(watermarkedImageUrl) => {const url = URL.createObjectURL(watermarkedImageUrl)console.log(watermarkedImageUrl, '结果',url)})
}
2.2、主图+文字(vue3)
index.vue页面:
<template><div class="container"><waterMark text="版权所有" style="background: #FF9900"><div class="content"></div></waterMark><waterMark text="禁止转载" style="background: #28c840"><div class="content"></div></waterMark></div>
</template>
<script setup lang="ts">
import waterMark from './watermark.vue'
</script>
<style lang="scss" scoped>
.container {width: 100%;height: 100%;display: flex;
}
</style>
watermark.vue组件:
<template><div ref="parentRef" class="watermark-container"><slot></slot></div>
</template>
<script setup>
import { onMounted, ref, defineProps, onUnmounted } from 'vue'
import useWaterMarkBg from './useWaterMarkBg.js'
const parentRef = ref()
const props = defineProps({text: {type: String,require: true,default: 'watermark',},fontSize: {type: Number,default: 40,},gap: {type: Number,default: 20,},
})
const bg = useWaterMarkBg(props)
let div
// 重置水印
function resetWatermark() {if (!parentRef.value) {return}if (div) {div.remove()}const { base64, size } = bg.valueconsole.log('Generated watermark:', base64) // 查看 base64 是否有效div = document.createElement('div')div.style.position = 'absolute'div.style.backgroundImage = `url(${base64})`div.style.backgroundSize = `${size}px ${size}px`div.style.backgroundRepeat = 'repeat'div.style.zIndex = 999div.style.inset = 0parentRef.value.appendChild(div) //这样是为了防止从浏览器修改
}
const ob = new MutationObserver((entries) => {for (const entry of entries) {// 删除for (const dom of entry.removedNodes) {if (dom === div) {resetWatermark()//如果有人在浏览器删除这个盒子,此时立即重新画一次return}}// 修改属性if (entry.target === div) {resetWatermark()//如果有人在浏览器修改盒子属性,此时立即重新画一次return}}
})
onMounted(() => {resetWatermark()ob.observe(parentRef.value, {childList: true,//观察子节点的变化(添加、删除节点)subtree: true,//观察整个子树(不仅仅是直接子节点,所有后代节点attributes: true,//观察属性的变化(例如 div 的属性发生变化时)})
})
onUnmounted(() => {ob.disconnect()
})
</script>
<style lang="scss" scoped>
.watermark-container {width: 400px;height: 400px;position: relative;z-index: 1; /* 确保水印不会覆盖其他内容 */margin-right: 20px;
}
</style>
其中:
MutationObserver 用于监听 DOM 树的变化
使用 ob.observe() 开始监听父容器(parentRef.value)上的变化
useWaterMarkBg.js代码:
import { computed } from 'vue';
export default function useWaterMarkBg(props) {return computed(() => {const canvas = document.createElement('canvas');const devicePixelRatio = window.devicePixelRatio || 1;const fontSize = props.fontSize * devicePixelRatio;const font = `${fontSize}px serif`;const ctx = canvas.getContext('2d');ctx.font = font;const { width } = ctx.measureText(props.text);const canvasSize = Math.max(100, width) + props.gap * devicePixelRatio;canvas.width = canvasSize;canvas.height = canvasSize;ctx.translate(canvas.width / 2, canvas.height / 2);ctx.rotate((Math.PI / 180) * -45);ctx.fillStyle = 'rgba(0,0,0,0.3)';ctx.font = font;ctx.textAlign = 'center';ctx.textBaseline = 'middle';ctx.fillText(props.text, 0, 0);return {base64: canvas.toDataURL(),size: canvasSize / devicePixelRatio,};});
}
相关文章:
前端图像处理(三)
目录 一、大文件分片 二、图片添加防篡改水印 2.1、主图水印图(vue2) 2.2、主图文字(vue3) 一、大文件分片 并行传输:多个数据块可以同时并行传输,利用多线程或多路复用技术提高传输效率;减…...
JAVA设计模式,动态代理模式
动态代理(Dynamic Proxy)是Java中一种非常有用的设计模式。它允许在运行时创建一个实现了一组给定接口的新类。这种模式主要用于当需要为某个对象提供一个代理以控制对该对象的访问时。通过这种方式,可以添加额外的功能,如事务管理…...
谈论 PHP与XSS
本文将讨论一些脚本攻击问题,以及如何解决XSS脚本攻击问题 美好的周末就用来学点知识吧!!! ———————————————————————————————————— 文章目录 XSS跨站脚本攻击XSS是什么XSS类型:反…...
基于Java Springboot武汉市公交路线查询APP且微信小程序
一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 微信…...
106.【C语言】数据结构之二叉树的三种递归遍历方式
目录 1.知识回顾 2.分析二叉树的三种遍历方式 1.总览 2.前序遍历 3.中序遍历 4.后序遍历 5.层序遍历 3.代码实现 1.准备工作 2.前序遍历函数PreOrder 测试结果 3.中序遍历函数InOrder 测试结果 4.后序遍历函数PostOrder 测试结果 4.底层分析 1.知识回顾 在99.…...
解决WebView写入localstorage但首次加载取不到值的问题
本文是解决Android写localstorage的问题。 在android中,native经常需要和h5页面进行交互,比如将本地token写入h5,然后h5中的js获取token进行api请求。 写入localstorage的方法很标准,即在webview的onPageFinished中注入并调用一…...
CTF-PWN glibc源码阅读[1]: 寻找libc中堆结构的定义(2.31-0ubuntu9.16)
源代码在这里下载 来到malloc/malloc.c 在980行发现这段代码 // 定义最大 mmap 值为 -4 #define M_MMAP_MAX -4// 如果没有定义 DEFAULT_MMAP_MAX,则将其定义为 65536 #ifndef DEFAULT_MMAP_MAX #define DEFAULT_MMAP_MAX (65536) #endif// 引…...
Node.js 实战: 爬取百度新闻并序列化 - 完整教程
很多时候我们需要爬取一些公开的网页内容来做一些数据分析和统计。而多数时候,大家会用到python ,因为实现起来很方便。但是其实Node.js 用来爬取网络内容,也是非常强大的。 今天我向大家介绍一下我自己写的一个百度新闻的爬虫,可…...
C++知识整理day3类与对象(下)——赋值运算符重载、取地址重载、列表初始化、友元、匿名对象、static
文章目录 1.赋值运算符重载1.1 运算符重载1.2 赋值运算符重载 2.取地址重载2.1 const成员函数2.2 取地址运算符重载 3.类与对象的补充3.1 再探构造函数---初始化列表3.2 类型转换3.3 static成员3.4 友元3.5 内部类3.6 匿名对象3.7 对象拷贝时的编译器优化 1.赋值运算符重载 赋…...
【计算机网络】实验6:IPV4地址的构造超网及IP数据报
实验 6:IPV4地址的构造超网及IP数据报 一、 实验目的 加深对IPV4地址的构造超网(无分类编制)的了解。 加深对IP数据包的发送和转发流程的了解。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、了解IPV4地址的构造超网…...
【服务器问题】xshell 登录远程服务器卡住( 而 vscode 直接登录不上)
打开 xshell ssh 登录远程服务器:卡在下面这里,迟迟不继续 当 SSH 连接卡在 Connection established. 之后,但没有显示远程终端提示符时,这通常意味着连接已经成功建立,说明不是网络连接和服务器连接问题,…...
node.js基础学习-querystring模块-查询字符串处理(三)
一、前言 querystring是 Node.js 中的一个内置模块,主要用于处理 URL 查询字符串。它提供了一些实用的方法来解析和格式化查询字符串,使得在处理 HTTP 请求中的查询参数等场景时非常方便。 还可以防止sql注入 二、解析查询字符串(parse方法&a…...
【C++】深入优化计算题目分析与实现
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯第一题:圆的计算我的代码实现代码分析改进建议改进代码 老师的代码实现代码分析可以改进的地方改进代码 💯第二题:对齐输出我的代码实现…...
【一起学习三维GIS】Cesium基础功能和项目讲解
一、Cesium整体介绍 Cesium正式发布于 2014 年,是一个完全开源的基于 WebGL 的 JavaScript框架,无需安装插件即可创建具有最佳性能、精度、视觉质量和易用性的世界级三维地球影像和地图,并且具有丰富的开源社区内容。 Cesium 作为一个较为…...
【docker】Overlay网络
什么是 Overlay 网络? Overlay 网络是一种 Docker 网络驱动,允许容器在不同主机间通信。 它依赖分布式存储(如 Swarm、Etcd 或 Consul)来管理网络配置和路由。 Overlay 网络的核心特点 跨主机通信:容器可以跨物理主…...
澎峰科技助力中国移动 重磅发布智算“芯合”算力原生基础软件栈2.0
11月30日 ,由中国通信学会主办、中国移动研究院承办的2024中国信息通信大会“算力网络算网一体创新发展论坛 ”在成都召开。中国移动研究院携手澎峰科技等产业合作伙伴在本次论坛重磅发布了智算“芯合”算力原生基础软件栈2.0。 芯片是智算生态的基石,基…...
电脑提示报错“Directx error”怎么解决?是什么原因导致的?游戏软件提示“Directx error”错误的解决方案
DirectX Error(DX错误)通常指的是在使用基于DirectX技术的应用程序(尤其是游戏)时遇到的问题。这个问题可能由多种因素导致,以下是一些可能的原因及相应的解决方案: 可能的原因 DirectX版本不匹配&#x…...
jmeter 压测常用静默参数解释应用
简介: JMeter静默压测(即无界面压测)是一种常用的性能测试方法,用于模拟多个用户同时访问系统并测量系统的响应时间和吞吐量等关键性能指标。在JMeter静默压测中,常用的压测参数及其解释如下: 一、基本…...
动态规划-----路径问题
动态规划-----路径问题 下降最小路径和1:状态表示2:状态转移方程3 初始化4 填表顺序5 返回值6 代码实现 总结: 下降最小路径和 1:状态表示 假设:用dp[i][j]表示:到达[i,j]的最小路径 2:状态转…...
LeetCode 438.找到字符串中所有字母异位词
LeetCode 438.找到字符串中所有字母异位词 思路🧐: 需要找到子串异位词,也就是只看该子串是否有相同字母而不管位置是否相同。分析题目发现只需要单调向前找异位词,则可以使用滑动窗口求解,注意这里每当左右边框长度大…...
[C++设计模式] 为什么需要设计模式?
文章目录 什么是设计模式?为什么需要设计模式?GOF 设计模式再次理解面向对象软件设计固有的复杂性软件设计复杂性的根本原因如何解决复杂性?分解抽象 结构化 VS 面向对象(封装)结构化设计代码示例:面向对象设计代码示例࿱…...
【ArkTS】使用AVRecorder录制音频 --内附录音机开发详细代码
系列文章目录 【ArkTS】关于ForEach的第三个参数键值 【ArkTS】“一篇带你读懂ForEach和LazyForEach” 【小白拓展】 【ArkTS】“一篇带你掌握TaskPool与Worker两种多线程并发方案” 【ArkTS】 一篇带你掌握“语音转文字技术” --内附详细代码 【ArkTS】技能提高–“用户授权”…...
【知识科普】设计模式之-责任链模式
这里写自定义目录标题 概述责任链模式的详细描述责任链模式的使用场景 使用场景举例1. 审批流程示例:2. 过滤器链示例:3. 事件处理系统示例:4. 插件系统示例: Java代码示例及注释代码解释 概述 责任链模式的详细描述 责任链模式…...
浏览器渲染原理
渲染原理 第一步解析Html第二步样式计算第三步布局第四步分层第五步绘制第六步分块第七步光栅化第八步画常见面试题什么是回流reflow?什么是重绘repaint? 当浏览器的网络线程收到HTML文档之后,会产生一个渲染任务并且会将其传递给渲染主线程的…...
顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Maltab)
顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Maltab) 目录 顶刊算法 | 鱼鹰算法OOA-BiTCN-BiGRU-Attention多输入单输出回归预测(Maltab)效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实…...
【机器学习】分类任务: 二分类与多分类
二分类与多分类:概念与区别 二分类和多分类是分类任务的两种类型,区分的核心在于目标变量(label)的类别数: 二分类:目标变量 y 只有两个类别,通常记为 y∈{0,1} 或 y∈{−1,1}。 示例ÿ…...
速盾:高防 CDN 可以配置客户端请求超时配置?
在高防 CDN(Content Delivery Network,内容分发网络)的运行管理中,客户端请求超时配置是一项重要的功能设定,它对于优化网络资源分配、保障服务质量以及维护系统稳定性有着关键意义。 一、客户端请求超时配置的概念 …...
字节青训Marscode——8:找出整形数组中超过一半的数
问题描述 小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。 测试样例 样例1: 输入:array [1, 3, 8, 2, 3, 1, 3, 3, 3] 输出…...
Fastapi + vue3 自动化测试平台---移动端App自动化篇
概述 好久写文章了,专注于新框架,新UI界面的实践,废话不多说,开搞 技术架构 后端: Fastapi Airtest multiprocessing 前端: 基于 Vue3、Vite、TypeScript、Pinia、Pinia持久化插件、Unocss 和 Elemen…...
go并发设计模式runner模式
go并发设计模式runner模式 真正运行的程序不可能是单线程运行的,go语言中最值得骄傲的就是CSP模型了,可以说go语言是CSP模型的实现。 假设现在有一个程序需要实现,这个程序有以下要求: 程序可以在分配的时间内完成工作࿰…...
[TPAMI 2024]Vision-Language Models for Vision Tasks: A Survey
论文网址:Vision-Language Models for Vision Tasks: A Survey | IEEE Journals & Magazine | IEEE Xplore 论文Github页面:GitHub - jingyi0000/VLM_survey: Collection of AWESOME vision-language models for vision tasks 英文是纯手打的&…...
Qt—QLineEdit 使用总结
文章参考:Qt—QLineEdit 使用总结 一、简述 QLineEdit是一个单行文本编辑控件。 使用者可以通过很多函数,输入和编辑单行文本,比如撤销、恢复、剪切、粘贴以及拖放等。 通过改变 QLineEdit 的 echoMode() ,可以设置其属性,比如以密码的形式输入。 文本的长度可以由 m…...
Flutter 之 InheritedWidget
InheritedWidget 是 Flutter 框架中的一个重要类,用于在 Widget 树中共享数据。它是 Flutter 中数据传递和状态管理的基础之一。通过 InheritedWidget,你可以让子 Widget 在不需要显式传递数据的情况下,访问祖先 Widget 中的数据。这种机制对…...
#JAVA-常用API-爬虫
1.爬虫 我们在正则表达式的讲解中可以使用字符串的方法materchs()来匹配,并且返回一个boolean值 String name "lshhhljh"; System.out.println(name.matches("lsh{3}\\s{3}")); //true现在我们将利用正则表达式来爬取本地或者网站上的文本内…...
Qt Serial Bus 前置介绍篇
文章目录 Qt Serial Bus 简介前言 什么是 Qt Serial Bus?Qt Serial Bus 的核心功能支持的协议1. **CAN 总线**2. **Modbus**3. **自定义协议** 应用场景优势总结 Qt Serial Bus 简介 前言 Qt Serial Bus 是 Qt 框架中的一个模块,用于与工业设备和嵌入式…...
JavaScript(一)
1.JavaScript 基本使用 2.JavaScript简单事件 3.JavaScript修改样式 4.JavaScript数据类型 JavaScript和Java有什么关系 知识点一 JavaScript基本使用 JS写在哪 还有一种写在中间的,也就是<head>里面 JS一些注意事项 JS修改元素内容 #JS获取对象<…...
Python实现网站资源批量下载【可转成exe程序运行】
Python实现网站资源批量下载【可转成exe程序运行】 背景介绍解决方案转为exe可执行程序简单点说详细了解下 声明 背景介绍 发现 宣讲家网 的PPT很好,作为学习资料使用很有价值,所以想下载网站的PPT课件到本地,但是由于网站限制,一…...
el-upload上传多个文件,一次请求,Django接收
1、:file-list"fileList" :on-change"handleChange" 将文件赋值到fileList 2、 :auto-upload"false" 手动触发上传 写个按钮点击执行这个 this.$refs.upload.submit(); 3、自己写上传,不会再触发上传成功或失败回调 4、 request.FI…...
【错误记录】jupyter notebook打开后服务器错误Forbidden问题
如题,在Anaconda Prompt里输入jupyter notebook后可以打开浏览器,但打开具体项目后就会显示“服务器错误:Forbidden”,终端出现: tornado.web.HTTPError: HTTP 403: Forbidden 查看jupyter-server和jupyter notebook版…...
修改MVCActiveRecord支持匿名函数(用于动态决定数据库连接)
要修改 TMVCActiveRecordMiddleware 以直接接受一个匿名函数(用于动态决定数据库连接)以及一个配置文件名,你需要对构造函数进行一些调整。这可以通过重载构造函数以接收另一个参数——匿名函数来实现。 构造函数修改步骤 假设你的目标是允…...
SpringMVC(一)
ModelAndView ModelAndView 是 Spring MVC 框架中的一个类,用于在控制器中返回模型数据和视图信息。 模型: 包含应用程序的数据,这些数据将被传递到视图层进行渲染。模型数据通常以键值对的形式存储在一个 map 中。 视图: 指定要渲…...
nginx配置笔记
前言 nginx官方文档: https://nginx.org/en/docs/openresty官方文档: https://github.com/openresty/lua-nginx-module一、配置 1. 配置实例 1.1. 80端口转443 server {listen 80 default_server;listen [::]:80 default_server;rewrite ^ https://$http_host$request_uri?…...
解决idea使用maven打包时无法将本地lib库文件和resource目录中的资源文件打包进jar文件的问题!!!
一、问题复现 1)项目结构如下 我们看到项目中手动添加了本地lib资源,同时bootspring的配置文件和mapper文件也放在了resouces目录中。 2)上述结构的项目在使用maven打包时,最终生成的jar文件中将不包含lib库文件,甚…...
html button 按钮单选且 高亮
<DIV class"middle"> <div class"containerTarget"> <span class"hover-target1" οnclick"btn(1);">韵达 </span> <span class"hover-target2" οnclick"btn(2);">中通 </span…...
GitLab使用中遇到的一些问题-记录
错误内容一 Warning: Permanently added gitlab.com (ED25519) to the list of known hosts. gitgitlab.com: Permission denied (publickey). Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. …...
【合作原创】使用Termux搭建可以使用的生产力环境(二)
前言 上期文章没看的可以先从上期文章开始看起 【合作原创】使用Termux搭建可以使用的生产力环境(一)-CSDN博客 目前我们已经完成了FinalShell ssh连接手机Termux的功能了,这期我们继续朝我们的目标前进。今天早上有读者进群以为生成环境指…...
UG NX二次开发(C#)-选择对象居中(不是全部居中)
文章目录 1、前言2、什么是对象居中3、功能实现代码3.1 对象居中3.1 恢复原视图1、前言 在UG NX二次开发过程中,我们经常会用到居中以查看完整的模型,但是对于如果想展示某些对象,而不是全部模型时,那么我们就想将选择的对象(如体对象)居中查看,当查看结束后还能恢复到…...
12.2深度学习_项目实战
十、项目实战 鲍勃开了自己的手机公司。他想与苹果、三星等大公司展开硬仗。 他不知道如何估算自己公司生产的手机的价格。在这个竞争激烈的手机市场,你不能简单地假设事情。为了解决这个问题,他收集了各个公司的手机销售数据。 鲍勃想找出手机的特性(例…...
【Go底层】select原理
目录 1、背景2、go版本3、 selectgo函数解释【1】函数参数解释【2】函数具体解释第一步:遍历pollorder,选出准备好的case第二步:将当前goroutine放到所有case通道中对应的收发队列上第三步:唤醒groutine 4、总结 1、背景 select多…...
QT实战-qt各种菜单样式实现
本文主要介绍了qt普通菜单样式、带选中样式、带子菜单样式、超过一屏幕菜单样式、自定义带有滚动条的菜单样式, 先上图如下: 1.普通菜单样式 代码: m_pmenu new QMenu(this);m_pmenu->setObjectName("quoteListMenu"); qss文…...