Flutter-基础Widget

Flutter页面-基础Widget

文章目录

  • Flutter页面-基础Widget
    • Widget
      • Stateless Widget
      • Stateful Widget
        • State生命周期
    • 基础widget
      • 文本显示
        • Text
        • RichText
        • DefaultTextStyle
      • 图片显示
        • FlutterLogo
        • Icon
        • Image
          • Iamge.asset
          • Image.file
          • Image.network
          • Image.memory
        • CircleAvatar
        • FadeInImage
      • 按钮
        • RaisedButton
        • FlatButton
        • OutlineButton
        • IconButton
      • 输入框
        • 焦点控制
        • 获取输入内容
        • TextFormField

​ 在Flutter中,几乎所有的对象都是一个 Widget,与原生开发中的 控件不同的是,Flutter中的 widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的组件如:用于手势检测的 GestureDetector widget、用于应用主题数据传递的 Theme等等。由于Flutter主要就是用于构建用户界面的,所以,在大多数时候,可以认为widget就是一个控件,不必纠结于概念。

​ Widget的功能是“描述一个UI元素的配置数据”,Widget其实并不是表示最终绘制在设备屏幕上的显示元素,而只是显示元素的一个配置数据。实际上,Flutter中真正代表屏幕上显示元素的类是Element,也就是说Widget只是描述Element的一个配置。一个Widget可以对应多个Element,这是因为同一个Widget对象可以被添加到UI树的不同部分,而真正渲染时,UI树的每一个节点都会对应一个Element对象。

Widget

StatelessWidgetStatefulWidgetflutter的基础组件,日常开发中自定义Widget都是选择继承这两者之一。也是在往后的开放中,我们最多接触的Widget:

  • StatelessWidget:无状态的,展示信息,面向那些始终不变的UI控件;

  • StatefulWidget:有状态的,可以通过改变状态使得 UI 发生变化,可以包含用户交互(比如弹出一个 dialog)。

在实际使用中,Stateless与Stateful的选择需要取决于这个 Widget 是有状态还是无状态,简单来说看界面是否需要更新。

Stateless Widget

​ StatelessWidget用于不需要维护状态的场景,它通常在build方法中通过嵌套其它Widget来构建UI,在构建过程中会递归的构建其嵌套的Widget。

BuildContext表示构建widget的上下文,它是操作widget在树中位置的一个句柄,它包含了一些查找、遍历当前Widget树的一些方法。每一个widget都有一个自己的context对象。

import 'package:flutter/material.dart';

void main() => runApp(StatelessApp());

class StatelessApp extends StatelessWidget {
  ///在build方法中通过嵌套其它Widget来构建UI,在构建过程中会递归的构建其嵌套的Widget
  
  Widget build(BuildContext context) {
    //嵌套 MaterialApp:封装了应用程序实现Material Design所需要的一些widget
    return MaterialApp(
        title: "Widget演示", //标题,显示在recent时候的标题
        //主页面
        //Scaffold : Material Design布局结构的基本实现。
        home: Scaffold(
          //ToolBar/ActionBar
          appBar: AppBar(title: Text("Widget")),
          body: Text("Hello,Flutter!"),
        )
    );
  }
}

Material Design:

一种设计语言,Material Design 于2014年的 Google I/O 首次亮相,是谷歌推出的全新的设计语言。说白了,就是一种设计风格。

Stateful Widget

​ StatefulWidget是动态的,添加了一个新的接口createState()用于创建和Stateful widget相关的状态State,它在Stateful widget的生命周期中可能会被多次调用。

​ 当State被改变时,可以手动调用其setState()方法通知Flutter framework状态发生改变,Flutter framework在收到消息后,会重新调用其build方法重新构建widget树,从而达到更新UI的目的。

class StatefulState extends State<StatefulApp> {
  int _i;

  ///当Widget第一次插入到Widget树时会被调用,对于每一个State对象,Flutter framework只会调用一次该回调
  
  void initState() {
    super.initState();
    _i = 1;
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
        title: "Widget演示",
        theme: ThemeData(),
        home: Scaffold(
          appBar: AppBar(title: Text("Widget")),
          body: RaisedButton(
            onPressed: () {
              //修改状态,setState会重新调用build更新ui
              setState(() {
                _i++;
              });
            },
            child: Text("Hello,Flutter! $_i"),
          ),
        ));
  }
}

State生命周期

​ State类除了build之外还提供了很多方法能够让我们重写,这些方法会在不同的状态下由Flutter调起执行,所以这些方法我们就称之为生命周期方法。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool isShowChild;

  ///当Widget第一次插入到Widget树时会被调用,对于每一个State对象,Flutter framework只会调用一次该回调
  
  void initState() {
    super.initState();
    isShowChild = true;
    debugPrint("parent initState......");
  }

  ///初始化时,在initState()之后立刻调用
  ///当依赖的InheritedWidget rebuild,会触发此接口被调用
  
  void didChangeDependencies() {
    super.didChangeDependencies();
    debugPrint("parent didChangeDependencies......");
  }

  ///绘制界面,当setState触发的时候会再次被调用
  
  Widget build(BuildContext context) {
    debugPrint("parent build......");
    return MaterialApp(
      home: Scaffold(
        body: Center(
            child: RaisedButton(
          onPressed: () {
            setState(() {
              isShowChild = !isShowChild;
            });
          },
          child: isShowChild ? Child() : Text("演示移除Child"),
        )),
      ),
    );
  }

  ///状态改变的时候会调用该方法,比如调用了setState
  
  void didUpdateWidget(MyApp oldWidget) {
    super.didUpdateWidget(oldWidget);
    debugPrint("parent didUpdateWidget......");
  }

  ///当State对象从树中被移除时,会调用此回调
  
  void deactivate() {
    super.deactivate();
    debugPrint('parent deactivate......');
  }

  ///当State对象从树中被永久移除时调用;通常在此回调中释放资源
  
  void dispose() {
    super.dispose();
    debugPrint('parent dispose......');
  }
}

class Child extends StatefulWidget {
  
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  
  Widget build(BuildContext context) {
    debugPrint("child build......");
    return Text('lifeCycle');
  }

  
  void initState() {
    super.initState();
    debugPrint("child initState......");
  }

  ///初始化时,在initState()之后立刻调用
  ///当依赖的InheritedWidget rebuild,会触发此接口被调用
  
  void didChangeDependencies() {
    super.didChangeDependencies();
    debugPrint("child didChangeDependencies......");
  }

  ///父widget状态改变的时候会调用该方法,比如父节点调用了setState
  
  void didUpdateWidget(Child oldWidget) {
    super.didUpdateWidget(oldWidget);
    debugPrint("child didUpdateWidget......");
  }

  ///当State对象从树中被移除时,会调用此回调
  
  void deactivate() {
    super.deactivate();
    debugPrint('child deactivate......');
  }

  ///当State对象从树中被永久移除时调用;通常在此回调中释放资源
  
  void dispose() {
    super.dispose();
    debugPrint('child dispose......');
  }
}

执行的输出结果显示为:

  • 运行到显示
I/flutter (22218): parent initState......
I/flutter (22218): parent didChangeDependencies......
I/flutter (22218): parent build......
I/flutter (22218): child initState......
I/flutter (22218): child didChangeDependencies......
I/flutter (22218): child build......
  • 点击按钮会移除Child
I/flutter (22218): parent build......
I/flutter (22218): child deactivate......
I/flutter (22218): child dispose......
  • 将MyApp的代码由 child: isShowChild ? Child() : Text("演示移除Child"),改为 child: Child(),点击按钮时
I/flutter (22765): parent build......
I/flutter (22765): child didUpdateWidget......
I/flutter (22765): child build......

从这些实验中能够得出State的生命周期为:

在这里插入图片描述

基础widget

文本显示

Text

Text是展示单一格式的文本Widget(Android TextView)。

import 'package:flutter/material.dart';

///
/// main方法 调用runApp传递Widget,这个Widget成为widget树的根
void main() => runApp(TextApp());

///
/// 1、单一文本Text
///
//创建一个无状态的Widget
class TextApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    //封装了应用程序实现Material Design所需要的一些widget
    return MaterialApp(
      title: "Text演示", //标题,显示在recent时候的标题
      //主页面
      //Scaffold : Material Design布局结构的基本实现。
      home: Scaffold(
        //ToolBar/ActionBar
        appBar: AppBar(title: Text("Text")),
        body: Text("Hello,Flutter"),
      ),
    );
  }
}

在使用Text显示文字时候,可能需要对文字设置各种不同的样式,类似Android的 android:textColor/Size

在Flutter中也拥有类似的属性

Widget _TextBody() {
  return Text(
    "Hello,Flutter",
    style: TextStyle(
        //颜色
        color: Colors.red,
        //字号 默认14
        fontSize: 18,
        //粗细
        fontWeight: FontWeight.w800,
        //斜体
        fontStyle: FontStyle.italic,
        //underline:下划线,overline:上划线,lineThrough:删除线
        decoration: TextDecoration.lineThrough,
        decorationColor: Colors.black,
        //solid:实线,double:双线,dotted:点虚线,dashed:横虚线,wavy:波浪线
        decorationStyle: TextDecorationStyle.wavy),
  );
}

class TextApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Text演示", 
      home: Scaffold(
        appBar: AppBar(title: Text("Text")),
        body: _TextBody(),
      ),
    );
  }
}

RichText

如果需要显示更为丰富样式的文本(比如一段文本中文字不同颜色),可以使用RichText或者Text.rich

Widget _RichTextBody() {
  var textSpan = TextSpan(
    text: "Hello",
    style: TextStyle(color: Colors.red),
    children: [
      TextSpan(text: "Flu", style: TextStyle(color: Colors.blue)),
      TextSpan(text: "uter", style: TextStyle(color: Colors.yellow)),
    ],
  );
  //Text.rich(textSpan);
  return RichText(text: textSpan);
}

DefaultTextStyle

​ 在widget树中,文本的样式默认是可以被继承的,因此,如果在widget树的某一个节点处设置一个默认的文本样式,那么该节点的子树中所有文本都会默认使用这个样式。相当于在Android中定义 Theme

Widget _DefaultStyle(){
  DefaultTextStyle(
    //设置文本默认样式
    style: TextStyle(
      color:Colors.red,
      fontSize: 20.0,
    ),
    textAlign: TextAlign.start,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Text("Hello Flutter!"),
        Text("Hello Flutter!"),
        Text("Hello Flutter!",
          style: TextStyle(
              inherit: false, //不继承默认样式
              color: Colors.grey
          ),
        ),
      ],
    ),
  );
}

图片显示

“图文”:有文字显示Widget,又怎么少的了图片呢。

FlutterLogo

​ 这个Widget用于显示Flutter的logo…

Widget flutterLogo() {
  return FlutterLogo(
    //大小
    size: 100,
    //logo颜色 默认为 Colors.blue
    colors: Colors.red,
    //markOnly:只显示logo,horizontal:logo右边显示flutter文字,stacked:logo下面显示文字
    style: FlutterLogoStyle.stacked,
    //logo上文字颜色
    textColor: Colors.blue,
  );
}

Icon

主要用于显示内置图标的Widget

Widget icon() {
  return Icon(
      //使用预定义Material icons
      // https://docs.flutter.io/flutter/material/Icons-class.html
      Icons.add,
      size: 100,
      color: Colors.red);
}

Image

显示图片的Widget。图片常用的格式主要有bmp,jpg,png,gif,webp等,Android中并不是天生支持gif和webp动图,但是这一特性在flutter中被很好的支持了。

方式解释
Image()使用ImageProvider提供图片,如下方法本质上也是使用的这个方法
Image.asset加载资源图片
Image.file加载本地图片文件
Image.network加载网络图片
Image.memory加载内存图片
Iamge.asset

在工程目录下创建目录,如:assets,将图片放入此目录。打开项目根目录:pubspec.yaml

在这里插入图片描述

return MaterialApp(
      title: "Image演示",
      home: Scaffold(
        appBar: AppBar(title: Text("Image")),
        body: Image.asset("assets/banner.jpeg"),
      ),
    );
Image.file

在sd卡中放入一张图片。然后利用path_provider库获取sd卡根目录(Dart库版本可以在:https://pub.dartlang.org/packages查询)。

在这里插入图片描述

注意权限

class ImageState extends State<ImageApp> {
  Image image;

  
  void initState() {
    super.initState();
    getExternalStorageDirectory().then((path) {
      setState(() {
        image = Image.file(File("${path.path}${Platform.pathSeparator}banner.jpeg"));
      });
    });
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Image演示",
      home: Scaffold(
        appBar: AppBar(title: Text("Image")),
        body: image,
      ),
    );
  }
}
Image.network

直接给网络地址即可。

Flutter 1.0,加载https时候经常出现证书错误。必须断开AS打开app

Image.memory
Future<List<int>> _imageByte() async {
  String path = (await getExternalStorageDirectory()).path;
  return await File("$path${Platform.pathSeparator}banner.jpeg").readAsBytes();
}

class ImageState extends State<ImageApp> {
  Image image;

  
  void initState() {
    super.initState();
    _imageByte().then((bytes) {
      setState(() {
        image = Image.memory(bytes);
      });
    });
  }

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Image演示",
      home: Scaffold(
        appBar: AppBar(title: Text("Image")),
        body: image,
      ),
    );
  }
}

fit属性相当于android中的scaletype,定义如下:

fit说明效果
BoxFit.fill填充,忽略原有的宽高比,填满为止[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Rnxejq9-1690637402334)(图片/基础Widget_Image_Fill.png)]
BoxFit.contain包含,不改变原有比例让容器包含整个图片,容器多余部分填充背景[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q33jpCMX-1690637402335)(图片/基础Widget_Image_Contain.png)]
BoxFit.cover覆盖,不改变原有比例,让图片充满整个容器,图片多余部分裁剪[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RawRtrsg-1690637402335)(图片/基础Widget_Image_Cover.png)]
BoxFit.fitWidth横向图片填充[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x2CnXYnj-1690637402335)(图片/基础Widget_Image_FitWidth.png)]
BoxFit.fitHeight纵向图片填充[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zu8quSyE-1690637402336)(图片/基础Widget_Image_FitHeight.png)]
BoxFit.none原始大小居中[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tnW2XX4w-1690637402336)(图片/基础Widget_Image_none.png)]
BoxFit.scaleDown图片大小小于容器事相当于none,图片大小大于容器时缩小图片大小实现contain[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IDbz5R3F-1690637402336)(图片/基础Widget_Image_ScaleDown.png)]

CircleAvatar

主要用来显示用户的头像,任何图片都会被剪切为圆形。

CircleAvatar(
      //图片提供者 ImageProvider
      backgroundImage: AssetImage("assets/banner.jpeg"),
      //半径,控制大小
      radius: 50.0,
    );

FadeInImage

当使用默认Image widget显示图片时,您可能会注意到它们在加载完成后会直接显示到屏幕上。这可能会让用户产生视觉突兀。如果最初显示一个占位符,然后在图像加载完显示时淡入,我们可以使用FadeInImage来达到这个目的!

 image =  FadeInImage.memoryNetwork(
      placeholder: kTransparentImage,
      image: 'https://flutter.io/images/homepage/header-illustration.png',
    );

按钮

Material widget库中提供了多种按钮Widget如RaisedButton、FlatButton、OutlineButton等,它们都是直接或间接对RawMaterialButton的包装定制,所以他们大多数属性都和RawMaterialButton一样。所有Material 库中的按钮都有如下相同点:

  1. 按下时都会有“水波动画”。
  2. 有一个onPressed属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

RaisedButton

"漂浮"按钮,它默认带有阴影和灰色背景

RaisedButton(
          child: Text("normal"),
          onPressed: () => {},
        )

FlatButton

扁平按钮,默认背景透明并不带阴影

FlatButton(
  child: Text("normal"),
  onPressed: () => {},
)

OutlineButton

默认有一个边框,不带阴影且背景透明。

OutlineButton(
  child: Text("normal"),
  onPressed: () => {},
)

IconButton

可点击的Icon

IconButton(
  icon: Icon(Icons.thumb_up),
  onPressed: () => {},
)

按钮外观可以通过其属性来定义,不同按钮属性大同小异

const FlatButton({
  ...  
   this.onPressed, //按钮点击回调
  this.textColor, //按钮文字颜色
  this.disabledTextColor, //按钮禁用时的文字颜色
  this.color, //按钮背景颜色
  this.disabledColor,//按钮禁用时的背景颜色
  this.highlightColor, //按钮按下时的背景颜色
  this.splashColor, //点击时,水波动画中水波的颜色
  this.colorBrightness,//按钮主题,默认是浅色主题 
  this.padding, //按钮的填充
  this.shape, //外形
   this.child, //按钮的内容
})
    
FlatButton(
  onPressed: () => {},
  child: Text("Raised"),
  //蓝色
  color: Colors.blue,
  //水波
  splashColor: Colors.yellow,
  //深色主题,这样文字颜色会变成白色
  colorBrightness: Brightness.dark,
   //圆角按钮
  shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(50)
  ),
)

RaisedButton,默认配置有阴影,因此在配置RaisedButton 时,拥有一系列 elevation 属性的配置

const RaisedButton({
  ...
  this.elevation = 2.0, //正常状态下的阴影
  this.highlightElevation = 8.0,//按下时的阴影
  this.disabledElevation = 0.0,// 禁用时的阴影
  ...
}

输入框

import 'package:flutter/material.dart';

void main() => runApp(Demo1());

class Demo1 extends StatelessWidget {

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Demo1",
      home: Scaffold(
        appBar: AppBar(
          title: Text("登录"),
        ),
        //线性布局,垂直方向
        body: Column(
          children: <Widget>[
            TextField(
              //自动获得焦点
              autofocus: true,
              decoration: InputDecoration(
                  labelText: "用户名",
                  hintText: "用户名或邮箱",
                  prefixIcon: Icon(Icons.person)),
            ),
            TextField(
              //隐藏正在编辑的文本
              obscureText: true,
              decoration: InputDecoration(
                  labelText: "密码",
                  hintText: "您的登录密码",
                  prefixIcon: Icon(Icons.lock)),
            ),
          ],
        ),
      ),
    );
  }
}

这个效果非常的“系统”,我们可能大多数情况下需要将下划线更换为矩形边框,这时候可能就需要组合widget来完成:

//容器 设置一个控件的尺寸、背景、margin 
Container(
    margin: EdgeInsets.all(32),
    child: TextField(
        keyboardType: TextInputType.emailAddress,
        decoration: InputDecoration(
            labelText: "用户名",
            hintText: "用户名或邮箱",
            prefixIcon: Icon(Icons.person),
            border: InputBorder.none //隐藏下划线
            )),
    //装饰
    decoration: BoxDecoration(
      // 边框浅灰色,宽度1像素
      border: Border.all(color: Colors.red[200], width: 1.0),
      //圆角
      borderRadius: BorderRadius.circular(5.0),
    ),
  )

焦点控制

​ FocusNode: 与Widget绑定,代表了这个Widget的焦点

​ FocusScope: 焦点控制范围

​ FocusScopeNode:控制焦点

class _TextFocusState extends State<TextFocusWidget> {
  FocusNode focusNode1 = new FocusNode();
  FocusNode focusNode2 = new FocusNode();

  void _listener() {
    debugPrint("用户名输入框焦点:${focusNode1.hasFocus}");
  }

  
  void initState() {
    super.initState();
    //监听焦点状态改变事件
    focusNode1.addListener(_listener);
  }

  
  void dispose() {
    super.dispose();
    focusNode1.dispose();
    focusNode2.dispose();
  }

  
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TextField(
          autofocus: true,
          //关联焦点
          focusNode: focusNode1,
          //设置键盘动作为: 下一步
          textInputAction: TextInputAction.next,
          //点击下一步执行回调
          onEditingComplete: () {
            //获得 context对应UI树的焦点范围 的焦点控制器
            FocusScopeNode focusScopeNode = FocusScope.of(context);
            //将焦点交给focusNode2
            focusScopeNode.requestFocus(focusNode2);
          },
          decoration: InputDecoration(
              labelText: "用户名",
              hintText: "用户名或邮箱",
              prefixIcon: Icon(Icons.person)),
        ),
        TextField(
          //隐藏正在编辑的文本
          obscureText: true,
          focusNode: focusNode2,
          decoration: InputDecoration(
              labelText: "密码",
              hintText: "您的登录密码",
              prefixIcon: Icon(Icons.lock)),
        ),
        custom(),
      ],
    );
  }
}

获取输入内容

获取输入内容有两种方式:

  1. 定义两个变量,用于保存用户名和密码,然后在onChange触发时,各自保存一下输入内容。
  2. 通过controller直接获取。

onChange获得输入内容:

TextField(
      onChanged: (s) => debugPrint("ssss:$s"),
    )

controller获取:

定义一个controller:

//定义一个controller
TextEditingController _unameController=new TextEditingController();

然后设置输入框controller:

TextField(
    controller: _unameController, //设置controller
    ...
)

通过controller获取输入框内容

debugPrint(_unameController.text)

TextFormField

TextFormFieldTextField多了一些属性,其中 validator用于设置验证回调。在单独使用时与TextField没有太大的区别。当结合From,利用From可以对输入框进行分组,然后进行一些统一操作(验证)

class _TextFocusState extends State<TextFocusWidget> {
  //全局key
  GlobalKey<FormState> _key = GlobalKey<FormState>();

  
  Widget build(BuildContext context) {
    return Form(
        //类似 id
        key: _key,
        child: Column(
          children: <Widget>[
            TextFormField(
                autofocus: true,
                decoration: InputDecoration(
                    labelText: "用户名",
                    hintText: "用户名或邮箱",
                    icon: Icon(Icons.person)),
                // 校验用户名
                validator: (v) {
                  return v.trim().length > 0 ? null : "用户名不能为空";
                }),
            TextFormField(
                decoration: InputDecoration(
                    labelText: "密码",
                    hintText: "您的登录密码",
                    icon: Icon(Icons.lock)),
                // 校验用户名
                validator: (v) {
                  return v.trim().length > 0 ? null : "密码不能为空";
                }),
            RaisedButton(
              onPressed: () {
                //Form所有TextFormField成功 返回true
                if (_key.currentState.validate()) {
                  
                }
              },
              child: Text("提交"),
            )
          ],
        ));
  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

抖音账号矩阵系统开发源码

一、技术自研框架开发背景&#xff1a; 抖音账号矩阵系统是一种基于数据分析和管理的全新平台&#xff0c;能够帮助用户更好地管理、扩展和营销抖音账号。 部分源码分享&#xff1a; ic function indexAction() { //面包屑 $breadcrumbs [ [tit…

【雕爷学编程】MicroPython动手做(13)——掌控板之RGB三色灯2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

Java另一种debug方法(not remote jmv debug),类似python远程debug方式

这种Debug类似python的debug方式&#xff0c;是运行时将业务代码及依赖推送到Linux并使用Linux的java运行运行程。只要本地能运行&#xff0c;就能自动将代码推送到Linux运行&#xff0c;不需打包及设置远程debug jvm参数&#xff0c;适合一些项目Debug调试 运行时会推送一些依…

67. 二进制求和

题目链接&#xff1a;力扣 解题思路&#xff1a;模拟十进制中的列竖式方法进行计算&#xff0c;逢二进一&#xff0c;因为高位在前&#xff0c;低位在后&#xff0c;两个二进制长度不一定相等&#xff0c;可以取两者长度的较大值&#xff0c;从后面开始遍历两个字符串&#xff…

【算法基础:动态规划】5.3 计数类DP(整数拆分、分拆数)

文章目录 例题&#xff1a;900. 整数划分解法1——完全背包解法2——分拆数⭐⭐⭐ 例题&#xff1a;900. 整数划分 https://www.acwing.com/problem/content/902/ 解法1——完全背包 容量是 n&#xff0c;物品的大小和价值是 1 ~ n 中的所有数字。 import java.util.*;pub…

Echarts 文字太长用省略号代替

xAxis: [{type: category,data: [materialUserEchartsDate.value[0] ? materialUserEchartsDate.value[0].name : ,materialUserEchartsDate.value[1] ? materialUserEchartsDate.value[1].name : ,materialUserEchartsDate.value[2] ? materialUserEchartsDate.value[2].na…

RabbitMQ 集群部署

RabbiMQ 是用 Erlang 开发的,集群非常方便,因为 Erlang 天生就是一门分布式语言,但其本身并不支持负载均衡。 RabbitMQ 的集群节点包括内存节点、磁盘节点。RabbitMQ 支持消息的持久化,也就是数据写在磁盘上,最合适的方案就是既有内存节点,又有磁盘节点。 RabbitMQ 模式大…

Kibana+Prometheus+node_exporter 监控告警部署

下载好三个软件包 一、prometheus安装部署 1、解压 linxxubuntu:~/module$ tar -xvf prometheus-2.45.0-rc.0.linux-amd64.tar.gz 2、修改配置文件的IP地址 # my global config global:scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is ever…

Eclipse memory analyzer 分析GC dump日志定位代码问题

1、问题描述&#xff1a; 使用命令 jstat -gcutil [pid] 查看JVM GC日志&#xff0c;发现生产系统频繁FullGC&#xff0c;大概几分钟一次&#xff0c;而且系统响应速度变慢很多 再使用 free -g 查看服务器内存全部占用&#xff0c;猜测是内存溢出了 2、导出dump日志 jmap -du…

修改整数(有点坑,所以发出来了)

问题描述 小贝给了小聪一个正整数 x&#xff0c;但是小聪决定把这个数改掉。她可以把整数 x 每个位置上的数 t 改成 9-t。 请你帮助小聪来计算一下&#xff0c;如何把 x 改成一个最小的正整数&#xff0c;注意&#xff0c;不能出现首位为 0 的情况。 输入格式 输入一个正整数…

Flowable-中间事件-消息中间抛出事件

定义 消息中间事件指在流程中将一个消息事件作为独立的节点来运行。它是一种抛出事件&#xff0c;当流程 执行到消息中间事件时就会中断在这里&#xff0c;一直等待被触发&#xff0c;直接到该事件接收到相应的消息后&#xff0c;流 程沿后继路线继续执行。消息事件是一种引用…

6门新兴语言,小众亦强大

编码语言在塑造我们创建软件的方式方面起着至关重要的作用。多年来&#xff0c;我们观察到Python&#xff0c;Java和C等成熟语言的流行。然而&#xff0c;如今一波新的编码语言浪潮已经出现&#xff0c;提出了创造性的解决方案&#xff0c;并推动了软件工程领域所能完成的极限。…

Redis学习路线(6)—— Redis的分布式锁

一、分布式锁的模型 &#xff08;一&#xff09;悲观锁&#xff1a; 认为线程安全问题一定会发生&#xff0c;因此在操作数据之前先获取锁&#xff0c;确保线程串行执行。例如Synchronized、Lock都属于悲观锁。 优点&#xff1a; 简单粗暴缺点&#xff1a; 性能略低 &#x…

如何在3ds max中创建可用于真人场景的巨型机器人:第 5 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. After Effects 中的项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 我有真人版 我在After Effects中导入的素材。这是将 用作与机器人动画合成的背景素材。 实景镜头 步骤 3 有背景 选定的素材…

MybatisPlus拓展篇

文章目录 逻辑删除通用枚举字段类型处理器自动填充功能防全表更新与删除插件MybatisX快速开发插件插件安装逆向工程常见需求代码生成 乐观锁问题引入乐观锁的使用效果测试 代码生成器执行SQL分析打印多数据源 逻辑删除 逻辑删除的操作就是增加一个字段表示这个数据的状态&…

uni-app点击按钮弹出提示框(以弹窗的形式显示),选择确定和取消

学习目标&#xff1a; 学习目标如下所示&#xff1a; uni-app点击提交按钮后弹出提示框&#xff0c;&#xff08;以弹窗的形式显示&#xff09;,提示用户是否确认提交&#xff08;即确定和取消&#xff09;&#xff0c;点击确定后调用真正的提交方法&#xff0c;将数据传给后端…

【基于矢量射线的衍射积分 (VRBDI)】基于矢量射线的衍射积分 (VRBDI) 和仿真工具(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

文心一言大数据模型-文心千帆大模型平台

官网&#xff1a; 文心千帆大模型平台 (baidu.com) 文心千帆大模型 (baidu.com) 模型优势 1、模型效果优&#xff1a;所需标注数据少&#xff0c;在各场景上的效果处于业界领先水平 2、生成能力强&#xff1a;拥有丰富的AI内容生成&#xff08;AIGC&#xff09;能力 3、应用…

Flink CEP(二) 运行源码解析

通过DemoApp学习一下&#xff0c;CEP的源码执行逻辑。为下一篇实现CEP动态Pattern奠定理论基础。 1. Pattern的定义 Pattern<Tuple3<String, Long, String>,?> pattern Pattern.<Tuple3<String, Long, String>>begin("begin").where(new…

详解python中的垃圾回收机制

目录 什么是垃圾回收机制 垃圾回收的工作流程 为什么要进行垃圾回收 详解python中的垃圾回收机制 总结 什么是垃圾回收机制 垃圾回收&#xff08;Garbage Collection&#xff09;是一种自动内存管理机制&#xff0c;用于检测和释放不再被程序使用的内存资源&#xff0c;以…