当前位置: 首页 > news >正文

View->裁剪框View的绘制,手势处理

XML文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="@color/black"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><com.yang.app.MyRootViewandroid:id="@+id/my_root"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:orientation="vertical"android:layout_marginLeft="60dp"android:layout_marginTop="60dp"android:layout_marginRight="60dp"android:layout_marginBottom="60dp"></com.yang.app.MyRootView></LinearLayout><com.yang.app.MyCropViewandroid:id="@+id/my_crop"android:layout_width="match_parent"android:layout_height="match_parent"/>
</RelativeLayout>

Activity代码

const val TAG = "Yang"
class MainActivity : AppCompatActivity() {var tempBitmap: Bitmap? = nullvar mRootView: MyRootView? = nullvar mCropView: MyCropView? = null@SuppressLint("MissingInflatedId")override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val tempRect = RectF(0f, 0f, resources.displayMetrics.widthPixels.toFloat(), resources.displayMetrics.heightPixels.toFloat())mCropView = findViewById(R.id.my_crop) as? MyCropViewmRootView = findViewById<MyRootView?>(R.id.my_root).apply {mCropView?.let {setRectChangeListener(it)}}CoroutineScope(Dispatchers.IO).launch {tempBitmap = getBitmap(resources, tempRect, R.drawable.real)withContext(Dispatchers.Main) {tempBitmap?.let {// 设置裁剪框的初始位置mCropView?.setOriginBitmapRect(RectF(0f, 0f, it.width.toFloat(), it.height.toFloat()))mRootView?.setOriginBitmap(it)}}}}
}fun getBitmap(resources : Resources, destRect : RectF, imageId: Int): Bitmap? {var imageWidth = -1var imageHeight = -1val preOption = BitmapFactory.Options().apply {// 只获取图片的宽高inJustDecodeBounds = trueBitmapFactory.decodeResource(resources, imageId, this)}imageWidth = preOption.outWidthimageHeight = preOption.outHeight// 计算缩放比例val scaleMatrix = Matrix()// 确定未缩放Bitmap的RectFvar srcRect = RectF(0f, 0f, imageWidth.toFloat(), imageHeight.toFloat())// 通过目标RectF, 确定缩放数值,存储在scaleMatrix中scaleMatrix.setRectToRect(srcRect, destRect, Matrix.ScaleToFit.CENTER)// 缩放数值再映射到原始Bitmap上,得到缩放后的RectFscaleMatrix.mapRect(srcRect)val finalOption = BitmapFactory.Options().apply {if (imageHeight > 0 && imageWidth > 0) {inPreferredConfig = Bitmap.Config.RGB_565inSampleSize = calculateInSampleSize(imageWidth,imageHeight,srcRect.width().toInt(),srcRect.height().toInt())}}return BitmapFactory.decodeResource(resources, imageId, finalOption)
}fun calculateInSampleSize(fromWidth: Int, fromHeight: Int, toWidth: Int, toHeight: Int): Int {var bitmapWidth = fromWidthvar bitmapHeight = fromHeightif (fromWidth > toWidth|| fromHeight > toHeight) {var inSampleSize = 2// 计算最大的inSampleSize值,该值是2的幂,并保持原始宽高大于目标宽高while (bitmapWidth >= toWidth && bitmapHeight >= toHeight) {bitmapWidth /= 2bitmapHeight /= 2inSampleSize *= 2}return inSampleSize}return 1
}fun setRectChangeListener(listener: RectChangedListener) {mRectChangeListener = listener
}fun dpToPx(context: Context, dp: Float): Float {val metrics = context.resources.displayMetricsreturn TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, metrics)
}

自定义View代码

  • 显示图片的View
class MyRootView constructor(context: Context, attrs: AttributeSet? ) : View(context, attrs) {private var lastX = 0fprivate var lastY = 0fprivate val scroller = OverScroller(context)private var tracker: VelocityTracker? = nullprivate var initialLeft = 0private var initialTop = 0private var mDestRect: RectF? = nullprivate val mScaleMatrix = Matrix()private var mRectChangeListener: RectChangedListener? = nullprivate var mPaint = Paint().apply {isAntiAlias = trueisFilterBitmap = true}private var mOriginBitmap: Bitmap? = nulloverride fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {super.onLayout(changed, left, top, right, bottom)if (initialLeft == 0) initialLeft = leftif (initialTop == 0) initialTop = topmDestRect = RectF(0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat())}override fun onTouchEvent(event: MotionEvent): Boolean {when (event.action) {MotionEvent.ACTION_DOWN -> {tracker = VelocityTracker.obtain().apply {addMovement(event)}lastX = event.rawXlastY = event.rawY}MotionEvent.ACTION_MOVE -> {if (tracker == null) {tracker = VelocityTracker.obtain()tracker?.addMovement(event)}val dx = event.rawX - lastXval dy = event.rawY - lastYval left = left + dx.toInt()val top = top + dy.toInt()val right = right + dx.toInt()val bottom = bottom + dy.toInt()layout(left, top, right, bottom)lastX = event.rawXlastY = event.rawY}MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {// 手指抬起时,根据速度进行惯性滑动// (int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY)// startX, startY:开始滑动的位置// velocityX, velocityY:滑动的速度// minX, maxX, minY, maxY:滑动的范围val parentView = (parent as? View)tracker?.computeCurrentVelocity(1000)scroller.fling(initialLeft, initialTop,-tracker?.xVelocity?.toInt()!!, -tracker?.yVelocity?.toInt()!!,0, parentView?.width!! - width,0, parentView?.height!! - height,width, height)tracker?.recycle()tracker = nullinvalidate() // 请求重绘View,这会导致computeScroll()被调用}}return true}override fun computeScroll() {if (scroller.computeScrollOffset()) {// 更新View的位置val left = scroller.currXval top = scroller.currYval right = left + widthval bottom = top + heightlayout(left, top, right, bottom)if (!scroller.isFinished) {invalidate()  // 继续请求重绘View,直到滑动结束}}}fun setOriginBitmap(bitmap: Bitmap) {mOriginBitmap = bitmapinvalidate()}override fun onDraw(canvas: Canvas?) {super.onDraw(canvas)mOriginBitmap?.let {setScaleMatrix(it)canvas?.drawBitmap(it, mScaleMatrix, mPaint)mScaleMatrix.postTranslate(left.toFloat(), top.toFloat())mRectChangeListener?.onRectChanged(mScaleMatrix)}}fun setScaleMatrix(bitmap: Bitmap) {val scaleX = mDestRect?.width()!! / bitmap.widthval scaleY = mDestRect?.height()!! / bitmap.heightval scale = Math.min(scaleX, scaleY)val dx = (mDestRect?.width()!! - bitmap.width!! * scale) / 2val dy = (mDestRect?.height()!! - bitmap.height!! * scale) / 2mScaleMatrix.reset()mScaleMatrix.postScale(scale, scale)mScaleMatrix.postTranslate(dx, dy)}fun setRectChangeListener(listener: RectChangedListener) {mRectChangeListener = listener}
}
  • 裁剪框View
class MyCropView(context: Context, attrs: AttributeSet) : View(context, attrs), RectChangedListener {private val mRectLinePaint = Paint().apply {isAntiAlias = truecolor = Color.WHITEstrokeWidth = dpToPx(context, 1.5f)style = Paint.Style.STROKE}private val mCornerAndCenterLinePaint = Paint().apply {isAntiAlias = truecolor = Color.REDstrokeWidth = dpToPx(context, 3f)style = Paint.Style.STROKE}private val mDividerLinePaint = Paint().apply {isAntiAlias = truecolor = Color.WHITEstrokeWidth = dpToPx(context, 3f) / 2falpha = (0.5 * 255).toInt()style = Paint.Style.STROKE}private val mLineOffset = dpToPx(context, 3f) / 2fprivate val mLineWidth = dpToPx(context, 15f)private val mCenterLineWidth = dpToPx(context, 18f)private val mCoverColor = context.getColor(com.tran.edit.R.color.crop_cover_color)// 处理手势private var downX = 0fprivate var downY = 0fenum class MoveType {LEFT_TOP, RIGHT_TOP, LEFT_BOTTOM, RIGHT_BOTTOM, LEFT, TOP, RIGHT, BOTTOM}private var mMoveType : MoveType?= nullprivate var mOriginBitmapRect = RectF()private var mOriginViewRect = RectF()private var mInitCropMatrix = Matrix()private var mCropMatrix = Matrix()private var mMinCropRect = RectF(0f, 0f, 200f , 200f)private var mActivePointerId = -1override fun onTouchEvent(event: MotionEvent?): Boolean {when (event?.actionMasked) {MotionEvent.ACTION_DOWN -> {// 记录第一根手指的位置和idval pointerIndex = event.actionIndexmActivePointerId = event.getPointerId(pointerIndex)downX = event.getX(pointerIndex)downY = event.getY(pointerIndex)val cropRect = getCropRect()// 计算初始拖动裁剪框的大致方向val leftTopRect = getStartCropCornerRect(cropRect.left, cropRect.top)if (leftTopRect.contains(event.x , event.y)) {mMoveType = MoveType.LEFT_TOPreturn true}val leftBottomRect = getStartCropCornerRect(cropRect.left, cropRect.bottom)if (leftBottomRect.contains(event.x , event.y)) {mMoveType = MoveType.LEFT_BOTTOMreturn true}val rightTopRect = getStartCropCornerRect(cropRect.right, cropRect.top)if (rightTopRect.contains(event.x , event.y)) {mMoveType = MoveType.RIGHT_TOPreturn true}val rightBottomRect = getStartCropCornerRect(cropRect.right, cropRect.bottom)if (rightBottomRect.contains(event.x , event.y)) {mMoveType = MoveType.RIGHT_BOTTOMreturn true}val leftCenterRect = getStartCropCenterRect(cropRect.left, cropRect.left, cropRect.top, cropRect.bottom)if (leftCenterRect.contains(event.x , event.y)) {mMoveType = MoveType.LEFTreturn true}val rightCenterRect = getStartCropCenterRect(cropRect.right, cropRect.right, cropRect.top, cropRect.bottom)if (rightCenterRect.contains(event.x , event.y)) {mMoveType = MoveType.RIGHTreturn true}val topCenterRect = getStartCropCenterRect(cropRect.left, cropRect.right, cropRect.top, cropRect.top)if (topCenterRect.contains(event.x , event.y)) {mMoveType = MoveType.TOPreturn true}val bottomCenterRect = getStartCropCenterRect(cropRect.left, cropRect.right, cropRect.bottom, cropRect.bottom)if (bottomCenterRect.contains(event.x , event.y)) {mMoveType = MoveType.BOTTOMreturn true}return true}MotionEvent.ACTION_POINTER_DOWN->{// 记录第二根手指的位置和idval pointerIndex = event.actionIndexmActivePointerId = event.getPointerId(pointerIndex)downX = event.getX(pointerIndex)downY = event.getY(pointerIndex)}MotionEvent.ACTION_MOVE -> {mMoveType ?: return false// 如果此时屏幕上有两根手指,这个时候mActivePointerId就是第二根手指的id,不支持多指更新位置val pointerIndex = event.findPointerIndex(mActivePointerId)if (pointerIndex < 0 || pointerIndex != 0) {return false}var deltaX = event.getX(pointerIndex) - downXvar deltaY = event.getY(pointerIndex) - downYdownX = event.getX(pointerIndex)downY = event.getY(pointerIndex)val originalRect = getInitCropRect()val startCropRect = getCropRect()val endCropRect = RectF(startCropRect)when (mMoveType) {MoveType.LEFT_TOP -> {endCropRect.left += deltaXendCropRect.top += deltaY}MoveType.LEFT_BOTTOM -> {endCropRect.left += deltaXendCropRect.bottom += deltaY}MoveType.RIGHT_TOP -> {endCropRect.right += deltaXendCropRect.top += deltaY}MoveType.RIGHT_BOTTOM -> {endCropRect.right += deltaXendCropRect.bottom += deltaY}MoveType.LEFT -> {endCropRect.left += deltaX}MoveType.RIGHT -> {endCropRect.right += deltaX}MoveType.TOP -> {endCropRect.top += deltaY}MoveType.BOTTOM -> {endCropRect.bottom += deltaY}else -> {//}}// 限制不超过初始裁剪框的大小endCropRect.left = max(endCropRect.left, originalRect.left)endCropRect.top = max(endCropRect.top, originalRect.top)endCropRect.right = min(endCropRect.right, originalRect.right)endCropRect.bottom = min(endCropRect.bottom, originalRect.bottom)if (endCropRect.width() < mMinCropRect.width() || endCropRect.height() < mMinCropRect.height()) {// 将裁剪框的大小调整到最小范围adjustCropRect(endCropRect, mMinCropRect, originalRect)return true}mCropMatrix.setRectToRect(startCropRect, endCropRect, Matrix.ScaleToFit.FILL)invalidate()mOriginViewRect.set(getCropRect())}MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {// 所有手指抬起,重置状态downX = -1fdownY = -1fmMoveType = nullmActivePointerId = -1}MotionEvent.ACTION_POINTER_UP -> {// 假如屏幕上有两根手指// 按下第二根,抬起第二根,mActivePointerId == pointerId, 活动手指更新为第一根// 按下第二根,抬起第一根,mActivePointerId != pointerId, 活动手指为第二根,不变val pointerIndex = event.actionIndexval pointerId = event.getPointerId(pointerIndex)if (mActivePointerId == pointerId) {// 选择一个新的活动手指val newPointerIndex = if (pointerIndex == 0) 1 else 0mActivePointerId = event.getPointerId(newPointerIndex)downX = event.getX(newPointerIndex)downY = event.getY(newPointerIndex)}}}return true}fun adjustCropRect(rect: RectF, minRect: RectF, maxRect: RectF) {if (rect.width() <= minRect.width()) {// 当前裁剪框的左右边界加上距离最小裁剪框的距离val xOffset = (minRect.width() - rect.width()) / 2rect.left -= xOffsetrect.right += xOffset// 如果左边界小于最小裁剪框的左边界,那么左边界就等于最小裁剪框的左边界if (rect.left < maxRect.left) {rect.offset(maxRect.left - rect.left, 0f)}if (rect.right > maxRect.right) {rect.offset(maxRect.right - rect.right, 0f)}}if (rect.height() <= minRect.height()) {// 当前裁剪框的上下边界加上距离最小裁剪框的距离val yOffset = (minRect.height() - rect.height()) / 2rect.top -= yOffsetrect.bottom += yOffset// 如果上边界小于最小裁剪框的上边界,那么上边界就等于最小裁剪框的上边界if (rect.top < maxRect.top) {rect.offset(0f, maxRect.top - rect.top)}if (rect.bottom > maxRect.bottom) {rect.offset(0f, maxRect.bottom - rect.bottom)}}}fun getStartCropCornerRect(startX : Float, startY : Float): RectF {return RectF(startX - mLineWidth, startY - mLineWidth, startX + mLineWidth, startY + mLineWidth)}fun getStartCropCenterRect(startX : Float, endX : Float, startY : Float, endY : Float): RectF {if (startX == endX){return RectF(startX - mLineWidth, startY, startX + mLineWidth, endY)}else{return RectF(startX, startY - mLineWidth, endX, startY + mLineWidth)}}override fun onRectChanged(changedMatrix: Matrix) {mInitCropMatrix.set(changedMatrix)val initCropRect = RectF(mOriginBitmapRect)mInitCropMatrix.mapRect(initCropRect)mOriginViewRect.set(initCropRect)invalidate()}fun getOriginViewRect(): RectF {return RectF(mOriginViewRect)}fun getInitCropRect(): RectF {val initCropRect = RectF(mOriginBitmapRect)mInitCropMatrix.mapRect(initCropRect)return initCropRect}fun getCropRect(): RectF {val cropRect = getOriginViewRect()mCropMatrix.mapRect(cropRect)mCropMatrix.reset()return cropRect}fun setOriginBitmapRect(rectF: RectF){mOriginBitmapRect = rectF}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)val drawRect = getCropRect()drawRect?.let { rect->// 1. 绘制遮罩canvas.save()canvas.clipOutRect(rect)canvas.drawColor(Color.argb(mCoverColor.alpha, mCoverColor.red, mCoverColor.green, mCoverColor.blue))canvas.restore()// 2. 绘制边框canvas?.drawRect(rect, mRectLinePaint)// 3. 绘制分割线val x1 = rect.left + rect.width() / 3val x2 = rect.left + rect.width() * 2 / 3val y1 = rect.top + rect.height() / 3val y2 = rect.top + rect.height() * 2 / 3canvas.drawLine(x1, rect.top, x1, rect.bottom, mDividerLinePaint)canvas.drawLine(x2, rect.top, x2, rect.bottom, mDividerLinePaint)canvas.drawLine(rect.left, y1, rect.right, y1, mDividerLinePaint)canvas.drawLine(rect.left, y2, rect.right, y2, mDividerLinePaint)// 4. 绘制四个角的折线canvas.drawLine(rect.left - mLineOffset, rect.top - mLineOffset * 2, rect.left - mLineOffset, rect.top + mLineWidth, mCornerAndCenterLinePaint)canvas.drawLine(rect.left - mLineOffset * 2, rect.top - mLineOffset, rect.left + mLineWidth, rect.top - mLineOffset, mCornerAndCenterLinePaint)canvas.drawLine(rect.right + mLineOffset, rect.top - mLineOffset * 2, rect.right + mLineOffset, rect.top + mLineWidth, mCornerAndCenterLinePaint)canvas.drawLine(rect.right + mLineOffset * 2, rect.top - mLineOffset, rect.right - mLineWidth, rect.top - mLineOffset, mCornerAndCenterLinePaint)canvas.drawLine(rect.right + mLineOffset, rect.bottom + mLineOffset * 2, rect.right + mLineOffset, rect.bottom - mLineWidth, mCornerAndCenterLinePaint)canvas.drawLine(rect.right + mLineOffset * 2, rect.bottom + mLineOffset, rect.right - mLineWidth, rect.bottom + mLineOffset, mCornerAndCenterLinePaint)canvas.drawLine(rect.left - mLineOffset, rect.bottom + mLineOffset * 2, rect.left - mLineOffset, rect.bottom - mLineWidth, mCornerAndCenterLinePaint)canvas.drawLine(rect.left - mLineOffset * 2, rect.bottom + mLineOffset, rect.left + mLineWidth, rect.bottom + mLineOffset, mCornerAndCenterLinePaint)// 5. 绘制四条边的中间线canvas.drawLine(rect.left - mLineOffset, rect.centerY() - mCenterLineWidth / 2, rect.left - mLineOffset, rect.centerY() + mCenterLineWidth / 2, mCornerAndCenterLinePaint)canvas.drawLine(rect.right + mLineOffset, rect.centerY() - mCenterLineWidth / 2, rect.right + mLineOffset, rect.centerY() + mCenterLineWidth / 2, mCornerAndCenterLinePaint)canvas.drawLine(rect.centerX() - mCenterLineWidth / 2, rect.top - mLineOffset, rect.centerX() + mCenterLineWidth / 2, rect.top - mLineOffset, mCornerAndCenterLinePaint)canvas.drawLine(rect.centerX() - mCenterLineWidth / 2, rect.bottom + mLineOffset, rect.centerX() + mCenterLineWidth / 2, rect.bottom + mLineOffset, mCornerAndCenterLinePaint)}}
}

效果图

在这里插入图片描述

相关文章:

View->裁剪框View的绘制,手势处理

XML文件 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android…...

语言模型的进化:从NLP到LLM的跨越之旅

在人工智能的浩瀚宇宙中&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是一个充满挑战和机遇的领域。随着技术的发展&#xff0c;我们见证了从传统规则到统计机器学习&#xff0c;再到深度学习和预训练模型的演进。如今&#xff0c;我们站在了大型语言模型&#xff…...

应急响应--网站(web)入侵篡改指南

免责声明:本文... 目录 被入侵常见现象: 首要任务&#xff1a; 分析思路&#xff1a; 演示案例: IIS&.NET-注入-基于时间配合日志分析 Apache&PHP-漏洞-基于漏洞配合日志分析 Tomcat&JSP-弱口令-基于后门配合日志分析 (推荐) Webshell 查杀-常规后门&…...

vue3+vue-router+vite 实现动态路由

文章中出现的代码是演示版本&#xff0c;仅供参考&#xff0c;实际的业务需求会更加复杂 什么是动态路由 什么场景会用到动态路由 举一个最常见的例子&#xff0c;比如说我们要开发一个后台管理系统&#xff0c;一般来说后台管理系统都会分角色登录&#xff0c;这个时候也就涉…...

Okhttp hostnameVerifier详解

hostnameVerifier 方法简介核心原理参考资料 方法简介 本篇博文以Okhttp 4.6.0来解析hostnameVerfier的作用&#xff0c;顾名思义&#xff0c;该方法的主要作用就是鉴定hostnname的合法性。Okhttp在初始化的时候我们可以自己配置hostnameVerfier&#xff1a; new OkHttpClien…...

TCP的p2p网络模式

TCP的p2p网络模式 1、tcp连接的状态有以下11种 CLOSED&#xff1a;关闭状态LISTEN&#xff1a;服务端状态&#xff0c;等待客户端发起连接请求SYN_SENT&#xff1a;客户端已发送同步连接请求&#xff0c;等待服务端相应SYN_RECEIVED&#xff1a;服务器收到客户端的SYN请请求&…...

力扣-贪心算法4

406.根据身高重建队列 406. 根据身高重建队列 题目 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或…...

动手学深度学习6.2 图像卷积-笔记练习(PyTorch)

以下内容为结合李沐老师的课程和教材补充的学习笔记&#xff0c;以及对课后练习的一些思考&#xff0c;自留回顾&#xff0c;也供同学之人交流参考。 本节课程地址&#xff1a;卷积层_哔哩哔哩_bilibili 代码_哔哩哔哩_bilibili 本节教材地址&#xff1a;6.2. 图像卷积 — 动…...

展开说说:Android服务之bindService解析

前面两篇文章我们分别总结了Android四种Service的基本使用以及源码层面总结一下startService的执行过程&#xff0c;本篇继续从源码层面总结bindService的执行过程。 本文依然按着是什么&#xff1f;有什么&#xff1f;怎么用&#xff1f;啥原理&#xff1f;的步骤来分析。 b…...

node-sass 老版本4.14.0 安装失败解决办法

旧项目 npm install 发现 node-sass 安装 失败 切换淘宝镜像之后 不能完全解决问题。因为需要编译&#xff0c;本地没有Python环境不能实现 安装node-sass时&#xff0c;在install阶段会从Github上下载一个叫binding.node的文件&#xff0c;而「GitHub Releases」里的文件…...

最近很火的字幕截图生成器

网址 https://disksing.com/fake-screenshot/ 最近很火的字幕截图生成器&#xff0c;对于自媒体来说真的太实用了 另外透露一下&#xff0c;你仔细研究就会发现&#xff0c;这是个纯前端的项目...

使用RabbitMQ实现可靠的消息传递机制

使用RabbitMQ实现可靠的消息传递机制 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. RabbitMQ简介 RabbitMQ是一个开源的消息代理软件&#xff0c;实现了高级消息队列协议&#xff08;AMQP&…...

Function Call ReACT,Agent应用落地的加速器_qwen的function calling和react有什么不同

探索智能体Agent的未来之路&#xff1a;Function Call与ReACT框架的较量&#xff0c;谁能引领未来&#xff1f; 引言 各大平台出现智能体应用创建&#xff0c;智能体逐渐落地&#xff0c;背后的使用哪种框架&#xff1f; 随着各大平台&#xff0c;例如百度千帆APPbuilder、阿…...

Java的JSONPath(fastjson)使用总结

背景 最近使用json实现复杂业务配置, 因为功能需要解析读取json的中节点数据。如果使用循环或者stream处理&#xff0c;可以实现&#xff0c;但是都过于麻烦。在想能否使用更简单json读取方式&#xff0c;正好发现fastjson支持该功能&#xff0c;本文做一个记录 案例说明 示…...

【大模型】大语言模型:光鲜背后的阴影——事实准确性和推理能力的挑战

大语言模型&#xff1a;光鲜背后的阴影——事实准确性和推理能力的挑战 引言一、概念界定二、事实准确性的局限2.1 训练数据的偏差2.2 知识的时效性问题2.3 复杂概念的理解与表述 三、推理能力的局限3.1 表层理解与深层逻辑的脱节3.2 缺乏常识推理3.3 无法进行长期记忆和连续推…...

Java面向对象练习(1.手机类)(2024.7.4)

手机类 package Phone;public class Phone {private String brand;private int price;private String color;public Phone(){}public Phone(String brand, int price, String color){this.brand brand;this.price price;this.color color;}public void setBrand(String bra…...

智慧生活新篇章,Vatee万腾平台领航前行

在21世纪的科技浪潮中&#xff0c;智慧生活已不再是一个遥远的梦想&#xff0c;而是正逐步成为我们日常生活的现实。从智能家居的温馨便捷&#xff0c;到智慧城市的高效运转&#xff0c;科技的每一次进步都在为我们的生活增添新的色彩。而在这场智慧生活的变革中&#xff0c;Va…...

Spring Cloud Gateway报sun.misc.Unsafe.park(Native Method)

项目引入spring cloud gateway的jar报&#xff0c;启动的时候报&#xff1a; [2024-07-05 10:10:16.162][main][ERROR][org.springframework.boot.web.embedded.tomcat.TomcatStarter][61]:Error starting Tomcat context. Exception: org.springframework.beans.factory.Bean…...

select single , select endselect

select single , select endselect single 根据条件找到一条数据&#xff0c;就出来了。 select endselect是在里面循环&#xff0c;每次找一条&#xff0c;依次放到into table中&#xff0c;或者放到into work area中&#xff0c;下面append table 。 实际开发中不建议这么操…...

后端学习(一)

添加数据库包&#xff1a; 数据库连接时 发生错误&#xff1a; 解决方式&#xff1a; SqlConnection conn new SqlConnection("serverlocalhost;databaseMyBBSDb;uidsa;pwd123456;Encryptfalse;") ;conn.Open();SqlCommand cmd new SqlCommand("SELECT * FROM…...

【活动行】参与上海两场线下活动,教育生态行业赛总决赛活动和WAIC人工智能大会活动 - 上海活动总结

目录 背景决赛最后一公里领域范围 决赛作品AI智教相机辅导老师Copilot辅导老师Copilot雅思写作竞技场 优秀作品总结 背景 决赛 百度发起的千帆杯教育生态行业赛于2024年7月4日进行线下决赛&#xff0c;博主虽然没能进入决赛&#xff0c;但也非常荣幸能够以嘉宾身份到现场给进…...

conda 安装设置

安装anaconda 推荐官网下载和安装,最新版本是anaconda3+python3.11,个人选择。有可能找不到 Index of /anaconda/archive/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror Tips:小白一定要全部勾选,特别第二项“add anaconda3 to my path environment variable…...

用PlantUML和语雀画UML类图

概述 首先阐述一下几个简单概念&#xff1a; UML&#xff1a;是统一建模语言&#xff08;Unified Modeling Language&#xff09;的缩写&#xff0c;它是一种用于软件工程的标准化建模语言&#xff0c;旨在提供一种通用的方式来可视化软件系统的结构、行为和交互。UML由Grady…...

uniapp微信小程序电子签名

先上效果图&#xff0c;不满意可以直接关闭这页签 新建成单独的组件&#xff0c;然后具体功能引入&#xff0c;具体功能点击签名按钮&#xff0c;把当前功能页面用样式隐藏掉&#xff0c;v-show和v-if也行&#xff0c;然后再把这个组件显示出来。 【签名-撤销】原理是之前绘画时…...

MetaPoint_速读

Meta-Point Learning and Refining for Category-Agnostic Pose Estimation https://arxiv.org/abs/2404.14808https://github.com/chenbys/metapointabstract 这篇文章介绍了一种名为Meta-Point Learning and Refining的框架&#xff0c;用于实现类别不可知的姿势估计。该框…...

数据库逆向工程工具reverse_sql

reverse_sql 是一个用于解析和转换 MySQL 二进制日志&#xff08;binlog&#xff09;的工具。它可以将二进制日志文件中记录的数据库更改操作&#xff08;如插入、更新、删除&#xff09;转换为反向的 SQL 语句&#xff0c;以便对系统或人为产生的误操作进行数据回滚和恢复。 *…...

四大内网穿透利器对比

本文精选四款市场上的佼佼者——巴比达、花生壳、Frp及NatApp&#xff0c;详细剖析它们的特点与优势&#xff0c;助力企业和个人用户精准选择&#xff0c;其中特别强调了巴比达在企业级安全访问方面的突出贡献。 1. 巴比达 特点 深度安全防护&#xff1a;巴比达提供全方位安…...

【LeetCode】每日一题:跳跃游戏 II

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - 1] 的最小…...

SpringBoot拦截器

目录 一、拦截器快速入门 &#xff08;1&#xff09;什么是拦截器 &#xff08;2&#xff09;拦截器的使用步骤 1、定义拦截器 &#x1f340;preHandle() 方法 &#x1f340;postHandle() 方法 &#x1f340;afterCompletion() 方法 2、注册配置拦截器 二、拦截器详解…...

uniapp中实现跳转链接到游览器(安卓-h5)

uniapp中实现跳转链接到游览器&#xff08;安卓-h5&#xff09; 项目中需要做到跳转到外部链接&#xff0c;网上找了很多都不是很符合自己的要求&#xff0c;需要编译成app后是跳转到游览器打开链接&#xff0c;编译成web是在新窗口打开链接。实现的代码如下&#xff1a; 效果&…...