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

flutter学习-day16-自定义组件

📚 目录

  1. 介绍
  2. 组合多个组件
  3. 自绘组件
    1. Custompaint
    2. 绘制边界RepaintBoundary
    3. CustomPainter与Canvas
    4. 画笔Paint
    5. 绘制组件例子

本文学习和引用自《Flutter实战·第二版》:作者:杜文

1. 介绍

当Flutter提供的现有组件无法满足我们的需求,或者我们为了共享代码需要封装一些通用组件,这时我们就需要自定义组件。在Flutter中自定义组件有三种方式:通过组合其他组件、自绘和实现RenderObject。

  • 组合多个Widget:通过已有组件来拼装组合成一个新的组件。
  • 通过CustomPaint自绘:通过Flutter中提供的CustomPaint和Canvas来实现UI自绘。
  • 通过RenderObject自绘:RenderObject中最终也是通过Canvas API来绘制的。而CustomPaint只是为了方便开发者封装的一个代理类。

2. 组合多个组件

实现一个渐变色背景,支持圆角,按下有涟漪效果的按钮,并且实现一个带动画的可以旋转的容器,每次点击按钮,容器旋转一点。

import 'package:flutter/material.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {double myTurns = 0.0;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Container(alignment: Alignment.center,child: Column(children: [TurnBox(turns: myTurns,speed: 500,child: const Icon(Icons.refresh,size: 50,)),MyButton(colors: const [Colors.green, Colors.orangeAccent],height: 60.0,width: 300.0,borderRadius: const BorderRadius.all(Radius.circular(8)),onPressed: () {setState(() {myTurns += 0.2;});},child: const Text('放手一搏'),)],),));}
}
/// 自定义按钮
class MyButton extends StatelessWidget {const MyButton({Key? key,this.colors,this.width,this.height,this.onPressed,this.borderRadius,required this.child}): super(key: key);// 渐变色数组final List<Color>? colors;// 按钮属性final double? width;final double? height;final BorderRadius? borderRadius;// 点击回调事件final GestureTapCallback? onPressed;final Widget child;Widget build(BuildContext context) {ThemeData theme = Theme.of(context);List<Color> myColors =colors ?? [theme.primaryColor, theme.primaryColorDark];return DecoratedBox(decoration: BoxDecoration(gradient: LinearGradient(colors: myColors),borderRadius: borderRadius),child: Material(type: MaterialType.transparency,child: InkWell(splashColor: Colors.white70,highlightColor: Colors.transparent,borderRadius: borderRadius ?? BorderRadius.circular(8),onTap: onPressed,child: ConstrainedBox(constraints: BoxConstraints.tightFor(height: height, width: width),child: Center(child: Padding(padding: const EdgeInsets.all(8.0),child: DefaultTextStyle(style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18.0),child: child,),),),),),),);}
}/// 自定义旋转
class TurnBox extends StatefulWidget {const TurnBox({Key? key,this.turns = .0, // 旋转的“圈”数,一圈为360度,如0.25圈即90度this.speed = 200, // 过渡动画执行的总时长required this.child}) :super(key: key);final double turns;final int speed;final Widget child;TurnBoxState createState() => TurnBoxState();
}class TurnBoxState extends State<TurnBox> with SingleTickerProviderStateMixin {AnimationController? myController;void initState() {super.initState();myController = AnimationController(vsync: this,lowerBound: -double.infinity,upperBound: double.infinity);myController!.value = widget.turns;}void dispose() {myController!.dispose();super.dispose();}Widget build(BuildContext context) {return RotationTransition(turns: myController!,child: widget.child,);}void didUpdateWidget(TurnBox oldWidget) {super.didUpdateWidget(oldWidget);// 旋转角度发生变化时执行过渡动画if (oldWidget.turns != widget.turns) {myController!.animateTo(widget.turns,duration: Duration(milliseconds: widget.speed??200),curve: Curves.easeOut,);}}
}

3. 自绘组件

对于一些复杂或不规则的UI,我们可能无法通过组合其他组件的方式来实现。比如一个正六边形、一个渐变的圆形进度条、一个棋盘等。在Flutter中,提供了一个CustomPaint 组件,它可以结合画笔CustomPainter来实现自定义图形绘制。

3-1. CustomPaint

画笔CustomPainter绘制时我们需要提供前景或背景画笔,两者也可以同时提供。我们的画笔需要继承CustomPainter类,我们在画笔类中实现真正的绘制逻辑。

属性描述
painter背景画笔,会显示在子节点后面
foregroundPainter前景画笔,会显示在子节点前面
size当child为null时,代表默认绘制区域大小,如果有child则忽略此参数,画布尺寸则为child尺寸。如果有child但是想指定画布为特定大小,可以使用SizeBox包裹CustomPaint实现。
isComplex是否复杂的绘制,如果是,Flutter会应用一些缓存策略来减少重复渲染的开销。
willChange和isComplex配合使用,当启用缓存时,该属性代表在下一帧中绘制是否会改变。

3-2. 绘制边界RepaintBoundary

如果CustomPaint有子节点,为了避免子节点不必要的重绘并提高性能,通常情况下都会将子节点包裹在RepaintBoundary组件中,这样会在绘制时就会创建一个新的绘制层(Layer),其子组件将在新的Layer上绘制,而父组件将在原来Layer上绘制,也就是说RepaintBoundary 子组件的绘制将独立于父组件的绘制,RepaintBoundary会隔离其子节点和CustomPaint本身的绘制边界。

CustomPaint(// 指定画布大小size: Size(300, 300),painter: MyPainter(),child: RepaintBoundary(child:...), 
)

3-3. CustomPainter与Canvas

CustomPainter中提定义了一个虚函数paint。它有两个参数,Canvas和Size。Canvas是Flutter中绘制UI的底层组件,它是一个画布,包括各种绘制方法。Size是当前绘制区域大小。Canvas常用API如下:

API描述
drawLine画线
drawPoint画点
drawPath画路径
drawImage画图像
drawRect画矩形
drawCircle画圆
drawOval画椭圆
drawArc画圆弧

3-4. 画笔Paint

Flutter提供了Paint类来实现画笔。在Paint中,我们可以配置画笔的各种属性如粗细、颜色、样式等。如下例子:

// 创建一个画笔并配置其属性
var paint = Paint()..isAntiAlias = true // 是否抗锯齿..style = PaintingStyle.fill // 画笔样式:填充..color = Color(0x77cdb175); // 画笔颜色

3-5. 绘制组件例子

如下,是一个自定义绘制的饼状图。

  • 饼图完整代码
import 'dart:math';
import 'package:flutter/material.dart';typedef PieChartViewTap = Function(int index);
typedef OutsideText = Text Function(PieChartModel model, String scale);class PieChartView extends ImplicitlyAnimatedWidget {final List<PieChartModel> models;/// 是否显示内部圆final bool isShowHole;/// 内部圆的半径final double holeRadius;/// 内部圆的颜色final Color holeColor;/// 扇形分割线宽度final double spaceWidth;/// 溢出上方文字final OutsideText? outsideTopText;/// 溢出下方文字final OutsideText? outsideBottomText;/// 扇形点击事件final PieChartViewTap? onTap;const PieChartView(this.models, {Key? key,this.holeRadius = 55.0,this.isShowHole = true,this.holeColor = Colors.white,this.spaceWidth = 2.0,this.outsideTopText,this.outsideBottomText,this.onTap,Curve curve = Curves.linear,Duration duration = const Duration(milliseconds: 150),}) : super(key: key,curve: curve,duration: duration,);CustomPieViewState createState() => CustomPieViewState();
}class CustomPieViewState extends AnimatedWidgetBaseState<PieChartView> {CustomPieTween? customPieTween;List<PieChartModel> get end => widget.models.map((e) => PieChartModel(value: e.value, color: e.color, name: e.name, radius: e.radius)).toList();Widget build(BuildContext context) {return CustomPaint(size: Size.infinite,painter: PieChartPainter(context,customPieTween!.evaluate(animation),holeRadius: widget.holeRadius,isShowHole: widget.isShowHole,holeColor: widget.holeColor,spaceWidth: widget.spaceWidth,outsideTopText: widget.outsideTopText,outsideBottomText: widget.outsideBottomText,onTap: widget.onTap,),);}void forEachTween(TweenVisitor<dynamic> visitor) {customPieTween = visitor(customPieTween, end, (dynamic value) {return CustomPieTween(begin: value, end: end);}) as CustomPieTween;}
}class CustomPieTween extends Tween<List<PieChartModel>> {CustomPieTween({List<PieChartModel>? begin, List<PieChartModel>? end}): super(begin: begin, end: end);List<PieChartModel> lerp(double t) {List<PieChartModel> list = [];begin?.asMap().forEach((index, model) {list.add(model..radius = lerpDouble(model.radius, end?[index].radius ?? 100.0, t));});return list;}double lerpDouble(double radius, double radius2, double t) {if (radius == radius2) {return radius;}var d = (radius2 - radius) * t;var value = radius + d;return value;}
}class PieChartPaint extends CustomPaint {const PieChartPaint({Key? key}) : super(key: key);
}class PieChartPainter extends CustomPainter {final BuildContext context;final List<PieChartModel> models;final bool isShowHole;final double holeRadius;final Color holeColor;final double spaceWidth;final OutsideText? outsideTopText;final OutsideText? outsideBottomText;final PieChartViewTap? onTap;final List<Path> paths = [];final Path holePath = Path();Offset oldTapOffset = Offset.zero;PieChartPainter(this.context,this.models, {this.holeRadius = 60.0,this.isShowHole = true,this.holeColor = Colors.white,this.spaceWidth = 2.0,this.outsideTopText,this.outsideBottomText,this.onTap,});void paint(Canvas canvas, Size size) {//移动到中心点canvas.translate(size.width / 2, size.height / 2);//绘制饼状图_drawPie(canvas, size);//绘制分割线_drawSpaceLine(canvas);// 绘制中心圆_drawHole(canvas, size);// drawLineAndText(canvas);}bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this;bool? hitTest(Offset position) {return _interceptTouchEvent(position);}bool _interceptTouchEvent(Offset offset) {if (oldTapOffset.dx == offset.dx && oldTapOffset.dy == offset.dy) {return false;}oldTapOffset = offset;for (int i = 0; i < paths.length; i++) {if (paths[i].contains(offset) && !holePath.contains(offset)) {onTap?.call(i);oldTapOffset = offset;return true;}}onTap?.call(-1);return false;}/// 绘制分割线void _drawSpaceLine(Canvas canvas) {var sumValue = models.fold<double>(0.0, (sum, model) => sum + model.value);var startAngle = 0.0;for (var model in models) {_drawLine(canvas, startAngle, model.radius);startAngle += model.value / sumValue * 360;_drawLine(canvas, startAngle, model.radius);}}void _drawLine(Canvas canvas, double angle, double radius) {var endX = cos(angle * pi / 180) * radius;var endY = sin(angle * pi / 180) * radius;Paint paint = Paint()..style = PaintingStyle.fill..color = Colors.white..strokeWidth = spaceWidth;canvas.drawLine(Offset.zero, Offset(endX, endY), paint);}/// 绘制饼状图void _drawPie(Canvas canvas, Size size) {var startAngle = 0.0;var sumValue = models.fold<double>(0.0, (sum, model) => sum + model.value);for (var model in models) {Paint paint = Paint()..style = PaintingStyle.fill..color = model.color;var sweepAngle = model.value / sumValue * 360;canvas.drawArc(Rect.fromCircle(radius: model.radius, center: Offset.zero),startAngle * pi / 180, sweepAngle * pi / 180, true, paint);Path path = Path();var centerX = size.width / 2;var centerY = size.height / 2;path.addArc(Rect.fromCircle(radius: model.radius, center: Offset(centerX, centerY)),startAngle * pi / 180,sweepAngle * pi / 180);path.moveTo(centerX, centerY);path.lineTo(centerX + cos(startAngle * pi / 180) * model.radius,centerY + sin(startAngle * pi / 180) * model.radius);path.lineTo(centerX + cos((sweepAngle + startAngle) * pi / 180) * model.radius,centerY + sin((sweepAngle + startAngle) * pi / 180) * model.radius);paths.add(path);// 为每一个区域绘制延长线和文字_drawLineAndText(canvas, size, model.radius, startAngle, sweepAngle, model);startAngle += sweepAngle;}}/// 绘制延长线和文字void _drawLineAndText(Canvas canvas, Size size, double radius,double startAngle, double sweepAngle, PieChartModel model) {var ratio = (sweepAngle / 360.0 * 100).toStringAsFixed(2);var top = outsideTopText?.call(model, ratio) ??Text(model.name,style: const TextStyle(color: Colors.black38),);var topTextPainter = getTextPainter(top);var bottom = outsideBottomText?.call(model, ratio) ??Text("$ratio%",style: const TextStyle(color: Colors.black38),);var bottomTextPainter = getTextPainter(bottom);// 绘制横线// 计算开始坐标以及转折点的坐标var startX = radius * (cos((startAngle + (sweepAngle / 2)) * (pi / 180)));var startY = radius * (sin((startAngle + (sweepAngle / 2)) * (pi / 180)));var firstLine = radius / 5;var secondLine =max(bottomTextPainter.width, topTextPainter.width) + radius / 4;var pointX = (radius + firstLine) *(cos((startAngle + (sweepAngle / 2)) * (pi / 180)));var pointY = (radius + firstLine) *(sin((startAngle + (sweepAngle / 2)) * (pi / 180)));// 计算坐标在左边还是在右边// 并计算横线结束坐标// 如果结束坐标超过了绘制区域,则改变结束坐标的值var endX = 0.0;// 距离绘制边界的偏移量var marginOffset = 20.0;if (pointX - startX > 0) {endX = min(pointX + secondLine, size.width / 2 - marginOffset);secondLine = endX - pointX;} else {endX = max(pointX - secondLine, -size.width / 2 + marginOffset);secondLine = pointX - endX;}Paint paint = Paint()..style = PaintingStyle.fill..strokeWidth = 1..color = Colors.grey;// 绘制延长线canvas.drawLine(Offset(startX, startY), Offset(pointX, pointY), paint);canvas.drawLine(Offset(pointX, pointY), Offset(endX, pointY), paint);// 文字距离中间横线上下间距偏移量var offset = 4;var textWidth = bottomTextPainter.width;var textStartX = 0.0;textStartX = _calculateTextStartX(pointX, startX, textWidth, secondLine, textStartX, offset);bottomTextPainter.paint(canvas, Offset(textStartX, pointY + offset));textWidth = topTextPainter.width;var textHeight = topTextPainter.height;textStartX = _calculateTextStartX(pointX, startX, textWidth, secondLine, textStartX, offset);topTextPainter.paint(canvas, Offset(textStartX, pointY - offset - textHeight));// 绘制文字前面的小圆点paint.color = model.color;canvas.drawCircle(Offset(textStartX - 8, pointY - 4 - topTextPainter.height / 2),4,paint);}double _calculateTextStartX(double stopX, double startX, double w,double line2, double textStartX, int offset) {if (stopX - startX > 0) {if (w > line2) {textStartX = (stopX + offset);} else {textStartX = (stopX + (line2 - w));}} else {if (w > line2) {textStartX = (stopX - offset - w);} else {textStartX = (stopX - (line2 - w) - w);}}return textStartX;}TextPainter getTextPainter(Text text) {TextPainter painter = TextPainter(locale: Localizations.localeOf(context),maxLines: text.maxLines,textDirection: TextDirection.ltr,text: TextSpan(text: text.data,style: text.style,),);painter.layout();return painter;}/// 绘制中心圆void _drawHole(Canvas canvas, Size size) {if (isShowHole) {holePath.reset();Paint paint = Paint()..style = PaintingStyle.fill..color = Colors.white;canvas.drawCircle(Offset.zero, holeRadius, paint);var centerX = size.width / 2;var centerY = size.height / 2;holePath.addArc(Rect.fromCircle(radius: holeRadius, center: Offset(centerX, centerY)),0,360 * pi / 180);}}
}/// 数据
class PieChartModel {double value;Color color;String name;double radius;PieChartModel({required this.value,required this.color,required this.name,this.radius = 100,});
}
  • 使用
import 'package:flutter/material.dart';
import 'package:demo1/widget/MyPieChart.dart';/// 定义
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => HomePageState();
}/// 实现
class HomePageState extends State<HomePage> {double myTurns = 0.0;Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Flutter Home'),),body: Container(alignment: Alignment.center,// 饼图child: PieChartView([PieChartModel(value: 35,name: 'A',color: Colors.blue,radius: 100,),PieChartModel(value: 15,name: 'B',color: Colors.red,radius: 100,),PieChartModel(value: 22,name: 'C',color: Colors.yellow,radius: 100,),PieChartModel(value: 18,name: 'D',color: Colors.orange,radius: 100,),PieChartModel(value: 39,name: 'F',color: Colors.green,radius: 100,),],),));}
}

本次分享就到这儿啦,我是鹏多多,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

往期文章

  • 手把手教你搭建规范的团队vue项目,包含commitlint,eslint,prettier,husky,commitizen等等
  • Web Woeker和Shared Worker的使用以及案例
  • Vue2全家桶+Element搭建的PC端在线音乐网站
  • vue3+element-plus配置cdn
  • 助你上手Vue3全家桶之Vue3教程
  • 助你上手Vue3全家桶之VueX4教程
  • 助你上手Vue3全家桶之Vue-Router4教程
  • 超详细!Vue的九种通信方式
  • 超详细!Vuex手把手教程
  • 使用nvm管理node.js版本以及更换npm淘宝镜像源
  • vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
  • 超详细!Vue-Router手把手教程

个人主页

  • CSDN
  • GitHub
  • 简书
  • 博客园
  • 掘金

相关文章:

flutter学习-day16-自定义组件

&#x1f4da; 目录 介绍组合多个组件自绘组件 Custompaint绘制边界RepaintBoundaryCustomPainter与Canvas画笔Paint绘制组件例子 本文学习和引用自《Flutter实战第二版》&#xff1a;作者&#xff1a;杜文 1. 介绍 当Flutter提供的现有组件无法满足我们的需求&#xff0c;或…...

XML简介 (EXtensible Markup Language)

XML简介 (EXtensible Markup Language) 可扩展标记语言 特点 XML与操作系统、编程语言的开发平台无关实现不同系统之间的数据交换 作用 数据交互配置应用程序和网站Ajax基石 XML标签 XML文档内容由一系列标签元素组成 <元素名 属性名"属性值">元素内容&l…...

基于Spring自动注入快速实现策略模式+工厂模式优化过多的if..else

一、策略模式 1.1策略模式定义 在策略模式&#xff08;Strategy Pattern&#xff09;中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。 在策略模式定义了一系列算法或策略&#xff0c;并将每个算法封装在独立的类中&#xff0c;使得它们可以互相…...

安装vcpkg管理opencv的安装+MFC缺失的解决

第一步&#xff0c;出现#include没有办法找到opencv头文件的问题&#xff0c;无法解决 在VC的提示下&#xff0c;安装了vcpkg&#xff0c;然后用vcpkg命令来帮助安装opencv&#xff0c;过程十分顺利。 1. cmd 到命令行窗口&#xff1b; 2. 建立src文件夹&#xff0c;并进入…...

了解树和学习二叉树

1.树 1.1 概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 。 注意&#xff1a;树形结构中…...

Spring Boot学习随笔- 拦截器实现和配置(HandlerInterceptor、addInterceptors)、jar包部署和war包部署

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第十三章、拦截器 拦截器 &#xff1a;Interceptor 拦截 中断 类似于javaweb中的Filter&#xff0c;不过没有Filter那么强大 作用 Spring MVC的拦截器是一种用于在请求处理过程中进行预处理和后处理的机制。拦…...

Pipelined-ADC设计二——结构指标及非理想因素(Part2)

接上文&#xff0c;本章将两个比较重要的非理想因素&#xff0c;因此各项指标制定。后续会对常见的非理想因素给出常见的解决方法&#xff0c;以及设计所采用的方法。 2.2.7. 比较器失调 在流水线 ADC 中&#xff0c;比较器的主要误差来源就是比较器失调&#xff0c;称为失调误…...

Ubuntu 常用命令之 clear 命令用法介绍

&#x1f4d1;Linux/Ubuntu 常用命令归类整理 clear命令在Ubuntu系统下用于清除终端屏幕的内容。这个命令没有任何参数&#xff0c;它的主要作用就是清理终端屏幕上的所有信息&#xff0c;使得屏幕看起来像是新打开的一样。 使用clear命令非常简单&#xff0c;只需要在终端中…...

【JAVA面试题】什么是对象锁?什么是类锁?

&#x1f34e; 个人博客 &#xff1a;个 人 主 页 &#x1f3c6;个人专栏&#xff1a;多线程JAVA ⛳️ 功 不 唐 捐 &#xff0c;玉 汝 于 成 目录 前言 回答 对象锁&#xff08;Object Lock&#xff09;&#xff1a; 类锁&#xff08;Class Lock&#xff09;&#xff1…...

飞天使-k8s知识点5-kubernetes基础名词扫盲

文章目录 deploymentspodNodeserviceskubectl 实现应用伸缩kubectl 实现滚动更新kubernetes架构 deployments 中文文档 http://docs.kubernetes.org.cn/251.htmldeployment是用来创建和更新应用的&#xff0c;master 会负责将创建好的应用实例调度到集群中的各个节点 应用实例…...

【视觉实践】使用Mediapipe进行目标检测:杯子检测和椅子检测实践

目录 1 Mediapipe 2 Solutions 3 安装mediapipe 4 实践 1 Mediapipe Mediapipe是google的一个开源项目,可以提供开源的、跨平台的常用机器学习(machine learning,ML)方案。MediaPipe是一个用于构建机器学习管道</...

C++之深拷贝进阶

目录 拷贝构造函数的深拷贝进阶版本 赋值运算符重载的深拷贝进阶 总结 上期我们学习了C中深拷贝的传统版本&#xff0c;今天我们将学习更为高效的版本。 拷贝构造函数的深拷贝进阶版本 传统版本代码如下&#xff1a; string(string& s):_str(new char[strlen(s._str)…...

导行电磁波从纵向场分量求其他方向分量的矩阵表示

导行电磁波从纵向场分量求解其他方向分量的矩阵表示 导行电磁波传播的特点 电磁波在均匀、线性、各向同性的空间中沿着 z z z轴传播&#xff0c;可用分离变量法将时间轴、 z z z轴与 x , y x,y x,y轴分离&#xff0c;电磁波的形式可表示为&#xff1a; E ⃗ E ⃗ ( x , y )…...

融资项目——swagger2的注解

1. ApiModel与ApiModelProperty(在实体类中使用) 如上图&#xff0c;ApiModel加在实体类上方&#xff0c;用于整体描述实体类。ApiModelProperty(value"xxx",example"xxx")放于每个属性上方&#xff0c;用于对属性进行描述。swagger2网页上的效果如下图&am…...

【性能优化】MySql数据库查询优化方案

阅读本文你的收获 了解系统运行效率提升的整体解决思路和方向学会MySQl中进行数据库查询优化的步骤学会看慢查询、执行计划、进行性能分析、调优 一、问题&#xff1a;如果你的系统运行很慢&#xff0c;你有什么解决方案&#xff1f; ​关于这个问题&#xff0c;我们通常首先…...

Chrome浏览器http自动跳https问题

现象&#xff1a; Chrome浏览器访问http页面时有时会自动跳转https&#xff0c;导致一些问题。比如&#xff1a; 开发阶段访问dev环境网址跳https&#xff0c;后端还是http&#xff0c;导致接口跨域。 复现&#xff1a; 先访问http网址&#xff0c;再改成https访问&#xf…...

【C++进阶02】多态

一、多态的概念及定义 1.1 多态的概念 多态简单来说就是多种形态 同一个行为&#xff0c;不同对象去完成时 会产生出不同的状态 多态分为静态多态和动态多态 静态多态指的是编译时 在程序编译期间确定了程序的行为 比如&#xff1a;函数重载 动态多态指的是运行时 在程序运行…...

PHP开发日志——循环和条件语句嵌套不同,效率不同(循环内加入条件语句,条件语句判断后加入循环,array_map函数中加入条件语句)

十多年前开发框架时&#xff0c;为了效率不断试过各种代码写法&#xff0c;今天又遇到了&#xff0c;想想php8时代会不会有所变化&#xff0c;结果其实也还是和当年一样&#xff0c;但当年没写博客&#xff0c;但现在可以把数据记录下来了。 PHP_loop_ireflies_dark_forest 项目…...

【Seata源码学习 】 扫描@GlobalTransaction注解 篇一

1. SeataAutoConfiguration 自动配置类的加载 基于SpringBoot的starter机制&#xff0c;在应用上下文启动时&#xff0c;会加载SeataAutoConfiguration自动配置类 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfigurationio.seata.spring.boot.aut…...

DBA-MySql面试问题及答案-上

文章目录 1.什么是数据库?2.如何查看某个操作的语法?3.MySql的存储引擎有哪些?4.常用的2种存储引擎&#xff1f;6.可以针对表设置引擎吗&#xff1f;如何设置&#xff1f;6.选择合适的存储引擎&#xff1f;7.选择合适的数据类型8.char & varchar9.Mysql字符集10.如何选择…...

网络爬虫之Ajax动态数据采集

动态数据采集 规则 有时候我们在用 requests 抓取页面的时候&#xff0c;得到的结果可能和在浏览器中看到的不一样&#xff0c;在浏览器中可以看到正常显示的页面教据&#xff0c;但是使用 requests 得到的结果并没有&#xff0c;这是因为requests 获取的都是原始的 HTML 文档…...

c语言的初始学习(练习)

##初学c语言---MOOC浙江大学翁恺先生学习c语言 那么我们先看看这个题目吧&#xff0c;这是初始语法的应用。 记住&#xff0c;我们的程序是按步骤执行的&#xff0c;并不是在不同的两行同时进行。 程序设计&#xff1a;1.了解题目的需要&#xff0c;几个变量需要用到&#x…...

研究论文 2022-Oncoimmunology:AI+癌RNA-seq数据 识别细胞景观

Wang, Xin, et al. "Deep learning using bulk RNA-seq data expands cell landscape identification in tumor microenvironment." Oncoimmunology 11.1 (2022): 2043662. https://www.tandfonline.com/doi/full/10.1080/2162402X.2022.2043662 被引次数&#xff1…...

ChatGPT4与ArcGIS Pro3助力AI 地理空间分析和可视化及助力科研论文写作

在地学领域&#xff0c;ArcGIS几乎成为了每位科研工作者作图、数据分析的必备工具&#xff0c;而ArcGIS Pro3除了良好地继承了ArcMap强大的数据管理、制图、空间分析等能力&#xff0c;还具有二三维融合、大数据、矢量切片制作及发布、任务工作流、时空立方体等特色功能&#x…...

okhttp系列-一些上限值

1.正在执行的任务数量最大值是64 异步请求放入readyAsyncCalls后&#xff0c;遍历readyAsyncCalls取出任务去执行的时候&#xff0c;如果发现runningAsyncCalls的数量大于等于64&#xff0c;就不从readyAsyncCalls取出任务执行。 public final class Dispatcher {private int …...

C++面向对象(OOP)编程-STL详解(vector)

本文主要介绍STL六大组件&#xff0c;并主要介绍一些容器的使用。 目录 1 泛型编程 2 CSTL 3 STL 六大组件 4 容器 4.1 顺序性容器 4.1.1 顺序性容器的使用场景 4.2 关联式容器 4.2.1 关联式容器的使用场景 4.3 容器适配器 4.3.1 容器适配器的使用场景 5 具体容器的…...

postman几种常见的请求方式

1、get请求直接拼URL形式 对于http接口&#xff0c;有get和post两种请求方式&#xff0c;当接口说明中未明确post中入参必须是json串时&#xff0c;均可用url方式请求 参数既可以写到URL中&#xff0c;也可写到参数列表中&#xff0c;都一样&#xff0c;请求时候都是拼URL 2&am…...

openai最新探索:超级对齐是否可行?

前言 今天来介绍一篇openai最新的paper&#xff1a;弱到强的对齐。 openai专门成立了一个团队来做大模型的超级对齐即superhuman model&#xff0c;之前chatgpt取得成功依赖RLHF即依赖人类反馈&#xff0c;但是作者期望的superhuman model将会是一个能够处理各种复杂问题的强…...

本地websocket服务端结合cpolar内网穿透实现公网访问

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…...

关于“Python”的核心知识点整理大全37

目录 13.6.2 响应外星人和飞船碰撞 game_stats.py settings.py alien_invasion.py game_functions.py ship.py 注意 13.6.3 有外星人到达屏幕底端 game_functions.py 13.6.4 游戏结束 game_stats.py game_functions.py 13.7 确定应运行游戏的哪些部分 alien_inva…...

哪个公司做网站好/百度竞价广告怎么投放

最近发现很多的站长朋友会问到伪静态的问题&#xff0c;那到底什么是伪静态、伪静态有什么好呢&#xff1f;我们先来了解一下什么是伪静态。要设置伪静态&#xff0c;请先弄清楚自己的网站环境&#xff01;伪静态伪静态是相对真实静态来讲的&#xff0c;伪静态就是将一些用PHP一…...

宜选网的网站是什么做的/郑州网站定制

LeetCode 1114&#xff1a;按序打印题目描述解题思路代码实现SynchronizedReentrantLockCyclicBarrierSemaphore法一Semaphore法二总结题目描述 给你一个类&#xff1a; public class Foo {public void first() { print("first"); }public void second() { print(&…...

珠海网站建设兼职/搜索引擎下载入口

在本文中&#xff0c;我们将了解如何配置Cisco3850交换机以实现基本无线连接。 这是Converged Access产品平台的一部分&#xff0c;您应该对新架构有一定的了解&#xff08;本文不会讨论&#xff09;。 这里是使用3850作为WLC时需要记住的几个关键点。 1. You have to attach y…...

wordpress用户登录插件/品牌seo培训

1、认真做好手头上的事情&#xff0c;并做到足够专业。因为让自己在市场上具备竞争力&#xff0c;方才能立于不败之地。 2、永远不要放弃学习和思考。 老话常谈&#xff1a;35岁中年危机 35岁这个话题&#xff0c;说来说去&#xff0c;关键还是看程序员们自己。不用回答我&…...

网站的主要栏目及功能/深圳seo优化服务商

编辑&#xff1a;ll RB157-ASEMI整流圆桥RB157 型号&#xff1a;RB157 品牌&#xff1a;ASEMI 封装&#xff1a;WOB-4 特性&#xff1a;整流圆桥 正向电流&#xff1a;1A 反向耐压&#xff1a;1000V 恢复时间&#xff1a;ns 引脚数量&#xff1a;4 芯片个数&#xff…...

网站页脚怎么做能好看点/百度指数查询工具app

贪心 class Solution { public:int maxSubArray(vector<int>& nums) {long long ans -3e9,cnt 0, his0, n nums.size(); for(int i0;i<n;i){if(his<0){// 如果 以上一个数结尾的子数组的和 小于0&#xff0c;那就不要前面这段cnt nums[i];}else{// 否则前…...