Android全新UI框架之常用ComposeUI组件

在Compose中,每个组件都是一个带有@Composable注解的函数,被称为Composable。Compose已经预置了很多基于MD设计规范的Composable组件。
在布局方面,Compose提供了Column、Row、Box三种布局组件(感觉跟flutter差不多),类似于传统视图开发中的LinearLayout(Vertical)、LinearLayout(Horizontal)、RelateiveLayout,可以满足各类产品的常见布局需求。

Modifier修饰符

在传统开发中,使用xml文件来描述组件的样式,而compose则是使用Modifier修饰符。Modifier允许我们通过链式调用的方式为组件应用一系列的样式设置,如边距、字体、位移等。在Compose中,每个基础的Composable组件都有一个modifier参数,通过传入自定义的Modifier来修改组件的样式。

  • 常见修饰符

    Modifier.size设置被修饰组件的大小 Image( painter = painterResource(id = R.drawable.ic_launcher),contentDescription = null, modifier = Modifier.size(width = 10.dp, height = 10.dp) )
    Modifier.background设置被修饰组件的背景颜色。背景色支持纯色背景,也可以使用brush设置渐变背景Image(painter = painterResource(id = R.drawable.ic_launcher),contentDescription = null,modifier = Modifier.size(width = 100.dp, height = 100.dp).background(brush = Brush.verticalGradient(colors = listOf(Color.Blue,Color.Red)))))
    Modifier.fillMaxXXX()让组件在高度或者宽度上填满父空间fillMaxSize():填满整个父空间, fillMaxHeight():高度填满父空间,fillMaxWidth():宽度填满父空间
    Modifier.border&Modifier.paddingborder用来为被修饰组件添加边框。边框可以指定颜色、粗细、以及通过shape指定形状。padding用来为被修饰组件增加间隙。可以在border前后各插入一个padding,区分对外和对内的间距 Box(modifier = Modifier.padding(5.dp).border(2.dp, Color.Green, shape = RoundedCornerShape(2.dp)).padding(5.dp)) { Spacer(modifier = Modifier.size(width = 100.dp, height = 10.dp).background(Color.Blue)) }
    Modifier.offset用来移动被修饰组件的位置,分别传入水平方向和垂直方向的偏移量即可 Box(modifier = Modifier.size(100.dp).background(Color.Blue).offset(x = 10.dp, y = 10.dp).background(Color.Cyan)) {}
  • 作用域限定Modifier修饰符
    Compose充分发挥kotlin的语法特性,让某些Modifier修饰符只能在特定作用域中使用,有利于类型安全地调用它们。所谓“作用域”,在kotlin中就是一个带有Receiver的代码块。注意Receiver代码块默认可以跨层级访问。在compose的DSL中,一般只需要调用当前作用域的方法,为此可以通过@LayoutScopeMarker注解来规避该问题。常见组件的Receiver作用域类型均已使用@LayoutScopeMarker注解进行了声明,使用了该注解之后,像跨级调用外层作用域的方法必须通过显式指明Receiver具体类型。

    @LayoutScopeMarker
    @Immutable
    interface ColumnScope
    

    常见的作用域限定Modifier修饰符:

    1. matchParentSize
      matchParentSize是只能在BoxScope中使用的作用域限定修饰符。当使用matchParentSize设置尺寸时,可以保证当前组件的尺寸与父组件相同。而父组件默认的是wrapContent。如果使用fillMaxSize取代matchParentSize,那么该组件的尺寸会被设置为父组件所允许的最大尺寸,这样会导致背景铺满整个屏幕,二者区别如下图所示。

          Column(modifier = Modifier.background(Color.DarkGray)) {Box() {Box(modifier = Modifier
      //                .fillMaxSize().matchParentSize().background(Color.Cyan))Spacer(modifier = Modifier.size(50.dp).padding(10.dp).background(Color.Red))}}
      

      matchParentSize效果如下所示:
      在这里插入图片描述
      fillMaxSize效果如下所示:在这里插入图片描述

    2. weight
      在RowScope和ColumnScope中,可以使用专属的weight修饰符来设置尺寸。与size不同的是weight允许组件通过百分比设置尺寸,也就是允许组件可以自适应适配各种屏幕尺寸的移动端设备。

          Column(modifier = Modifier.background(Color.DarkGray).width(300.dp).height(200.dp)) {Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.White))Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.Red))Spacer(modifier = Modifier.fillMaxWidth().weight(1f).background(Color.Blue))}
      
  • Modifier实现原理
    各位读者可以参考下面这篇博客:
    图解Compose Modifier实现原理 ,竟然如此简单!

常用的基础组件

文字组件
  1. Text文本
    在Compose中,Text是遵循MD设计规范的上层文本组件,如果想脱离MD,也可以直接使用更底层的文本组件BasicText。
    @Composable
    fun Text(text: String,modifier: Modifier = Modifier,color: Color = Color.Unspecified,fontSize: TextUnit = TextUnit.Unspecified,fontStyle: FontStyle? = null,fontWeight: FontWeight? = null,fontFamily: FontFamily? = null,letterSpacing: TextUnit = TextUnit.Unspecified,textDecoration: TextDecoration? = null,textAlign: TextAlign? = null,lineHeight: TextUnit = TextUnit.Unspecified,overflow: TextOverflow = TextOverflow.Clip,softWrap: Boolean = true,maxLines: Int = Int.MAX_VALUE,onTextLayout: (TextLayoutResult) -> Unit = {},style: TextStyle = LocalTextStyle.current
    )
    
    在很多应用场景中,我们需要在一段文字中对局部内容应用特别格式以示突出,比如一个超链接,此时需要用到AnnotatedString。AnnotatedString是一个数据类,除了文本值,还包含一个SpanStyle和ParagraphStyle的Range列表。SpanStyle用于描述在文本中子串的文字样式,ParagraphStyle则用于描述文本中子串的段落样式,Range确定子串的范围。
    用法如下所示:
    //append用来添加子串的文本
    //withStyle为append的子串指定文字或段落样式
    Text(text = buildAnnotatedString {withStyle(style = SpanStyle(fontSize = 24.sp)){append("你现在学习的章节是")}withStyle(style = SpanStyle(fontSize = 24.sp, fontWeight = FontWeight.W900)){append("Text")}append("\n")withStyle(style = ParagraphStyle(lineHeight = 25.sp)){append("在刚刚讲过的内容中,我们学会了如何应用文字样式,以及如何限制文本的行数和处理溢出的视觉效果。")append("\n")append("现在,我们正在学习")withStyle(style = SpanStyle(fontWeight = FontWeight.W900, textDecoration = TextDecoration.Underline, color = Color(0xff59a869))){append("AnnotatedString")}}})
    
    SpanStyle继承了TextStyle中关于文字样式相关的字段,而ParagraphStyle继承了TextStyle中控制段落的样式,例如textAlign、lineHeight等。SpanStyle和ParagraphStyle中的设置优先于TextStyle中同名属性设置。
  • SelectionContainer选中文字
    Text自身默认是不能被长按选择的,Compose提供了专门的SelectionContainer组件,对包裹的Text进行选中。

    SelectionContainer() {Text(text = "我是可以被复制的文字")
    }
    
  • ClickableText
    Compose提供了一种可点击文本组件,可以响应对文字的点击,并返回点击位置。可以让AnnotatedString子串在相应的ClickedText中点击后,做出不同的动作。在AnnotatedString中可以为子串添加一个tag标签,在处理onClick事件时,根据tag实现不同的逻辑。

     ClickableText(text = annotated, onClick ={annotated.getStringAnnotations(tag = "URL",start = it,end = it).firstOrNull()?.let {Log.e("MainActivity",it.toString())}} )val annotated = buildAnnotatedString {withStyle(style = ParagraphStyle(lineHeight = 25.sp)){// 开始一个注解区域pushStringAnnotation(tag = "URL", annotation = "https://www.baidu.com")// 追加带有注解的文本withStyle(style = SpanStyle(fontWeight = FontWeight.W900,textDecoration = TextDecoration.Underline,color = Color(0xff59a869))){append("AnnotatedString")}// 结束注解区域pop()//下面这段文本不会有注解withStyle(style = SpanStyle(fontWeight = FontWeight.W900,textDecoration = TextDecoration.Underline,color = Color(0xff59a869))){append("NotAnnotatedString")}}}
    
  • TextField输入框
    TextField组件是我们最常用的文本输入框,它也遵循MD设计准则。它也有一个低级别的底层组件,BasicTextField,与TextField和OutlinedTextField不同的是,BasicTextField拥有更多的自定义效果。由于TextField和OutlinedTextField是根据MD准则设计的,无法直接修改输入框的高度,如果尝试修改高度,会看到输入区域被截断,影响正常输入。

    fun TextField(value: TextFieldValue,onValueChange: (TextFieldValue) -> Unit,modifier: Modifier = Modifier,enabled: Boolean = true,readOnly: Boolean = false,textStyle: TextStyle = LocalTextStyle.current,label: @Composable (() -> Unit)? = null,placeholder: @Composable (() -> Unit)? = null,leadingIcon: @Composable (() -> Unit)? = null,trailingIcon: @Composable (() -> Unit)? = null,supportingText: @Composable (() -> Unit)? = null,isError: Boolean = false,visualTransformation: VisualTransformation = VisualTransformation.None,keyboardOptions: KeyboardOptions = KeyboardOptions.Default,keyboardActions: KeyboardActions = KeyboardActions.Default,singleLine: Boolean = false,maxLines: Int = Int.MAX_VALUE,interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },shape: Shape = TextFieldDefaults.filledShape,colors: TextFieldColors = TextFieldDefaults.textFieldColors()
    )
    fun BasicTextField(value: String,onValueChange: (String) -> Unit,modifier: Modifier = Modifier,enabled: Boolean = true,readOnly: Boolean = false,textStyle: TextStyle = TextStyle.Default,keyboardOptions: KeyboardOptions = KeyboardOptions.Default,keyboardActions: KeyboardActions = KeyboardActions.Default,singleLine: Boolean = false,maxLines: Int = Int.MAX_VALUE,visualTransformation: VisualTransformation = VisualTransformation.None,onTextLayout: (TextLayoutResult) -> Unit = {},interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },cursorBrush: Brush = SolidColor(Color.Black),decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =@Composable { innerTextField -> innerTextField() }
    ) 
    

    TextField输入框案例如下:

    @Composablefun TextFieldSample(){var text by remember {mutableStateOf("")}Box(modifier = Modifier.fillMaxSize().background(Color(0xfd3d3d3)),contentAlignment = Alignment.Center) {BasicTextField(modifier = Modifier.padding(10.dp).background(Color.White, CircleShape).height(30.dp).fillMaxSize(),value = text,onValueChange = {text = it},decorationBox = {Row(verticalAlignment = Alignment.CenterVertically,modifier = Modifier.padding(vertical = 2.dp, horizontal = 8.dp)) {Icon(imageVector = Icons.Filled.Search, contentDescription = null)Box(modifier = Modifier.padding(horizontal = 10.dp).width(100.dp), contentAlignment = Alignment.CenterStart) {if(text.isEmpty()){Text(text = "输入点东西看看吧~",style = TextStyle(color = Color(0,0,0,128)))}it()}Box(contentAlignment = Alignment.CenterEnd){if(text.isNotEmpty()){IconButton(onClick = { text="" },modifier = Modifier.size(16.dp)) {Icon(imageVector = Icons.Filled.Close, contentDescription = null, tint = Color.Red)}}}}})}}
    
  • 图片组件

    1. Icon图标
      Icon组件用于显示一系列小图标。Icon组件支持三种不同类型的图片设置:
    @Composable
    fun Icon(imageVector: ImageVector,//矢量图对象,可以显示SVG格式的图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current
    )
    @Composable
    fun Icon(bitmap: ImageBitmap,//位图对象,可以显示JPG、PNG等格式的图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current
    )
    @Composable
    fun Icon(painter: Painter,//代表一个自定义画笔,可以使用画笔在Canvas上直接绘制图标contentDescription: String?,modifier: Modifier = Modifier,tint: Color = LocalContentColor.current
    )
    
    1. Image图片
      Image组件用来显示一张图片。它和Icon一样也支持三种类型的图片设置。
  • 按钮组件

    1. Button按钮
      Button也是最常用的组件之一,它也是按照MD风格来实现的。Button并非唯一可点击组件,理论上任何Composable组件都可以通过Modifier.clickable修饰符化身为可点击组件。
      案例如下:
        @Composablefun ButtonSample(){val interactionSource = remember {MutableInteractionSource()}val pressState = interactionSource.collectIsPressedAsState()val borderColor = if (pressState.value) Color.Green else Color.WhiteButton(modifier = Modifier.clickable {//该方法在button组件会失效Log.e("MainActivity","点击Butttonclickable")},interactionSource = interactionSource,border = BorderStroke(2.dp, color = borderColor),onClick = {Log.e("MainActivity","点击Buttton")}) {Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))Text(text = "确认")}}
    
    1. IconButton图标按钮
      IconButton组件实际上只是Button组件的简单封装(一个可点击的图标),它一般用于应用栏中的导航或者其他行为。一般来说,需要在IconButton组件里提供一个图标组件,这个图标的默认尺寸一般为24*24dp。
     IconButton(onClick = { text="" },modifier = Modifier.size(16.dp)) {Icon(imageVector = Icons.Filled.Close, contentDescription = null, tint = Color.Red)
    
    1. FloatingActionButton悬浮按钮
        @Composablefun FloatButton(){FloatingActionButton(onClick = {}) {Row() {Text(text = "添加到我的喜欢")Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))}}ExtendedFloatingActionButton(onClick = { /*TODO*/ }) {Row() {Text(text = "添加到我的喜欢")Icon(imageVector = Icons.Filled.Done, contentDescription = null, modifier = Modifier.size(ButtonDefaults.IconSize))}}}
    
  • 选择器

    1. CheckBox复选框
        @Composablefun ChecBoxDemo(){val checkedState = remember {mutableStateOf(true)}Checkbox(checked = checkedState.value,onCheckedChange ={checkedState.value = it},colors = CheckboxDefaults.colors(checkedColor =  Color(0xff0079d3)))}
    
    1. TriStateCheckBox三态选择框
      很多时候,我们的复选框会有很多个,并且希望能够统一选择或者取消,这个时候就可以使用三态选择框
     @Composablefun ChecBoxDemo(){val (state,onStateChange) = remember { mutableStateOf(true) }val (state2,onStateChange2) = remember { mutableStateOf(true) }val parentState = remember(state,state2) {if (state&&state2) ToggleableState.Onelse if (!state&&!state2) ToggleableState.Offelse ToggleableState.Indeterminate}val onParentClick = {val s = parentState != ToggleableState.OnonStateChange(s)onStateChange2(s)}TriStateCheckbox(colors = CheckboxDefaults.colors(checkedColor = Color.Red),state = parentState,onClick = onParentClick,)Column(Modifier.padding(10.dp,0.dp,0.dp,0.dp)) {Checkbox(checked = state, onCheckedChange = onStateChange )Checkbox(checked = state2, onCheckedChange = onStateChange2 )}}
    
    1. Switch单选开关——控制单个项目的开启或关闭状态
      @Composablefun ChecBoxDemo(){val checkedState = remember {mutableStateOf(true)}Switch(checked = checkedState.value, onCheckedChange = {checkedState.value = it})}
    
    1. Slider滑竿组件——可用来做音量、亮度之类的数值调整或进度条
     var sliderPosition by remember {mutableStateOf(0f)}Slider(value = sliderPosition, onValueChange = {sliderPosition = it})
    
    1. 进度条
      var progress by remember {mutableStateOf(0.1f)}val animatedProgress by animateFloatAsState(targetValue = progress, animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec)Column {CircularProgressIndicator(progress = animatedProgress)Spacer(modifier = Modifier.requiredHeight(30.dp))OutlinedButton(onClick = {if(progress<1f)progress +=.1f}) {Text(text = "增加进度")}}
    
    1. 对话框
        @Composablefun DialogDemo(){val openDialog = remember {mutableStateOf(true)}val dialogWidth = 200.dpval dialogHeight = 50.dpif(openDialog.value){Dialog(onDismissRequest = { openDialog.value = false },properties = DialogProperties(dismissOnBackPress = true,//允许通过点击物理返回键取消对话框dismissOnClickOutside = true//允许点击对话框外部取消对话框)) {Box(modifier = Modifier.size(dialogWidth, dialogHeight).background(Color.Blue))}}}
    

常用的布局组件

  • 线性布局
    线性布局对应于传统视图中的linearLayout,Compose根据orientation的不同又分为Column和Row。

    1. Column
      Column是一个垂直线性布局组件,它能够将子项按照从上到下的顺序垂直排列。verticalArrangement和horizontalAlignment参数分别可以帮助我们安排子项的垂直/水平位置,在默认的情况下,子项会以垂直方向上靠上,水平方向上靠左来布置。
    2. Row
      Row组件能够将内部子项按照从左到右的方向水平排列。用法Column类似。
  • 帧布局

    1. Box
      Box组件是一个能够将里面的子项依次按照顺序堆叠的布局组件,在使用上类似于传统视图中的Framelayout。
    2. Surface
      Surface是一个平面,在MD设计准则中也同样如此,我们可以将很多的组件摆放在这个平面之上,可以设置这个平面的边框、圆角、颜色等。
  • Spacer留白
    在很多时候,需要让两个组件之间留有空白的间隔,这个时候就可以使用该组件。其实当Box组件没有content时,完全可以用Spacer替换。可以给Spacer做如下封装,可以更方便地用在水平或垂直布局中。

        @Composablefun WidthSpacer(value:Dp){Spacer(modifier = Modifier.width(value))}@Composablefun HeightSpacer(value:Dp){Spacer(modifier = Modifier.height(value))}
    
  • ConstraintLayout约束布局
    各位读者可以参考下面这篇博客:
    Compose ConstraintLayout 详讲

  • Scaffold脚手架
    Scaffold组件实现了MD的布局结构,通过配合其他MD组件可以轻松构建MD风格的页面。

        @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")@OptIn(ExperimentalMaterial3Api::class)@Composablefun Sample(){var selectedItem by remember {mutableStateOf(0)}val items = listOf(Item("主页",R.drawable.ic_launcher),Item("列表",R.drawable.ic_launcher),Item("设置",R.drawable.ic_launcher),)Scaffold(topBar ={TopAppBar(title = { Text(text = "主页")},navigationIcon = {IconButton(onClick = { /*TODO*/ }) {Icon(imageVector = Icons.Filled.Menu, contentDescription = null)}})}){Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center){Text(text = "主页面")}}}
    

列表

很多产品中都有展示一组数据的需求场景,如果数据数量是可以枚举的,则仅需通过Column组件来枚举列出。然而很多时候,列表中的项目会非常多,我们需要滑动列表来查看所有内容,可以通过给Column的modifier添加verticalScroll方法来让列表实现滑动。

    @Composablefun ListDemo(){val initialCapacity = 1000 // 设置你想要的初始容量val items = ArrayList<String>(initialCapacity)for (i in 1..initialCapacity) {items.add("我是text$i")}Column(modifier = Modifier.verticalScroll(state = ScrollState(5), enabled = true)) {items.forEach{Text(text = "$it")}}}

给Column的Modifier添加verticalScroll方法可以让列表实现滑动。但是如果列表过长,众多的内容会占用大量的内存。然而更多的内容对于用户其实都是不可见的,没有必要加载到内存。所以compose提供了专门用于处理长列表的组件,LazyColumn和LazyRow,其作用类似于传统视图中的Listview和RecyclerView。

  LazyColumn(modifier = Modifier.fillMaxSize().background(Color.Cyan),contentPadding = PaddingValues(30.dp),//为内容设置外边距verticalArrangement = Arrangement.spacedBy(10.dp)//为每个item设置间隔) {items(1000){Text(text = "$it")}}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

几个常见的C/C++语言冷知识

当涉及到C/C语言时&#xff0c;有一些冷知识可能并不为人所熟知&#xff0c;但却可以让你更深入地理解这门古老而强大的编程语言。以下是一些有趣的C/C语言冷知识。 1. 数组的下标可以是负数 在我们日常的C语言编程中&#xff0c;数组是一个非常常见的数据结构。我们习惯性地使…

Flutter学习4 - Dart数据类型

1、基本数据类型 num、int、double &#xff08;1&#xff09;常用数据类型 num类型&#xff0c;是数字类型的父类型&#xff0c;有两个子类 int 和 double 通过在函数名前加下划线&#xff0c;可以将函数变成私有函数&#xff0c;私有函数只能在当前文件中调用 //常用数据…

干货分享 | TSMaster 序列发送模块在汽车开发测试中的应用

众所周知&#xff0c;序列发送模块可以不需要脚本代码实现测试中特定控制报文序列的发送&#xff0c;该模块多用于循环顺序控制的测试案例中。序列发送模块的常用场景&#xff0c;主要是针对一些新开发的产品需要通过该模块来验证产品功能等等。本文重点和大家分享一下关于TSMa…

防御保护——内容安全笔记

双机热备配置 1&#xff0c;根据网段划分配置IP地址和安全区域 2&#xff0c;配置双机热备场景 主备场景配置 抢占延时仅对主设备生效。 hello报文周期时间--- 默认为1S&#xff0c;可以修改&#xff0c;但是&#xff0c;主备设备需要同时修改为相同值。 配置VRRP虚拟IP地址时&…

苹果iPad通过Code APP应用实现SSH连接服务器远程进行开发

文章目录 1. 在iPad下载Code APP2.安装cpolar内网穿透2.1 cpolar 安装2.2 创建TCP隧道 3. iPad远程vscode4. 配置固定TCP端口地址4.1 保留固定TCP地址4.2 配置固定的TCP端口地址4.3 使用固定TCP地址远程vscode 本文主要介绍开源iPad应用IDE Code App 如何下载安装&#xff0c;并…

C语言第二十八弹---整数在内存中的存储

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 目录 1、整数在内存中的存储 2、大小端字节序和字节序 2.1、什么是大小端&#xff1f; 2.2、为什么有大小端? 2.3、练习 2.3.1、练习1 2.3.2、练习2 2.…

性能全面提升!探索ONLYOFFICE最新8.0版:更快速、更强大,PDF表单编辑轻松搞定!

文章目录 PDF表单功能表单模板 屏幕朗读器功能EXCEL新增功能单变量求解图表向导数字排序 PPT 新增功能新增语言区域设置和优化插件界面 ONLYOFFICE 是由 Ascensio System SIA 推出的一款功能强大的办公套件&#xff0c;其中提供了适用于文本文档、表格以及演示文稿的在线编辑软…

2024 全国水科技大会暨第二届智慧水环境管理与技术创新论坛

论坛二&#xff1a;第二届智慧水环境管理与技术创新论坛 召集人&#xff1a;刘炳义 武汉大学智慧水业研究所所长、教授 为贯彻落实中共中央国务院印发《数字中国建设整体布局规划》和国务院关于印发《“十四五”数字经济发展规划》的通知&#xff0c;推动生态环境智慧治理&…

Spring Boot打war包部署到Tomcat,访问页面404 !!!

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 文章目录 Spring Boot打war包部署到Tomcat&#xff0c;访问页面404 &#xff01;&#xff01;&#xff01;解决办法&#xff1a;检查Tomcat版本和Jdk的对应关系&#xff0c;我的Tomcat是6.x&#x…

3DSC特征描述符、对应关系可视化以及ICP配准

一、3DSC特征描述符可视化 C #include <pcl/point_types.h> #include <pcl/point_cloud.h> #include <pcl/search/kdtree.h> #include <pcl/io/pcd_io.h> #include <pcl/features/normal_3d_omp.h>//使用OMP需要添加的头文件 #include <pcl…

FPGA领域顶级学术会议

FPGA领域顶级学术会议主要有FPGA,FCCM,FPL和FPT。 1 FPGA 会议全名是: ACM/SIGDA International Symposium on Field-Programmable Gate Arrays 网站是:https://dl.acm.org/conference/fpga FPGA常年在美国举办,每年2月,偏FPGA基础研究; 该会议的论文免费下载。这个比…

(十三)【Jmeter】线程(Threads(Users))之tearDown 线程组

简述 操作路径如下: 作用:在正式测试结束后执行清理操作,如关闭连接、释放资源等。配置:设置清理操作的采样器、执行顺序等参数。使用场景:确保在测试结束后应用程序恢复到正常状态,避免资源泄漏或对其他测试的影响。优点:提供清理操作,确保测试环境的整洁和可重复性…

jvm、jre、jdk的关系

jvm Java 虚拟机&#xff08;JVM&#xff09;是运行 Java 字节码的虚拟机。 jre JRE&#xff08;Java Runtime Environment&#xff09; 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合&#xff0c;主要包括 Java 虚拟机&#xff08;JVM&#xff09;、J…

C++笔记:OOP三大特性之继承

文章目录 一、继承的概念和定义1.1 概念1.2 定义格式1.3 继承关系和访问限定符 二、基类和派生类对象赋值兼容转换2.1 类型转换存在临时对象的意义2.2 赋值兼容转换不会产生临时变量 三、继承中的作用域四、派生类中的默认成员函数4.1 构造4.2 拷贝构造4.3 赋值重载4.4 析构 五…

【Java多线程】分析线程加锁导致的死锁问题以及解决方案

目录 1、线程加锁 2、死锁问题的三种经典场景 2.1、一个线程一把锁 2.2、两个线程两把锁 2.3、N个线程M把锁&#xff08;哲学家就餐问题&#xff09; 3、解决死锁问题 1、线程加锁 其中 locker 可以是任意对象&#xff0c;进入 synchronized 修饰的代码块, 相当于加锁&…

OpenWRT部署web站点并结合内网穿透实现无公网ip远程访问

文章目录 前言1. 检查uhttpd安装2. 部署web站点3. 安装cpolar内网穿透4. 配置远程访问地址5. 配置固定远程地址 前言 uhttpd 是 OpenWrt/LuCI 开发者从零开始编写的 Web 服务器&#xff0c;目的是成为优秀稳定的、适合嵌入式设备的轻量级任务的 HTTP 服务器&#xff0c;并且和…

尝试一下最新的联合办公利器ONLYOffice

下载下来一起试试吧 桌面安装版下载地址&#xff1a;https://www.onlyoffice.com/zh/download-desktop.aspx) 官网地址&#xff1a;https://www.onlyoffice.com 普通Office对联合办公的局限性 普通Office软件&#xff08;如Microsoft Office、Google Docs等&#xff09;在面对…

Socket通信---Python发送数据给C++程序

0. Problems 很多时候实现某种功能&#xff0c;需要在不同进程间发送数据&#xff0c;目前有几种主流的方法&#xff0c;如 让python和C/C程序互相发送数据&#xff0c;其实有几种方法&#xff1a; 共享内存共享文件Socket通信 在这里只提供Socket通信的例程&#xff0c;共享…

MySQL学习笔记3: MySQL数据库基础

目录 前言目标数据库操作&#xff08;针对database 的操作&#xff09;1. 创建数据库 create database 数据库名;2. 查看数据库 show databases;3. 选中数据库 use 数据库名;4. 删除数据库 drop database 数据库名; mysql中支持的数据类型1. 数值类型: NUMERIC(M,D)2. 字符串类…

如何在OpenWRT安装内网穿透工具实现远程访问本地搭建的web网站界面

文章目录 前言1. 检查uhttpd安装2. 部署web站点3. 安装cpolar内网穿透4. 配置远程访问地址5. 配置固定远程地址 前言 uhttpd 是 OpenWrt/LuCI 开发者从零开始编写的 Web 服务器&#xff0c;目的是成为优秀稳定的、适合嵌入式设备的轻量级任务的 HTTP 服务器&#xff0c;并且和…